優化 .net core 應用的 dockerfile Intro 在給 .net core 應用的寫 dockerfile 的時候一直有個苦惱,就是如果有很多個項目,在 dockerfile 里寫起來就會很繁瑣,有很多項目文件要 copy,dockerfile 還不支持直接批量複製項目文件,今天要 ...
優化 .net core 應用的 dockerfile
Intro
在給 .net core 應用的寫 dockerfile 的時候一直有個苦惱,就是如果有很多個項目,在 dockerfile 里寫起來就會很繁瑣,有很多項目文件要 copy,dockerfile 還不支持直接批量複製項目文件,今天要改的一個項目也是有好多個項目文件,不想再一個一個複製,於是 google 一下看有沒有比較好的解決方案,找到一個折中的解決方案,分享一下
Solution
- 首先把所有的項目文件拷貝到 docker 鏡像內
COPY */*.csproj ./
- 然後根據項目文件名稱創建項目文件夾,並移動項目文件到對應的項目目錄下
原來的 dockerfile
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-alpine AS build-env
WORKDIR /src
# Copy csproj and restore as distinct layers
COPY ActivityReservation.Common/*.csproj ActivityReservation.Common/
COPY ActivityReservation.Models/*.csproj ActivityReservation.Models/
COPY ActivityReservation.DataAccess/*.csproj ActivityReservation.DataAccess/
COPY ActivityReservation.Business/*.csproj ActivityReservation.Business/
COPY ActivityReservation.Helper/*.csproj ActivityReservation.Helper/
COPY ActivityReservation.WechatAPI/*.csproj ActivityReservation.WechatAPI/
COPY ActivityReservation.AdminLogic/*.csproj ActivityReservation.AdminLogic/
COPY ActivityReservation.API/*.csproj ActivityReservation.API/
COPY ActivityReservation/ActivityReservation.csproj ActivityReservation/
# RUN dotnet restore ActivityReservation/ActivityReservation.csproj
## diff between netcore2.2 and netcore3.0
WORKDIR /src/ActivityReservation
RUN dotnet restore
# copy everything and build
COPY . .
RUN dotnet publish -c Release -o out ActivityReservation/ActivityReservation.csproj
# build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-alpine
LABEL Maintainer="WeihanLi"
WORKDIR /app
COPY --from=build-env /src/ActivityReservation/out .
EXPOSE 80
ENTRYPOINT ["dotnet", "ActivityReservation.dll"]
修改之後的 dockerfile
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-alpine AS build-env
WORKDIR /src
# Copy csproj and restore as distinct layers
# https://andrewlock.net/optimising-asp-net-core-apps-in-docker-avoiding-manually-copying-csproj-files-part-2/
COPY */*.csproj ./
RUN for file in $(ls *.csproj); do mkdir -p ${file%.*}/ && mv $file ${file%.*}/; done
## diff between netcore2.2 and netcore3.0
WORKDIR /src/ActivityReservation
RUN dotnet restore
# copy everything and build
COPY . .
RUN dotnet publish -c Release -o out ActivityReservation/ActivityReservation.csproj
# build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-alpine
LABEL Maintainer="WeihanLi"
WORKDIR /app
COPY --from=build-env /src/ActivityReservation/out .
EXPOSE 80
ENTRYPOINT ["dotnet", "ActivityReservation.dll"]
是不是精簡了許多,來看一下修改前後的對比,更明顯的對比一下:
核心代碼:
# 拷貝所有的二級目錄下的項目文件
COPY */*.csproj ./
# 根據項目文件名稱創建項目文件夾,並移動項目文件到對應的項目目錄下
RUN for file in $(ls *.csproj); do mkdir -p ${file%.*}/ && mv $file ${file%.*}/; done
More
註:上面的方法適用於項目文件目錄名稱和項目文件名稱一致的情況,預設創建的項目應該都會符合這樣的要求,如果你的項目文件是三級目錄,如 src/*/*.csproj
的,需要自己根據項目情況調整 dockerfile
有沒有學到呢~~
Reference
- https://stackoverflow.com/questions/51372791/is-there-a-more-elegant-way-to-copy-specific-files-using-docker-copy-to-the-work
- https://andrewlock.net/optimising-asp-net-core-apps-in-docker-avoiding-manually-copying-csproj-files-part-2/
- https://github.com/WeihanLi/ActivityReservation/blob/dev/Dockerfile