【发布时间】:2021-09-10 19:56:01
【问题描述】:
我们有这样的Dockerfile:
FROM alpine:latest as step1
RUN echo "STEP1"
FROM alpine:latest as step2
RUN echo "STEP2"
FROM step1 as step3
RUN echo "STEP3"
在 Windows(或 WSL2)上,我们有这样的构建多阶段图像的结果。
在 Windows 上构建所有步骤:
$ docker build .
[+] Building 0.2s (7/7) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 32B 0.0s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> [step1 1/2] FROM docker.io/library/alpine:latest 0.0s
=> CACHED [step1 2/2] RUN echo "STEP1" 0.0s
=> CACHED [step3 1/1] RUN echo "STEP3" 0.0s
=> exporting to image 0.1s
=> => exporting layers 0.0s
=> => writing image sha256:38ba33425558f5373099ad59aa187456c38b3f5eab14a60fdbb3cb7b1c484392 0.0s
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
在 Windows 上构建步骤 2:
$ docker build --target step2 .
[+] Building 0.5s (6/6) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 32B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> CACHED [step2 1/2] FROM docker.io/library/alpine:latest 0.0s
=> [step2 2/2] RUN echo "STEP2" 0.3s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:855f35039a5a902e1d33111fc781f748955f8b3cad7fb56d6eb420fc5d2fa55b 0.0s
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Windows 上的 Docker 版本:
$ docker version
Client:
Cloud integration: 1.0.17
Version: 20.10.7
API version: 1.41
Go version: go1.16.4
Git commit: f0df350
Built: Wed Jun 2 12:00:56 2021
OS/Arch: windows/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.7
API version: 1.41 (minimum version 1.12)
Go version: go1.13.15
Git commit: b0f5bc3
Built: Wed Jun 2 11:54:58 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.6
GitCommit: d71fcd7d8303cbf684402823e425e9dd2e99285d
runc:
Version: 1.0.0-rc95
GitCommit: b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7
docker-init:
Version: 0.19.0
GitCommit: de40ad0
在 Ubuntu 上,我们的结果略有不同。
在 Ubuntu 上构建所有步骤:
$ docker build .
Sending build context to Docker daemon 2.048kB
Step 1/6 : FROM alpine:latest as step1
---> d4ff818577bc
Step 2/6 : RUN echo "STEP1"
---> Using cache
---> ca7b2711269c
Step 3/6 : FROM alpine:latest as step2
---> d4ff818577bc
Step 4/6 : RUN echo "STEP2"
---> Using cache
---> 50668d3ea1c2
Step 5/6 : FROM step1 as step3
---> ca7b2711269c
Step 6/6 : RUN echo "STEP3"
---> Using cache
---> f529239cd29a
Successfully built f529239cd29a
在 Ubuntu 上构建步骤 2:
$ docker build --target step2 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM alpine:latest as step1
---> d4ff818577bc
Step 2/4 : RUN echo "STEP1"
---> Using cache
---> ca7b2711269c
Step 3/4 : FROM alpine:latest as step2
---> d4ff818577bc
Step 4/4 : RUN echo "STEP2"
---> Using cache
---> 50668d3ea1c2
Successfully built 50668d3ea1c2
Ubuntu 上的 Docker 版本:
$ docker version
Client: Docker Engine - Community
Version: 20.10.7
API version: 1.41
Go version: go1.13.15
Git commit: f0df350
Built: Wed Jun 2 11:56:38 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.7
API version: 1.41 (minimum version 1.12)
Go version: go1.13.15
Git commit: b0f5bc3
Built: Wed Jun 2 11:54:50 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.6
GitCommit: d71fcd7d8303cbf684402823e425e9dd2e99285d
runc:
Version: 1.0.0-rc95
GitCommit: b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7
docker-init:
Version: 0.19.0
GitCommit: de40ad0
您可以看到 Docker Desktop (Windows) 跳过不需要的阶段,而 Ubuntu 上的 Docker 会构建它们。 Docker Engine 版本相同。
对于复杂的多阶段图像,与 Ubuntu 相比,Windows 上的 Docker 缓存行为可以节省大量构建时间。
如何使 Ubuntu 上的 Docker 在缓存方面的行为与 Windows 上的行为相同?
【问题讨论】:
-
两台不同机器上的缓存可以以不同方式填充。在尝试构建相同的两个镜像之前,您可能已经在机器上构建了不同的镜像。要真正与同类进行比较,您需要先清除两台机器的缓存。无论哪种方式......你为什么关心缓存有多好 - 你应该只是在两种情况下都希望获得相同的图像,并将缓存/优化留给 docker 可执行文件的细节。
-
当 Ubuntu(非 buildkit)输出显示
Using cache时,它也跳过了这一步。如果您想进一步证明这一点,请尝试将其中一个步骤更改为RUN sleep 5并查看它是否处于休眠状态。 -
这里的问题是我根本没有构建不需要的阶段。
-
例如,如果 stage2 有命令
COPY / /app,那么如果文件夹中的文件发生更改,那么无论缓存如何,stage2 都将在 Ubuntu 上重建。在 Windows 上,它将被跳过——正确的行为。 -
@DavidMaze,让我们进行如下更改:``` FROM alpine:latest as step1 RUN echo "STEP1" FROM alpine:latest as step2 RUN sleep 10 FROM step1 as step3 RUN echo "STEP3" ` `` 并通过
docker build --no-cache .在不缓存的情况下运行构建,Windows 上的构建时间约为 1 秒,而在 Ubuntu 上则超过 10 秒。
标签: linux windows docker caching build