如何更高效更快地構建Docker映象

如何更高效更快地構建Docker映象

在構建服務期間,我們經常需要構建docker映象。我們每天都要做很多次。這可能是一個耗時的任務。在本地,我們只注意到一點,但在CI/CD管道中,這可能是一個問題。

在這篇文章中,我將告訴你如何加快構建Docker映象這一過程。我將向你展示如何使用快取,將你的Docker檔案分層,並使用多階段構建,以使你的構建更快。

為此,我將使用一個簡單的Go應用程式。你可以使用你的任何其他應用程式。你使用哪個堆疊、語言或框架並不重要。原則都是一樣的。

我所做的一切都在我的本地機器上執行。我不使用任何CI/CD工具。我使用Docker Desktop for Mac。

清理工作

為了確保我們從一個乾淨的狀態開始,我們可以刪除所有未使用的映象、容器、卷和網路:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ docker system prune -a
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all images without at least one container associated to them
- all build cache
Are you sure you want to continue? [y/N] y
...gone with the wind...
$ docker system prune -a WARNING! This will remove: - all stopped containers - all networks not used by at least one container - all images without at least one container associated to them - all build cache Are you sure you want to continue? [y/N] y ...gone with the wind...
$ docker system prune -a
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all images without at least one container associated to them
- all build cache
Are you sure you want to continue? [y/N] y
...gone with the wind...

起始點

我從一個簡單的Dockerfile(Dockerfile_1)開始:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
FROM golang:buster
WORKDIR /app
COPY app /app/
ENTRYPOINT [ "/app/app" ]
FROM golang:buster WORKDIR /app COPY app /app/ ENTRYPOINT [ "/app/app" ]
FROM golang:buster
WORKDIR /app
COPY app /app/
ENTRYPOINT [ "/app/app" ]

為了能夠使用這個Docker檔案,我必須先建立一個應用程式:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ go build -o app
$ go build -o app
$ go build -o app

然後再建立映象:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ docker build . -f Dockerfile_1
Sending build context to Docker daemon 22.84MB
Step 1/4 : FROM golang:buster
---> f8c6c6bf3e26
Step 2/4 : WORKDIR /app
---> Running in 62eb8791ace1
Removing intermediate container 62eb8791ace1
---> d586151d2813
Step 3/4 : COPY app /app/
---> 25b4f091cba7
Step 4/4 : ENTRYPOINT [ "/app/app" ]
---> Running in 7853090f8c3b
Removing intermediate container 7853090f8c3b
---> 0e3d3835a61b
Successfully built 0e3d3835a61b
$ docker build . -f Dockerfile_1 Sending build context to Docker daemon 22.84MB Step 1/4 : FROM golang:buster ---> f8c6c6bf3e26 Step 2/4 : WORKDIR /app ---> Running in 62eb8791ace1 Removing intermediate container 62eb8791ace1 ---> d586151d2813 Step 3/4 : COPY app /app/ ---> 25b4f091cba7 Step 4/4 : ENTRYPOINT [ "/app/app" ] ---> Running in 7853090f8c3b Removing intermediate container 7853090f8c3b ---> 0e3d3835a61b Successfully built 0e3d3835a61b
$ docker build  . -f Dockerfile_1
Sending build context to Docker daemon  22.84MB
Step 1/4 : FROM golang:buster
---> f8c6c6bf3e26
Step 2/4 : WORKDIR /app
---> Running in 62eb8791ace1
Removing intermediate container 62eb8791ace1
---> d586151d2813
Step 3/4 : COPY app /app/
---> 25b4f091cba7
Step 4/4 : ENTRYPOINT [ "/app/app" ]
---> Running in 7853090f8c3b
Removing intermediate container 7853090f8c3b
---> 0e3d3835a61b
Successfully built 0e3d3835a61b

我想啟動它,但我需要知道映象的名稱。我可以用 docker images 來找到它:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 0e3d3835a61b 48 seconds ago 739MB
excalidraw/excalidraw latest d6392f9c5191 2 days ago 34.8MB
golang buster f8c6c6bf3e26 4 days ago 720MB
moby/buildkit buildx-stable-1 4dc9f4d5bf89 2 weeks ago 168MB
slimdotai/dd-ext 0.8.2 56f11b815b6c 7 months ago 153MB
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> 0e3d3835a61b 48 seconds ago 739MB excalidraw/excalidraw latest d6392f9c5191 2 days ago 34.8MB golang buster f8c6c6bf3e26 4 days ago 720MB moby/buildkit buildx-stable-1 4dc9f4d5bf89 2 weeks ago 168MB slimdotai/dd-ext 0.8.2 56f11b815b6c 7 months ago 153MB
$ docker images
REPOSITORY              TAG               IMAGE ID       CREATED          SIZE
<none>                  <none>            0e3d3835a61b   48 seconds ago   739MB
excalidraw/excalidraw   latest            d6392f9c5191   2 days ago       34.8MB
golang                  buster            f8c6c6bf3e26   4 days ago       720MB
moby/buildkit           buildx-stable-1   4dc9f4d5bf89   2 weeks ago      168MB
slimdotai/dd-ext        0.8.2             56f11b815b6c   7 months ago     153MB

我可以看到映象的名稱是 <none> 。我可以用它來啟動容器:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ docker run 0e3d3835a61b
exec /app/app: exec format error
$ docker run 0e3d3835a61b exec /app/app: exec format error
$ docker run 0e3d3835a61b
exec /app/app: exec format error

會發生什麼?回到Dockerfile_1,看一下它。這裡面有幾個問題:

  • 我正在為OSX構建應用程式,但我想在Linux中執行它。
  • 我沒有指定我使用的是哪個Go版本。在本地,我可以使用Go 1.16,但映象上有最新的Go版本(目前是1.20)。
  • 我的應用程式使用9999埠,但我沒有公開它。
  • 我的映象沒有名稱和版本。

多階段構建

為了解決第一個問題,我可以使用多階段構建。我將建立一個新的Dockerfile(Dockerfile_2):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
ARG GO_VERSION=1.20.3
FROM golang:${GO_VERSION}-buster as builder
WORKDIR /app
COPY . /app/
RUN go mod tidy
RUN go build -o app
FROM debian:buster as final
WORKDIR /app
COPY --from=builder /app/app /app/
EXPOSE ${PORT:-9999}
ENTRYPOINT [ "/app/app" ]
ARG GO_VERSION=1.20.3 FROM golang:${GO_VERSION}-buster as builder WORKDIR /app COPY . /app/ RUN go mod tidy RUN go build -o app FROM debian:buster as final WORKDIR /app COPY --from=builder /app/app /app/ EXPOSE ${PORT:-9999} ENTRYPOINT [ "/app/app" ]
ARG GO_VERSION=1.20.3
FROM golang:${GO_VERSION}-buster as builder
WORKDIR /app
COPY . /app/
RUN go mod tidy
RUN go build -o app
FROM debian:buster as final
WORKDIR /app
COPY --from=builder /app/app /app/
EXPOSE ${PORT:-9999}
ENTRYPOINT [ "/app/app" ]

在新的Docker檔案中,我用 ARG 指令處理Go版本。你不一定要這樣做。你也可以對版本進行硬編碼。但有了 ARG ,你可以在構建映象時覆蓋它。

構建一個應用程式被移到第一個或 builder 階段。當應用程式構建完成後,它被複制到第二階段或 final 階段。在這兩個階段,我都使用Debian Buster。它是一個小的映像,對我的應用程式來說已經足夠了。我還暴露了一個埠,設定預設值為9999。

現在我可以建立映象了:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ docker build . -t rnemet/echo:0.0.1 -f Dockerfile_2
Sending build context to Docker daemon 22.84MB
Step 1/11 : ARG GO_VERSION=1.20.3
Step 2/11 : FROM golang:${GO_VERSION}-buster as builder
1.20.3-buster: Pulling from library/golang
Digest: sha256:413cd9e04db86fee3f5c667de293f37d9199b74880771c37dcfeb165cefaf424
Status: Downloaded newer image for golang:1.20.3-buster
---> f8c6c6bf3e26
Step 3/11 : WORKDIR /app
---> Using cache
---> d586151d2813
Step 4/11 : COPY . /app/
---> 331d288c0f19
Step 5/11 : RUN go mod tidy
---> Running in 2657122aa7fe
go: downloading github.com/prometheus/client_golang v1.14.0
...snip...
go: downloading github.com/rogpeppe/go-internal v1.8.0
Removing intermediate container 2657122aa7fe
---> 48197d27f8ab
Step 6/11 : RUN go build -o app
---> Running in 7e593ea7ffb4
Removing intermediate container 7e593ea7ffb4
---> d086687f4f17
Step 7/11 : FROM debian:buster
buster: Pulling from library/debian
4e2befb7f5d1: Already exists
Digest: sha256:235f2a778fbc0d668c66afa9fd5f1efabab94c1d6588779ea4e221e1496f89da
Status: Downloaded newer image for debian:buster
---> 4591634d6289
Step 8/11 : WORKDIR /app
---> Running in a79e19ed4815
Removing intermediate container a79e19ed4815
---> b316081e2c13
Step 9/11 : COPY --from=builder /app/app /app/
---> 6fdc4f84223f
Step 10/11 : EXPOSE ${PORT:-9999}
---> Running in e5bf1bc188b9
Removing intermediate container e5bf1bc188b9
---> 8da39c1270c4
Step 11/11 : ENTRYPOINT [ "/app/app" ]
---> Running in 421008b145ee
Removing intermediate container 421008b145ee
---> 159ca8b29354
Successfully built 159ca8b29354
Successfully tagged rnemet/echo:0.0.1
$ docker build . -t rnemet/echo:0.0.1 -f Dockerfile_2 Sending build context to Docker daemon 22.84MB Step 1/11 : ARG GO_VERSION=1.20.3 Step 2/11 : FROM golang:${GO_VERSION}-buster as builder 1.20.3-buster: Pulling from library/golang Digest: sha256:413cd9e04db86fee3f5c667de293f37d9199b74880771c37dcfeb165cefaf424 Status: Downloaded newer image for golang:1.20.3-buster ---> f8c6c6bf3e26 Step 3/11 : WORKDIR /app ---> Using cache ---> d586151d2813 Step 4/11 : COPY . /app/ ---> 331d288c0f19 Step 5/11 : RUN go mod tidy ---> Running in 2657122aa7fe go: downloading github.com/prometheus/client_golang v1.14.0 ...snip... go: downloading github.com/rogpeppe/go-internal v1.8.0 Removing intermediate container 2657122aa7fe ---> 48197d27f8ab Step 6/11 : RUN go build -o app ---> Running in 7e593ea7ffb4 Removing intermediate container 7e593ea7ffb4 ---> d086687f4f17 Step 7/11 : FROM debian:buster buster: Pulling from library/debian 4e2befb7f5d1: Already exists Digest: sha256:235f2a778fbc0d668c66afa9fd5f1efabab94c1d6588779ea4e221e1496f89da Status: Downloaded newer image for debian:buster ---> 4591634d6289 Step 8/11 : WORKDIR /app ---> Running in a79e19ed4815 Removing intermediate container a79e19ed4815 ---> b316081e2c13 Step 9/11 : COPY --from=builder /app/app /app/ ---> 6fdc4f84223f Step 10/11 : EXPOSE ${PORT:-9999} ---> Running in e5bf1bc188b9 Removing intermediate container e5bf1bc188b9 ---> 8da39c1270c4 Step 11/11 : ENTRYPOINT [ "/app/app" ] ---> Running in 421008b145ee Removing intermediate container 421008b145ee ---> 159ca8b29354 Successfully built 159ca8b29354 Successfully tagged rnemet/echo:0.0.1
$ docker build . -t rnemet/echo:0.0.1 -f Dockerfile_2
Sending build context to Docker daemon  22.84MB
Step 1/11 : ARG GO_VERSION=1.20.3
Step 2/11 : FROM golang:${GO_VERSION}-buster as builder
1.20.3-buster: Pulling from library/golang
Digest: sha256:413cd9e04db86fee3f5c667de293f37d9199b74880771c37dcfeb165cefaf424
Status: Downloaded newer image for golang:1.20.3-buster
---> f8c6c6bf3e26
Step 3/11 : WORKDIR /app
---> Using cache
---> d586151d2813
Step 4/11 : COPY . /app/
---> 331d288c0f19
Step 5/11 : RUN go mod tidy
---> Running in 2657122aa7fe
go: downloading github.com/prometheus/client_golang v1.14.0
...snip...
go: downloading github.com/rogpeppe/go-internal v1.8.0
Removing intermediate container 2657122aa7fe
---> 48197d27f8ab
Step 6/11 : RUN go build -o app
---> Running in 7e593ea7ffb4
Removing intermediate container 7e593ea7ffb4
---> d086687f4f17
Step 7/11 : FROM debian:buster
buster: Pulling from library/debian
4e2befb7f5d1: Already exists
Digest: sha256:235f2a778fbc0d668c66afa9fd5f1efabab94c1d6588779ea4e221e1496f89da
Status: Downloaded newer image for debian:buster
---> 4591634d6289
Step 8/11 : WORKDIR /app
---> Running in a79e19ed4815
Removing intermediate container a79e19ed4815
---> b316081e2c13
Step 9/11 : COPY --from=builder /app/app /app/
---> 6fdc4f84223f
Step 10/11 : EXPOSE ${PORT:-9999}
---> Running in e5bf1bc188b9
Removing intermediate container e5bf1bc188b9
---> 8da39c1270c4
Step 11/11 : ENTRYPOINT [ "/app/app" ]
---> Running in 421008b145ee
Removing intermediate container 421008b145ee
---> 159ca8b29354
Successfully built 159ca8b29354
Successfully tagged rnemet/echo:0.0.1

現在我可以看到映象有名稱和版本:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
rnemet/echo 0.0.1 159ca8b29354 4 minutes ago 133MB
<none> <none> d086687f4f17 4 minutes ago 1.17GB
<none> <none> 0e3d3835a61b 40 minutes ago 739MB
excalidraw/excalidraw latest d6392f9c5191 2 days ago 34.8MB
golang 1.20.3-buster f8c6c6bf3e26 5 days ago 720MB
golang buster f8c6c6bf3e26 5 days ago 720MB
moby/buildkit buildx-stable-1 4dc9f4d5bf89 2 weeks ago 168MB
debian buster 4591634d6289 2 weeks ago 114MB
slimdotai/dd-ext 0.8.2 56f11b815b6c 7 months ago 153MB
docker images REPOSITORY TAG IMAGE ID CREATED SIZE rnemet/echo 0.0.1 159ca8b29354 4 minutes ago 133MB <none> <none> d086687f4f17 4 minutes ago 1.17GB <none> <none> 0e3d3835a61b 40 minutes ago 739MB excalidraw/excalidraw latest d6392f9c5191 2 days ago 34.8MB golang 1.20.3-buster f8c6c6bf3e26 5 days ago 720MB golang buster f8c6c6bf3e26 5 days ago 720MB moby/buildkit buildx-stable-1 4dc9f4d5bf89 2 weeks ago 168MB debian buster 4591634d6289 2 weeks ago 114MB slimdotai/dd-ext 0.8.2 56f11b815b6c 7 months ago 153MB
docker images
REPOSITORY              TAG               IMAGE ID       CREATED          SIZE
rnemet/echo             0.0.1             159ca8b29354   4 minutes ago    133MB
<none>                  <none>            d086687f4f17   4 minutes ago    1.17GB
<none>                  <none>            0e3d3835a61b   40 minutes ago   739MB
excalidraw/excalidraw   latest            d6392f9c5191   2 days ago       34.8MB
golang                  1.20.3-buster     f8c6c6bf3e26   5 days ago       720MB
golang                  buster            f8c6c6bf3e26   5 days ago       720MB
moby/buildkit           buildx-stable-1   4dc9f4d5bf89   2 weeks ago      168MB
debian                  buster            4591634d6289   2 weeks ago      114MB
slimdotai/dd-ext        0.8.2             56f11b815b6c   7 months ago     153MB

而且我可以執行這個容器:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ docker run rnemet/echo:0.0.1
2021/12/05 20:56:05 Starting server on port 9999
$ docker run rnemet/echo:0.0.1 2021/12/05 20:56:05 Starting server on port 9999
$ docker run rnemet/echo:0.0.1
2021/12/05 20:56:05 Starting server on port 9999

如果你想覆蓋Go版本,你可以這樣做:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$ docker build . -t rnemet/echo:0.0.1 -f Dockerfile_2 --build-arg GO_VERSION=1.16.10
$ docker build . -t rnemet/echo:0.0.1 -f Dockerfile_2 --build-arg GO_VERSION=1.16.10
$ docker build . -t rnemet/echo:0.0.1 -f Dockerfile_2 --build-arg GO_VERSION=1.16.10

分層和快取

再看一下Dockerfile_2。Dockerfile中的每個條目都建立了一個新的層,每個層都被快取了。如果你改變了Dockerfile中的內容,Docker將重建被改變的層和所有後續層。

看一下 docker build 命令的輸出:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Sending build context to Docker daemon 22.84MB
Step 1/11 : ARG GO_VERSION=1.20.3
Step 2/11 : FROM golang:${GO_VERSION}-buster as builder
1.20.3-buster: Pulling from library/golang
Digest: sha256:413cd9e04db86fee3f5c667de293f37d9199b74880771c37dcfeb165cefaf424
Status: Downloaded newer image for golang:1.20.3-buster
---> f8c6c6bf3e26
Step 3/11 : WORKDIR /app
---> Using cache <=== here cache is used
---> d586151d2813
Step 4/11 : COPY . /app/
---> 331d288c0f19
Step 5/11 : RUN go mod tidy
---> Running in 2657122aa7fe
go: downloading github.com/prometheus/client_golang v1.14.0
...snip...
go: downloading github.com/rogpeppe/go-internal v1.8.0
Removing intermediate container 2657122aa7fe
---> 48197d27f8ab
Sending build context to Docker daemon 22.84MB Step 1/11 : ARG GO_VERSION=1.20.3 Step 2/11 : FROM golang:${GO_VERSION}-buster as builder 1.20.3-buster: Pulling from library/golang Digest: sha256:413cd9e04db86fee3f5c667de293f37d9199b74880771c37dcfeb165cefaf424 Status: Downloaded newer image for golang:1.20.3-buster ---> f8c6c6bf3e26 Step 3/11 : WORKDIR /app ---> Using cache <=== here cache is used ---> d586151d2813 Step 4/11 : COPY . /app/ ---> 331d288c0f19 Step 5/11 : RUN go mod tidy ---> Running in 2657122aa7fe go: downloading github.com/prometheus/client_golang v1.14.0 ...snip... go: downloading github.com/rogpeppe/go-internal v1.8.0 Removing intermediate container 2657122aa7fe ---> 48197d27f8ab
Sending build context to Docker daemon  22.84MB
Step 1/11 : ARG GO_VERSION=1.20.3
Step 2/11 : FROM golang:${GO_VERSION}-buster as builder
1.20.3-buster: Pulling from library/golang
Digest: sha256:413cd9e04db86fee3f5c667de293f37d9199b74880771c37dcfeb165cefaf424
Status: Downloaded newer image for golang:1.20.3-buster
---> f8c6c6bf3e26
Step 3/11 : WORKDIR /app
---> Using cache                            <=== here cache is used
---> d586151d2813
Step 4/11 : COPY . /app/
---> 331d288c0f19
Step 5/11 : RUN go mod tidy
---> Running in 2657122aa7fe
go: downloading github.com/prometheus/client_golang v1.14.0
...snip...
go: downloading github.com/rogpeppe/go-internal v1.8.0
Removing intermediate container 2657122aa7fe
---> 48197d27f8ab

我的目標是編寫基本相同的圖層。這樣一來,我就可以使用快取,更快地建立映象。在第4步,我把所有檔案從我的本地目錄複製到映象上。乍一看,這的確有道理。但是,如果我改變了一個README檔案,或者任何其他與應用程式無關的檔案,我將重建整個映象。這就不妙了。所以,我要麼指定複製什麼,要麼不復制什麼。

對於第二個選擇,我可以使用 .dockerignore 檔案。它類似於 .gitignore 檔案。它包含一個不應該被複制到映象中的檔案列表:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
.gitignore
.dockerignore
**/compose*
Dockerfile
License
Makefile
Readme.md
.gitignore .dockerignore **/compose* Dockerfile License Makefile Readme.md
.gitignore
.dockerignore
**/compose*
Dockerfile
License
Makefile
Readme.md

那麼 COPY . /app/ 將只複製檔案,不在 .dockerignore 檔案中。

讓我們再考慮一件事。在第5步,我正在執行 go mod tidy 。它下載了所有的依賴項。這些依賴項並不經常改變。當它們被改變時,我應該重建這個應用程式。對於Go應用程式來說,下載依賴項並不是一個大問題,但對於其他語言來說,這可能是一個問題(想想NodeJS)。所以,讓我們先處理依賴關係,然後再複製原始碼。這樣一來,我就用一個快取來處理依賴關係,而不是在每次改變原始碼時都重建它們。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
ARG GO_VERSION=1.20.3
FROM golang:${GO_VERSION}-buster as builder
WORKDIR /app
COPY go.mod go.sum /app/
RUN go mod download -x
COPY . /app/
RUN go build -o app
FROM debian:buster
WORKDIR /app
COPY --from=builder /app/app /app/
EXPOSE ${PORT:-9999}
ENTRYPOINT [ "/app/app" ]
ARG GO_VERSION=1.20.3 FROM golang:${GO_VERSION}-buster as builder WORKDIR /app COPY go.mod go.sum /app/ RUN go mod download -x COPY . /app/ RUN go build -o app FROM debian:buster WORKDIR /app COPY --from=builder /app/app /app/ EXPOSE ${PORT:-9999} ENTRYPOINT [ "/app/app" ]
ARG GO_VERSION=1.20.3
FROM golang:${GO_VERSION}-buster as builder
WORKDIR /app
COPY go.mod go.sum /app/
RUN go mod download -x
COPY . /app/
RUN go build -o app
FROM debian:buster
WORKDIR /app
COPY --from=builder /app/app /app/
EXPOSE ${PORT:-9999}
ENTRYPOINT [ "/app/app" ]

當最初執行 docker build . -t rnemet/echo:0.0.1 -f Dockerfile_3 會花一些時間來下載依賴項。因為我使用了選項 -x,我可以看到所有下載的依賴項。如果你覺得麻煩,你可以刪除 -x 選項。如果你重新執行它,它將會快得多。而且,你會注意到,依賴關係是被快取的。

如果你改變了原始碼,依賴項就不會被再次下載。所以構建映象的速度會快很多。

自己試試吧。比較Dockerfile_2和Dockerfile_3的構建時間。

遠端快取

在使用CI/CD時,你要麼依靠CI/CD快取的實現,要麼依靠遠端快取。遠端快取是一個儲存在遠端位置的快取,因此,你可以用它來加快構建速度,在不同的機器和不同的使用者之間共享。

為此,我不得不使用BuildKit。它是Docker的一個新的構建工具箱。你可以像這樣使用它:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
docker buildx build -t rnemet/echo:0.0.1 . -f Dockerfile_3 --cache-to type=registry,ref=rnemet/echo:test --cache-from type=registry,ref=rnemet/echo:test --cache-from type=registry,ref=rnemet/echo:main [--push|--load]
docker buildx build -t rnemet/echo:0.0.1 . -f Dockerfile_3 --cache-to type=registry,ref=rnemet/echo:test --cache-from type=registry,ref=rnemet/echo:test --cache-from type=registry,ref=rnemet/echo:main [--push|--load]
docker buildx build -t rnemet/echo:0.0.1 . -f Dockerfile_3 --cache-to type=registry,ref=rnemet/echo:test --cache-from type=registry,ref=rnemet/echo:test --cache-from type=registry,ref=rnemet/echo:main [--push|--load]

如果你想使用遠端快取,請指定 --cache-to--cache-from 選項。選項 --cache-to 指定了儲存快取的位置。選項 --cache-from 指定從哪裡獲得快取。你可以為這兩個選項指定多個位置。如果你為 --cache-from 指定了多個位置,它將嘗試從所有的位置獲取快取。如果它在其中一個地方找到了快取,它就會使用它。

一個好的做法是為分支和主幹建立一個快取。在上面的例子中,我有 testmain 兩個分支。我把 test 分支用於測試, main 用於生產。所以,我為這兩個分支都建立了快取。如果我正在建立一個 test 分支,它將嘗試從 test 分支獲取快取,如果失敗,它將嘗試從 main 分支獲取快取。

如果你想把映象推送到登錄檔,使用 --push 選項。如果你要把映象載入到你的本地機器上,你可以使用 --load 選項。

總結

在這篇文章中,我向你展示瞭如何構建Dockerfile以加快構建過程。我希望你覺得這篇文章對你有幫助。

參考文獻

評論留言