优化 ASP.NET Core Docker 镜像的大小
<p>在这容器化的世界里,我们已经很少直接通过文件发布来运行asp.net core程序了。现在大多数情况下,我们都会使用docker来运行程序。在使用docker之前,我们往往需要打包我们的应用程序。asp.net core程序的镜像打包,网上有很多教程,其中大多数是使用sdk这个镜像来直接打包。打出来的包有好几百MB,3.1 SDK打出来的包甚至超过了1GB。那么有什么办法来缩小我们打出来的镜像吗?最小能缩小到多少呢?这篇文章就来介绍下如何缩小asp.net core 打包出来镜像的大小。</p><h2 id="新建aspnet-core-程序">新建asp.net core 程序</h2>
<p><img src="https://ftp.bmp.ovh/imgs/2021/03/d478a45b4738f630.png" alt="" loading="lazy"><br>
新建一个asp.net core应用程序,用来演示打包。首先我们演示下如果使用dotnet sdk5.0来打包 docker 镜像。</p>
<h2 id="sdk50">sdk:5.0</h2>
<pre><code>FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /app
COPY /. /app
RUN dotnet restore -s https://nuget.cdn.azure.cn/v3/index.json
WORKDIR /app/CoreDockerImageSizeTest
RUN dotnet publish -o ./out -c Release
EXPOSE 5000
ENTRYPOINT ["dotnet", "out/CoreDockerImageSizeTest.dll"]
</code></pre>
<p>在项目根目录下新建一个Dockerfile文件,文件内容如上。这个Dockerfile比较简单,使用dotnet sdk:5.0最为底层包来构建,这也是最傻瓜的打包方式。那么看看这个镜像打出来有多大吧。</p>
<pre><code>docker build . -t coredockerimagesizetest_0.1
</code></pre>
<p>使用docker build命令进行打包。</p>
<pre><code>REPOSITORY TAG IMAGE ID CREATED SIZE
coredockerimagesizetest_0.1 latest 14aea8e0c1d5 5 seconds ago 643MB
</code></pre>
<p>使用docker images命令来查看镜像列表,我们发现我们打出来的镜像居然有643MB,真的很大。如果是内网还好一点,如果在镜像存在docker hub等第三方仓库,这得下半天。显然这个镜像太大了,接下来看我们如何进行优化。</p>
<h2 id="sdk50-buster-slim">sdk:5.0-buster-slim</h2>
<p>最新的VisualStudio内置了docker工具,可以自动为我们生成Dockerfile文件。我们来看看它生成的镜像文件有多大。<br>
<img src="https://ftp.bmp.ovh/imgs/2021/03/03063451a26ef4bd.png" alt="" loading="lazy"><br>
右键解决方案=>添加=>Docker支持=>Linux 。<br>
选择完成后VS会为我们自动添加一个Dockerfile在根目录。</p>
<pre><code>FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
EXPOSE 5000
FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build
WORKDIR /src
COPY ["CoreDockerImageSizeTest/CoreDockerImageSizeTest.csproj", "CoreDockerImageSizeTest/"]
RUN dotnet restore "CoreDockerImageSizeTest/CoreDockerImageSizeTest.csproj"
COPY . .
WORKDIR "/src/CoreDockerImageSizeTest"
RUN dotnet build "CoreDockerImageSizeTest.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "CoreDockerImageSizeTest.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "CoreDockerImageSizeTest.dll"]
</code></pre>
<p>这个自动生成的Dockerfile使用了sdk:5.0-buster-slim这个镜像进行build跟publish,使用aspnet:5.0-buster-slim这个runtime级别的镜像做为final底包。从名字来看,很明显slim代表着轻量。让我们试试这个Dockerfile打出来的包有多大。</p>
<pre><code>REPOSITORY TAG IMAGE ID CREATED SIZE
coredockerimagesizetest_0.2 latest 0a24618f6ece 11 seconds ago 210MB
</code></pre>
<p>使用docker build命令进行打包。使用docker images命令查看镜像的大小,这个镜像的大小为210MB。果然比上面的镜像小了很多。那么是否还能继续缩小镜像的大小呢?继续往下看。</p>
<h2 id="50-alpine">5.0-alpine</h2>
<p>除了使用buster-slim镜像,我们还可以选择更加小巧的alpine镜像来打包。alpine镜像是继续alpine linux创建的镜像,所以它更加轻量级更加小巧。<br>
关于alpine linux可以查看这篇:Alpine Linux 与 CentOS 有什么区别? 。</p>
<pre><code>FROM mcr.microsoft.com/dotnet/aspnet:5.0-alpine AS base
WORKDIR /app
EXPOSE 5000
FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS build
WORKDIR /src
COPY ["CoreDockerImageSizeTest/CoreDockerImageSizeTest.csproj", "CoreDockerImageSizeTest/"]
RUN dotnet restore "CoreDockerImageSizeTest/CoreDockerImageSizeTest.csproj"
COPY . .
WORKDIR "/src/CoreDockerImageSizeTest"
RUN dotnet build "CoreDockerImageSizeTest.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "CoreDockerImageSizeTest.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "CoreDockerImageSizeTest.dll"]
</code></pre>
<p>修改Dockerfile使用aspnet:5.0-alpine及sdk:5.0-alpine来构建这个镜像。</p>
<pre><code>REPOSITORY TAG IMAGE ID CREATED SIZE
coredockerimagesizetest_0.3 latest db34d613e21a 12 seconds ago 108MB
</code></pre>
<p>使用docker build命令进行打包。使用docker images命令查看镜像的大小,这个镜像的大小为108MB。现在这个镜像已经比我们第一次打包减少了500多MB了。那么还能更小吗?请往下看。</p>
<h2 id="runtime-deps50-alpine">runtime-deps:5.0-alpine</h2>
<p>最新的.net core程序支持自宿主及单文件发布。如果采用以上发布形式,那么我们可以选择使用runtime-deps:5.0-alpine做为最终底包来打包我们的镜像。</p>
<pre><code>FROM mcr.microsoft.com/dotnet/aspnet:5.0-alpine AS base
WORKDIR /app
EXPOSE 5000
FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS build
WORKDIR /src
COPY ["CoreDockerImageSizeTest/CoreDockerImageSizeTest.csproj", "CoreDockerImageSizeTest/"]
RUN dotnet restore "CoreDockerImageSizeTest/CoreDockerImageSizeTest.csproj"
COPY . .
WORKDIR "/src/CoreDockerImageSizeTest"
RUN dotnet build "CoreDockerImageSizeTest.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "CoreDockerImageSizeTest.csproj" -c Release -o /app/publish \
--runtime alpine-x64 \
--self-contained true \
/p:PublishTrimmed=true \
/p:PublishSingleFile=true
FROM mcr.microsoft.com/dotnet/runtime-deps:5.0-alpine AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["./CoreDockerImageSizeTest"]
</code></pre>
<p>修改Dockerfile,使用/runtime-deps:5.0-alpine做为final镜像。</p>
<pre><code>REPOSITORY TAG IMAGE ID CREATED SIZE
coredockerimagesizetest_0.5 latest dab1289626f9 6 seconds ago 54.6MB
</code></pre>
<p>使用docker build命令进行打包。使用docker images命令查看镜像的大小,这个镜像的大小为54.6MB。</p>
<h2 id="总结">总结</h2>
<p>通过以上演示,我们的镜像大小从一开始的600多MB缩小到了54MB。一般生产我主要选择buster-slim这个镜像来打包。如果选择runtime-deps打包,打出来的包是最小的,虽然演示项目是可以运行的,但是本人没有在生产使用过,还请谨慎使用。<br>
代码在这:CoreDockerImageSizeTest</p>
<h2 id="关注我的公众号一起玩转技术">关注我的公众号一起玩转技术</h2>
<p><img src="https://s1.ax1x.com/2020/06/29/NfQjds.jpg" alt="" loading="lazy"></p>
</div>
<div id="MySignature" role="contentinfo">
<div id="AllanboltSignature">
<p id="PSignature" style="border-top: #e0e0e0 1px dashed; border-right: #e0e0e0 1px dashed; border-bottom: #e0e0e0 1px dashed; border-left: #e0e0e0 1px dashed; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; font-family: 微软雅黑; font-size: 11px">
QQ群:1022985150 VX:kklldog 一起探讨学习.NET技术
<br>
作者:Agile.Zhou(kklldog)
<br>
出处:http://www.cnblogs.com/kklldog/
<br>本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
</p>
</div><br><br>
来源:https://www.cnblogs.com/kklldog/p/netcore-docker-image-size.html
頁:
[1]