Docker多階段構建實戰(multi-stage builds)

在編寫Dockerfile構建docker鏡像時,常遇到如下問題:java

  1. RUN命令會讓鏡像新增layer,致使鏡像變大,雖然經過&&鏈接多個命令能緩解此問題,但若是命令之間用到docker指令例如COPY、WORKDIR等,依然會致使多個layer;
  2. 有些工具在構建過程當中會用到,可是最終的鏡像是不須要的(例如用maven編譯構建java工程),這要求Dockerfile的編寫者花更多精力來清理這些工具,清理的過程又可能致使新的layer;

爲了解決上述問題,從17.05版本開始Docker在構建鏡像時增長了新特性:多階段構建(multi-stage builds),將構建過程分爲多個階段,每一個階段均可以指定一個基礎鏡像,這樣在一個Dockerfile就能將多個鏡像的特性同時用到,例如:先用SDK鏡像構建.NET Core工程,再把構建結果和Runtime 合成,就作成了一個能夠直接運行.NET Core工程鏡像了;git

官方描述以下圖所示,地址是:https://docs.docker.com/develop/develop-images/multistage-build/github

image

官方的實例是golang的,今天咱們以.NET Core構建ASP.NET Core工程爲例,介紹如何使用multi-stage特性構建.NET Core微服務鏡像;golang

Dockerfile文件參見: https://github.com/geffzhang/AKS-learning-series/blob/master/src/TechTalksWeb/Dockerfile
### 第一階段,用sdk 鏡像進行編譯

FROM microsoft/dotnet:2.1.300-sdk AS build-envdocker

WORKDIR /TechTalksWebasp.net

COPY NuGet.config ./maven

COPY TechTalksWeb.csproj ./微服務

RUN dotnet restore工具

COPY . ./ui

#編譯構建

RUN dotnet publish --configuration Release --output releaseOutput --no-restore

#build runtime image

### 第二階段,用第一階段的.NET Core編譯文件和aspnetcore-runtime 鏡像合成一個小體積的鏡像

FROM microsoft/dotnet:2.1.0-aspnetcore-runtime

WORKDIR /TechTalksWeb

#從名爲build-env的stage複製構建結果到工做目錄

COPY --from=build-env /TechTalksWeb/releaseOutput ./

ENTRYPOINT ["dotnet", "TechTalksWeb.dll"]

上面就是分紅了兩個階段構建的Dockerfile腳本,請參考每行的註釋來理解,有如下幾點須要重點關注:

  1. 一共有兩次FROM指令出現,而最終的鏡像是基於最後一個FROM生成的;
  2. WORKDIR 被定義了兩次,由於前面階段定義的變量在後面的階段是用不了的;
  3. COPY --from=build-env 這個命令,能夠將指定階段的文件複製到當前階段來,這一步很關鍵,第一階段用.NET Core SDK構建出來的dll 文件,經過該命令複製到後面的階段來使用了;
  4. 最後一個FROM是microsoft/dotnet:2.1.0-aspnetcore-runtime,這是asp.net core 運行環境鏡像,最終鏡像的內容就是dotnet:2.1.0-aspnetcore-runtime和sdk的構建結果,而前面的sdk鏡像和最終構建結果無關;
image
相關文章
相關標籤/搜索