比如我們現在有乙個最簡單的 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...