为多阶段构建自动删除悬空图像并同时支持缓存
Automatic removing of danging images and supporting cache at same time for multi-stage builds
我正在尝试设置一个 CI 构建,它从 Docker 包含多步配置的文件构建图像。
要求如下:
- 需要使用 Docker 层缓存,因为它会在
RUN
指令期间加载大量应用依赖项。
- 它应该会在每次构建后自动删除旧的悬挂图像。 (为了防止以后手动清理它
docker image prune
)
我的示例解决方案:
(只是为了演示这个问题)看起来像这样:
docker build -t sample-app.
docker rmi $(docker images --filter "dangling=true" -q --no-trunc)
Docker文件:
FROM ubuntu:18.04 AS builder
WORKDIR /app
COPY some-file-for-build.txt /app
RUN echo 'building...'
FROM ubuntu:18.04
CMD ["echo", "running..."]
问题:
由于删除了悬空图像,缓存变得无效并且 RUN
指令在每次构建期间执行。
单阶段配置的意外行为
但如果删除第 2 步,则将 Docker 文件更改为:
FROM ubuntu:18.04
WORKDIR /app
COPY some-file-for-build.txt /app
RUN echo 'building...'
缓存开始为 RUN
指令工作。
Step 4/4 : RUN echo 'building...'
---> Using cache
---> 9c7c15230600
问题:
- 有没有办法让它按要求工作?
- 为什么缓存适用于单级配置但不适用于多级配置?
您需要使用Docker 18.09 及以上版本,还需要设置环境变量DOCKER_BUILDKIT=1
。此环境变量允许使用 BuildKit 功能,这反过来又允许更高性能 docker 构建和缓存可能性以减少构建时间。您可以获得更多信息here
据我所知,使用 Docker >18.09
.
缓存可用于单级和多级配置
Docker文件:
FROM ubuntu:18.04 AS builder
WORKDIR /app
COPY some-file-for-build.txt /app
RUN echo 'building...'
FROM ubuntu:18.04
WORKDIR /app
COPY --from=builder /app/some-file-for-build.txt some-file-for-build-from-builder-stage.txt
CMD ["bash"]
这是我的 docker 构建和清理的日志:
> docker build --pull --rm -f "61977760.Dockerfile" -t 61977760:latest "."
[+] Building 4.7s (10/10) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from 61977760.Dockerfile 0.1s
=> => transferring dockerfile: 289B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:18.04 2.4s
=> [internal] load build context 0.0s
=> => transferring context: 44B 0.0s
=> [builder 1/4] FROM docker.io/library/ubuntu:18.04@sha256:3235326357dfb65f1781dbc4df3b834546d8bf914e82cce58e6e6b676e23ce8f 0.3s
=> => resolve docker.io/library/ubuntu:18.04@sha256:3235326357dfb65f1781dbc4df3b834546d8bf914e82cce58e6e6b676e23ce8f 0.0s
=> => sha256:3235326357dfb65f1781dbc4df3b834546d8bf914e82cce58e6e6b676e23ce8f 1.42kB / 1.42kB 0.0s
=> => sha256:b58746c8a89938b8c9f5b77de3b8cf1fe78210c696ab03a1442e235eea65d84f 1.15kB / 1.15kB 0.0s
=> => sha256:c3c304cb4f22ceb8a6fcc29a0cd6d3e4383ba9eb9b5fb552f87de7c0ba99edac 3.41kB / 3.41kB 0.0s
=> [builder 2/4] WORKDIR /app 0.0s
=> [builder 3/4] COPY some-file-for-build.txt /app 0.0s
=> [builder 4/4] RUN echo 'building...' 0.8s
=> [stage-1 3/3] COPY --from=builder /app/some-file-for-build.txt some-file-for-build-from-builder-stage.txt 0.0s
=> exporting to image 0.9s
=> => exporting layers 0.8s
=> => writing image sha256:94fd1e56c8044f0e2f80ee83c784cca5f2c384fd4eba9210f9ff81db68f406e5 0.0s
=> => naming to docker.io/library/61977760:latest 0.0s
> docker rmi $(docker images --filter "dangling=true" -q --no-trunc)
Deleted: sha256:4d157078805ccf08fd42502b19a665a0b60e80a33a7c5b6485e6fd201ca91cc1
Deleted: sha256:6f7f45cca948cf855afea76ff73878b8348da6ed2652d62b48f992f7d9768822
Deleted: sha256:eefe65e58b69e4567c5145828ec95d1d9f3477709cc76fb571e204920df8e378
> docker build --pull --rm -f "61977760.Dockerfile" -t 61977760:latest "."
[+] Building 0.9s (10/10) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from 61977760.Dockerfile 0.1s
=> => transferring dockerfile: 47B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:18.04 0.8s
=> [builder 1/4] FROM docker.io/library/ubuntu:18.04@sha256:3235326357dfb65f1781dbc4df3b834546d8bf914e82cce58e6e6b676e23ce8f 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 42B 0.0s
=> CACHED [builder 2/4] WORKDIR /app 0.0s
=> CACHED [builder 3/4] COPY some-file-for-build.txt /app 0.0s
=> CACHED [builder 4/4] RUN echo 'building...' 0.0s
=> CACHED [stage-1 3/3] COPY --from=builder /app/some-file-for-build.txt some-file-for-build-from-builder-stage.txt 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:94fd1e56c8044f0e2f80ee83c784cca5f2c384fd4eba9210f9ff81db68f406e5 0.0s
=> => naming to docker.io/library/61977760:latest 0.0s
> docker builder prune --all
WARNING! This will remove all build cache. Are you sure you want to continue? [y/N] y
Deleted build cache objects:
np9zknowpkgi9aa2qtfstthnr
l0lucvc40nl98ceqxqadjplaw
elj14uwncgbk928oawwalht9x
s4l0w4h3day53tc3w20njd9cm
t6br3zadzcqhwilswvhkc2qkv
q8wrflxp3sppgmrft0yv805l0
qbe59a3kgjdvaw4ng7d5rasc8
sha256:82751c4dcc36265daceeee0abd938806b591eb66700863186377348c96e8aead
sha256:24b16cac34768092d57cdb429a12de6c9ee870a3724d70098a189ae0ac344c42
sha256:b1daff3b271fede2bec31812c398e28952f792935f608e467271cdfaccab7de2
sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e
Total reclaimed space: 64.21MB
>
我正在尝试设置一个 CI 构建,它从 Docker 包含多步配置的文件构建图像。
要求如下:
- 需要使用 Docker 层缓存,因为它会在
RUN
指令期间加载大量应用依赖项。 - 它应该会在每次构建后自动删除旧的悬挂图像。 (为了防止以后手动清理它
docker image prune
)
我的示例解决方案:
(只是为了演示这个问题)看起来像这样:
docker build -t sample-app.
docker rmi $(docker images --filter "dangling=true" -q --no-trunc)
Docker文件:
FROM ubuntu:18.04 AS builder
WORKDIR /app
COPY some-file-for-build.txt /app
RUN echo 'building...'
FROM ubuntu:18.04
CMD ["echo", "running..."]
问题:
由于删除了悬空图像,缓存变得无效并且 RUN
指令在每次构建期间执行。
单阶段配置的意外行为
但如果删除第 2 步,则将 Docker 文件更改为:
FROM ubuntu:18.04
WORKDIR /app
COPY some-file-for-build.txt /app
RUN echo 'building...'
缓存开始为 RUN
指令工作。
Step 4/4 : RUN echo 'building...'
---> Using cache
---> 9c7c15230600
问题:
- 有没有办法让它按要求工作?
- 为什么缓存适用于单级配置但不适用于多级配置?
您需要使用Docker 18.09 及以上版本,还需要设置环境变量
DOCKER_BUILDKIT=1
。此环境变量允许使用 BuildKit 功能,这反过来又允许更高性能 docker 构建和缓存可能性以减少构建时间。您可以获得更多信息here据我所知,使用
Docker >18.09
. 缓存可用于单级和多级配置
Docker文件:
FROM ubuntu:18.04 AS builder
WORKDIR /app
COPY some-file-for-build.txt /app
RUN echo 'building...'
FROM ubuntu:18.04
WORKDIR /app
COPY --from=builder /app/some-file-for-build.txt some-file-for-build-from-builder-stage.txt
CMD ["bash"]
这是我的 docker 构建和清理的日志:
> docker build --pull --rm -f "61977760.Dockerfile" -t 61977760:latest "."
[+] Building 4.7s (10/10) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from 61977760.Dockerfile 0.1s
=> => transferring dockerfile: 289B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:18.04 2.4s
=> [internal] load build context 0.0s
=> => transferring context: 44B 0.0s
=> [builder 1/4] FROM docker.io/library/ubuntu:18.04@sha256:3235326357dfb65f1781dbc4df3b834546d8bf914e82cce58e6e6b676e23ce8f 0.3s
=> => resolve docker.io/library/ubuntu:18.04@sha256:3235326357dfb65f1781dbc4df3b834546d8bf914e82cce58e6e6b676e23ce8f 0.0s
=> => sha256:3235326357dfb65f1781dbc4df3b834546d8bf914e82cce58e6e6b676e23ce8f 1.42kB / 1.42kB 0.0s
=> => sha256:b58746c8a89938b8c9f5b77de3b8cf1fe78210c696ab03a1442e235eea65d84f 1.15kB / 1.15kB 0.0s
=> => sha256:c3c304cb4f22ceb8a6fcc29a0cd6d3e4383ba9eb9b5fb552f87de7c0ba99edac 3.41kB / 3.41kB 0.0s
=> [builder 2/4] WORKDIR /app 0.0s
=> [builder 3/4] COPY some-file-for-build.txt /app 0.0s
=> [builder 4/4] RUN echo 'building...' 0.8s
=> [stage-1 3/3] COPY --from=builder /app/some-file-for-build.txt some-file-for-build-from-builder-stage.txt 0.0s
=> exporting to image 0.9s
=> => exporting layers 0.8s
=> => writing image sha256:94fd1e56c8044f0e2f80ee83c784cca5f2c384fd4eba9210f9ff81db68f406e5 0.0s
=> => naming to docker.io/library/61977760:latest 0.0s
> docker rmi $(docker images --filter "dangling=true" -q --no-trunc)
Deleted: sha256:4d157078805ccf08fd42502b19a665a0b60e80a33a7c5b6485e6fd201ca91cc1
Deleted: sha256:6f7f45cca948cf855afea76ff73878b8348da6ed2652d62b48f992f7d9768822
Deleted: sha256:eefe65e58b69e4567c5145828ec95d1d9f3477709cc76fb571e204920df8e378
> docker build --pull --rm -f "61977760.Dockerfile" -t 61977760:latest "."
[+] Building 0.9s (10/10) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from 61977760.Dockerfile 0.1s
=> => transferring dockerfile: 47B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:18.04 0.8s
=> [builder 1/4] FROM docker.io/library/ubuntu:18.04@sha256:3235326357dfb65f1781dbc4df3b834546d8bf914e82cce58e6e6b676e23ce8f 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 42B 0.0s
=> CACHED [builder 2/4] WORKDIR /app 0.0s
=> CACHED [builder 3/4] COPY some-file-for-build.txt /app 0.0s
=> CACHED [builder 4/4] RUN echo 'building...' 0.0s
=> CACHED [stage-1 3/3] COPY --from=builder /app/some-file-for-build.txt some-file-for-build-from-builder-stage.txt 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:94fd1e56c8044f0e2f80ee83c784cca5f2c384fd4eba9210f9ff81db68f406e5 0.0s
=> => naming to docker.io/library/61977760:latest 0.0s
> docker builder prune --all
WARNING! This will remove all build cache. Are you sure you want to continue? [y/N] y
Deleted build cache objects:
np9zknowpkgi9aa2qtfstthnr
l0lucvc40nl98ceqxqadjplaw
elj14uwncgbk928oawwalht9x
s4l0w4h3day53tc3w20njd9cm
t6br3zadzcqhwilswvhkc2qkv
q8wrflxp3sppgmrft0yv805l0
qbe59a3kgjdvaw4ng7d5rasc8
sha256:82751c4dcc36265daceeee0abd938806b591eb66700863186377348c96e8aead
sha256:24b16cac34768092d57cdb429a12de6c9ee870a3724d70098a189ae0ac344c42
sha256:b1daff3b271fede2bec31812c398e28952f792935f608e467271cdfaccab7de2
sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e
Total reclaimed space: 64.21MB
>