Docker多階段構建最佳實踐
Docker目前在容器市場可以說是佔領了大部分市場,Docker掀起了容器革命,同時也改變了現代化雲平臺的構建方式。儘管Docker很強大,但使用過程當中也遇到了一些問題。比如說我想要構建一個編譯型語言映象,需要先在一個Dockerfile中編譯,然後再使用另外一個Dockerfile把編譯好的檔案放到映象中。這樣無形當中就增大了CI/CD的複雜度。
Docker多階段構建是17.05以後引入的新特性,旨在解決編譯和構建複雜的問題。減小映象大小。因此要使用多階段構建特性必須使用高於或等於17.05的Docker。
多階段構建出現之前
構建映象最具挑戰性的一點是使映象大小盡可能的小。Dockerfile中的每條指令都為影像新增了一個圖層,您需要記住在移動到下一層之前清理任何不需要的工件。
為了編寫一個真正高效的Dockerfile,傳統上需要使用shell技巧和其他邏輯來保持層儘可能小,並確保每個層都具有前一層所需的工件而不是其他任何東西。
實際上,有一個Dockerfile用於開發(包含構建應用程式所需的所有內容),以及用於生產環境的精簡版Dockerfile,它只包含您的應用程式以及執行它所需的內容。這被稱為“建造者模式”。維護兩個Dockerfiles並不理想。
這是一個Dockerfile.build和Dockerfile的例子,它遵循上面的模式:
Dockerfile.build:
FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
COPY app.go .
RUN go get -d -v golang.org/x/net/html \
&& CGO_ENABLED= GOOS=linux go build -a -installsuffix cgo -o app .
請注意,此示例使用Bash &&運算子人為壓縮兩個RUN命令,以避免在image中建立其他層。這很容易出錯並且難以維護。
Dockerfile:
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app .
CMD ["./app"]
build.sh:
#!/bin/sh
echo Building alexellis2/href-counter:build
docker build --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy \
-t alexellis2/href-counter:build . -f Dockerfile.build
docker container create --name extract alexellis2/href-counter:build
docker container cp extract:/go/src/github.com/alexellis/href-counter/app ./app
docker container rm -f extract
echo Building alexellis2/href-counter:latest
docker build --no-cache -t alexellis2/href-counter:latest .
rm ./app
當您執行build.sh指令碼時,它需要構建第一個image,從中建立容器以複製工件,然後構建第二個image。
多階段構建大大簡化了這種情況!
使用多階段構建
對於多階段構建,您可以在Dockerfile中使用多個FROM語句。每個FROM指令可以使用不同的基礎,並且每個指令都開始一個新的構建。您可以選擇性地將工件從一個階段複製到另一個階段,從而在最終image中只留下您想要的內容。
為了說明這是如何工作的,讓我們調整上述示例的Dockerfile以使用多階段構建。
Dockerfile:
FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED= GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from= /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
您只需要單個Dockerfile。您也不需要單獨的構建指令碼。只需執行docker build:
$ docker build -t app:latest .
最終結果是產生與之前相同大小的image,複雜性顯著降低。您不需要建立任何中間image,也不需要將任何artifacts提取到本地系統。
它是如何工作的?第二個FROM指令以alpine:latest image為基礎開始一個新的構建階段。
COPY –from = 0行僅將前一階段的構建檔案複製到此新階段。Go SDK和任何中間層都被遺忘,而不是儲存在最終image中。
為多構建階段命名
預設情況下,階段未命名,您可以透過整數來引用它們,從第0個FROM指令開始。
但是,您可以透過向FROM指令新增as NAME來命名您的階段。此示例透過命名階段並使用COPY指令中的名稱來改進前一個示例。
這意味著即使稍後重新排序Dockerfile中的指令,COPY也不會中斷。
FROM golang:1.7.3 as builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED= GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
停在特定的構建階段
構建映像時,不一定需要構建整個Dockerfile每個階段。
可以指定目標構建階段。以下命令假定您使用的是以前的Dockerfile,但在名為builder的階段停止:
$ docker build --target builder -t alexellis2/href-counter:latest .
使用此功能可能的一些非常適合的場景是:
◾除錯特定的構建階段
◾在debug階段,啟用所有除錯或工具,而在production階段儘量精簡
◾在testing階段,您的應用程式將填充測試資料,但在production階段則使用生產資料
使用外部映象作為stage
使用多階段構建時,您不僅可以從Dockerfile中建立的映象中進行復制。
您還可以使用COPY –from指令從單獨的image中複製,使用本地image名稱,本地或Docker登錄檔中可用的標記或標記ID。
如有必要,Docker會提取image並從那裡開始複製。
語法是:
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
原文連結: https://wilhelmguo.tk/blog/post/william/Docker 構建之多階段構建
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31547898/viewspace-2213072/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Dockerfile 多階段構建實踐Docker
- Docker多階段構建實戰(multi-stage builds)DockerUI
- 使用 Docker 開發 - 使用多階段構建映象Docker
- Docker 分階段構建映象Docker
- Docker 映象分階段構建Docker
- 使用nodejs構建Docker image最佳實踐NodeJSDocker
- Docker 重要更新: 原生支援多階段構建(multi-stage build)DockerUI
- 新版的Django Docker部署方案,多階段構建、自動處理前端依賴DjangoDocker前端
- 使用Docker Compose構建生產應用的最佳實踐 — NickDocker
- 突破難關:Docker映象和容器的區別以及構建的最佳實踐Docker
- 使用管道流實現Java 8階段構建器Java
- 【快速學習】docker構建java專案實踐DockerJava
- 用mobx構建大型專案的最佳實踐
- 使用React構建大型應用的最佳實踐React
- Git最佳實踐建議Git
- Docker 構建多平臺映象Docker
- Docker構建多平臺映象Docker
- Prompt進階2:LangGPT(構建高效能Prompt策略和技巧)--最佳實踐指南GPT
- Docker結合Jenkins的持續構建實踐DockerJenkins
- Docker映象構建:技術深度解析與實踐指南Docker
- 用mobx構建大型專案的最佳實踐(2)
- 基於 react, redux 最佳實踐構建的 2048ReactRedux
- Docker進階與實踐之三:Docker映象Docker
- 統一過程(UP)定義了初啟階段、精化階段、構建階段、移交階段和產生階段,每個階段以達到某個里程碑時結束,其中()的里程碑是生命週期架構。 A.初啟階段 B.精化階段 C.構建階段 D.移交階段架構
- Docker容器日誌管理最佳實踐Docker
- Docker 映象優化與最佳實踐Docker優化
- 構建高效Presubmit卡點,落地測試左移最佳實踐MIT
- Aggregated APIServer 構建雲原生應用最佳實踐APIServer
- Flink Table Store 0.3 構建流式數倉最佳實踐
- 構建高效的 Python Web 應用:最佳實踐指南PythonWeb
- 最佳化您的部署:Docker 映象最佳實踐Docker
- React 進階二-元件最佳實踐React元件
- 【建議收藏】swoft的最佳實踐
- TKE 叢集組建最佳實踐
- [Docker]寫 Dockerfile 的最佳實踐理論Docker
- ABAP system landscape和vue專案webpack構建的最佳實踐VueWeb
- Nestjs最佳實踐教程(八): CRUD抽象化框架構建JS抽象框架架構
- 得物佈局構建耗時最佳化方案實踐