Docker多階段構建

2021-10-23 05:57:44 字數 2974 閱讀 6684

在 docker 17.05 版本之前,我們構建 docker 映象時,通常會採用兩種方式:

一種方式是將所有的構建過程編包含在乙個 dockerfile 中,包括專案及其依賴庫的編譯、測試、打包等流程,這裡可能會帶來的一些問題:

package main  

import "fmt"

func main()

編寫 dockerfile.one 檔案

workdir /root/構建映象

$ docker build -t go/helloworld:1 -f dockerfile.one .

另一種方式,就是我們事先在乙個 dockerfile 將專案及其依賴庫編譯測試打包好後,再將其拷貝到執行環境中,這種方式需要我們編寫兩個 dockerfile 和一些編譯指令碼才能將其兩個階段自動整合起來,這種方式雖然可以很好地規避第一種方式存在的風險,但明顯部署過程較複雜。

例如,編寫 dockerfile.build 檔案

run go get -d -v github.com/go-sql-driver/mysql \編寫 dockerfile.copy 檔案

from alpine:latest

run apk --no-cache add ca-certificates

workdir /root/

新建 build.sh

#!/bin/sh

echo building go/helloworld:build

docker build -t go/helloworld:build . -f dockerfile.build

docker create --name extract go/helloworld:build

docker rm -f extract

echo building go/helloworld:2

docker build --no-cache -t go/helloworld:2 . -f dockerfile.copy

現在執行指令碼即可構建映象

$ chmod +x build.sh

$ ./build.sh

對比兩種方式生成的映象大小

$ docker image ls

repository tag image id created size

go/helloworld 2 f7cf3465432c 22 seconds ago 6.47mb

go/helloworld 1 f55d3e16affc 2 minutes ago 295mb

為解決以上問題,docker v17.05 開始支援多階段構建 ( multistage builds )。使用多階段構建我們就可以很容易解決前面提到的問題,並且只需要編寫乙個 dockerfile :

例如,編寫 dockerfile 檔案

workdir /root/構建映象

$ docker build -t go/helloworld:3 .

對比三個映象大小

$ docker image ls

repository tag image id created size

go/helloworld 3 d6911ed9c846 7 seconds ago 6.47mb

go/helloworld 2 f7cf3465432c 22 seconds ago 6.47mb

go/helloworld 1 f55d3e16affc 2 minutes ago 295mb

很明顯使用多階段構建的映象體積小,同時也完美解決了上邊提到的問題。

只構建某一階段的映象

我們可以使用 as 來為某一階段命名,例如

from golang:1.9-alpine as builder

例如當我們只想構建 builder 階段的映象時,我們可以在使用 docker build 命令時加上 --target 引數即可

$ docker build --target builder -t username/imagename:tag .

$ copy --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

docker 多階段構建

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

Docker 的多階段構建

比如我們現在有乙個最簡單的 golang 服務,需要構建乙個最小的docker映象,原始碼如下 複製 我們最終的目的都是將最終的可執行檔案放到乙個最小的映象 比如alpine 中去執行,怎樣得到最終的編譯好的檔案呢?基於docker的指導思想,我們需要在乙個標準的容器中編譯,比如在乙個 ubuntu...

docker 映象多階段構建

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