Docker 的多階段構建

2021-09-11 13:53:14 字數 2800 閱讀 9192

比如我們現在有乙個最簡單的 golang 服務,需要構建乙個最小的docker映象,原始碼如下:

}複製**

我們最終的目的都是將最終的可執行檔案放到乙個最小的映象(比如alpine)中去執行,怎樣得到最終的編譯好的檔案呢?基於docker的指導思想,我們需要在乙個標準的容器中編譯,比如在乙個 ubuntu 映象中先安裝編譯的環境,然後編譯,最後也在該容器中執行即可。

但是如果我們想把編譯後的檔案放置到alpine映象中執行呢?我們就得通過上面的 ubuntu 映象將編譯完成的檔案通過volume掛載到我們的主機上,然後我們再將這個檔案掛載到alpine映象中去。

這種解決方案理論上肯定是可行的,但是這樣的話在構建映象的時候我們就得定義兩步了,第一步是先用乙個通用的映象編譯映象,第二步是將編譯後的檔案複製到alpine映象中執行,而且通用映象編譯後的檔案在alpine映象中不一定能執行。

定義編譯階段的dockerfile:(儲存為dockerfile.build)

run govendor sync定義alpine映象:(儲存為dockerfile.old)

from alpine:latest

run apk add -u tzdata

run ln -sf /usr/share/zoneinfo/asia/shanghai /etc/localtime

workdir /root/

根據我們的執行步驟,我們還可以簡單定義成乙個指令碼:(儲存為build.sh)

#!/bin/sh

echo building cnych/docker-multi-stage-demo:build

​docker build -t cnych/docker-multi-stage-demo:build . -f dockerfile.build

​docker create --name extract cnych/docker-multi-stage-demo:build

docker rm -f extract

​echo building cnych/docker-multi-stage-demo:old

​docker build --no-cache -t cnych/docker-multi-stage-demo:old . -f dockerfile.old

當我們執行完上面的構建指令碼後,就實現了我們的目標。

有沒有一種更加簡單的方式來實現上面的映象構建過程呢?docker 17.05版本以後,官方就提供了乙個新的特性:multi-stage builds(多階段構建)。使用多階段構建,你可以在乙個dockerfile中使用多個 from 語句。每個 from 指令都可以使用不同的基礎映象,並表示開始乙個新的構建階段。你可以很方便的將乙個階段的檔案複製到另外乙個階段,在最終的映象中保留下你需要的內容即可。

我們可以調整前面一節的dockerfile來使用多階段構建:(儲存為dockerfile)

expose 8080現在我們只需要乙個dockerfile檔案即可,也不需要拆分構建指令碼了,只需要執行 build 命令即可:

$ docker build -t cnych/docker-multi-stage-demo:latest .複製**
預設情況下,構建階段是沒有命令的,我們可以通過它們的索引來引用它們,第乙個 from 指令從0開始,我們也可以用as指令為階段命令,比如我們這裡的將第一階段命名為build-env,然後在其他階段需要引用的時候使用--from=build-env引數即可。

最後我們簡單的執行下該容器測試:

$ docker run --rm -p 8080:8080 cnych/docker-multi-stage-demo:latest複製**
執行成功後,我們可以在瀏覽器中開啟位址,可以看到pong返回。

現在我們就把兩個映象的檔案最終合併到乙個映象裡面了。

文章中涉及到**可以前往 github 檢視:github.com/cnych/docke…

Docker多階段構建

在 docker 17.05 版本之前,我們構建 docker 映象時,通常會採用兩種方式 一種方式是將所有的構建過程編包含在乙個 dockerfile 中,包括專案及其依賴庫的編譯 測試 打包等流程,這裡可能會帶來的一些問題 package main import fmt func main 編寫...

docker 多階段構建

構建映象最具挑戰性的一點是使映象大小盡可能的小。dockerfile中的每條指令都為影象新增了乙個圖層,您需要記住在移動到下一層之前清理任何不需要的工件。對於多階段構建,您可以在dockerfile中使用多個from語句。每個from指令可以使用不同的基礎,並且每個指令都開始乙個新的構建。您可以選擇...

docker 映象多階段構建

下面是 go 語言 hello world package main import fmt func main 接著用 alpine 1 的 go 語言 image 來編譯出可執行檔案。from golang alpine接著執行如下編譯指令 build stage from golang alpi...