Docker多阶段构建实战(multi-stage builds)
在编写dockerfile构建docker镜像时,常遇到以下问题:
- run命令会让镜像新增layer,导致镜像变大,虽然通过&&连接多个命令能缓解此问题,但如果命令之间用到docker指令例如copy、workdir等,依然会导致多个layer;
- 有些工具在构建过程中会用到,但是最终的镜像是不需要的(例如用maven编译构建java工程),这要求dockerfile的编写者花更多精力来清理这些工具,清理的过程又可能导致新的layer;
为了解决上述问题,从17.05版本开始docker在构建镜像时增加了新特性:多阶段构建(multi-stage builds),将构建过程分为多个阶段,每个阶段都可以指定一个基础镜像,这样在一个dockerfile就能将多个镜像的特性同时用到,例如:先用sdk镜像构建.net core工程,再把构建结果和runtime 合成,就做成了一个可以直接运行.net core工程镜像了;
官方描述如下图所示,地址是:
官方的实例是golang的,今天我们以.net core构建asp.net core工程为例,介绍如何使用multi-stage特性构建.net core微服务镜像;
dockerfile文件参见: https://github.com/geffzhang/aks-learning-series/blob/master/src/techtalksweb/dockerfile
### 第一阶段,用sdk 镜像进行编译
from microsoft/dotnet:2.1.300-sdk as build-env
workdir /techtalksweb
copy nuget.config ./
copy techtalksweb.csproj ./
run dotnet restore
copy . ./
#编译构建
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脚本,请参考每行的注释来理解,有以下几点需要重点关注:
- 一共有两次from指令出现,而最终的镜像是基于最后一个from生成的;
- workdir 被定义了两次,因为前面阶段定义的变量在后面的阶段是用不了的;
- copy --from=build-env 这个命令,可以将指定阶段的文件复制到当前阶段来,这一步很关键,第一阶段用.net core sdk构建出来的dll 文件,通过该命令复制到后面的阶段来使用了;
- 最后一个from是microsoft/dotnet:2.1.0-aspnetcore-runtime,这是asp.net core 运行环境镜像,最终镜像的内容就是dotnet:2.1.0-aspnetcore-runtime和sdk的构建结果,而前面的sdk镜像和最终构建结果无关;
上一篇: C#调用7z实现文件的压缩与解压
下一篇: 2.reset.css文件