[Docker] docker build 속도 차이

.NET 으로 Docker 이미지를 빌드하고 있습니다.

A 프로젝트를 Image로 만들 때 현재는 B,C,D,E,F 프로젝트가 참조로 달려있고 그 밖에 Nuget 패키지도 약간 있습니다.

이 상태에서 Docker Build를 수행하면 시간이 5~10분 가량 소요되며, 간혹 grpc 통신 장애라는 내용이 발생하면서 취소된다는 로그가 남습니다. 단순히 빌드 시간이 길어서 그런건지 감이 잘 안잡히네요.

혹시 이 B,C,D,E,F 를 Nuget 패키지로 만들어서 A 프로젝트에 참조시키면, 빌드속도가 빨라지는지 여쭙니다.

아무래도 .NET에서 Docker 빌드할 때 발생하는 원리를 이해하지 못하다보니 이런 질문이 발생하는 것 같습니다.

아래는 Dockerfile 입니다. PAT 부분은 제거했습니다.

FROM mcr.microsoft.com/dotnet/runtime:5.0 AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["AwesomeSwagWeb/AwesomeAutoImageSlice/Nuget.config", "."]
COPY ["Translate/Translate/Translate/nuget.config", "./Translate/"]
COPY ["AwesomeSwagWeb/AwesomeAutoImageSlice/AwesomeAutoImageSlice.csproj", "./AwesomeAutoImageSlice/"]
COPY ["AwesomeSwagWeb/AwesomeSwagSDK/AwesomeSwagSDK.csproj", "./AwesomeSwagSDK/"]
COPY ["Crawling/ElevenStreet/ElevenStreet.csproj", "./Crawling/ElevenStreet/"]
COPY ["Crawling/NaverSmartStore/NaverSmartStore.csproj", "./Crawling/NaverSmartStore/"]
COPY ["ShopeeV2/ShopeeSDKV2/ShopeeSDKV2.csproj", "./ShopeeV2/ShopeeSDKV2/"]
COPY ["Translate/Translate/Translate/Translate.csproj", "./Translate/"]
COPY ["Crawling/GMarket/GMarket.csproj", "./Crawling/GMarket/"]
COPY ["AwesomeSwagWeb/AwesomeFunctionInfraStructure/AwesomeFunctionInfraStructure.csproj", "./AwesomeFunctionInfraStructure/"]

ARG PAT=localhost
RUN sed -i "s|</configuration>|<packageSourceCredentials><EcremmoceSDK><add key=\"Username\" value=\"PAT\" /><add key=\"ClearTextPassword\" value=\"${PAT}\" /></EcremmoceSDK></packageSourceCredentials></configuration>|" nuget.config
RUN wget -qO- https://aka.ms/install-artifacts-credprovider.sh | bash
ENV DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0
ENV NUGET_CREDENTIALPROVIDER_SESSIONTOKENCACHE_ENABLED true
ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS {\"endpointCredentials\": [{\"endpoint\":\"https://pkgs.dev.azure.com/ecremmoce/_packaging/EcremmoceSDK/nuget/v3/index.json\", \"username\":\"Email\", \"password\":\"PAT\"}]}

RUN dotnet restore "AwesomeAutoImageSlice/AwesomeAutoImageSlice.csproj"

COPY . .
WORKDIR "/src/AwesomeAutoImageSlice"
RUN dotnet build "AwesomeAutoImageSlice.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "AwesomeAutoImageSlice.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "AwesomeAutoImageSlice.dll"]

아래는 로그입니다.

PS docker build --tag awesomeautoimageslice:v1 -f ./AwesomeSwagWeb/AwesomeAutoImageSlice/Dockerfile .
[+] Building 2.4s (7/28)
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 2.60kB 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for mcr.microsoft.com/dotnet/sdk:5.0 0.1s
=> [internal] load metadata for mcr.microsoft.com/dotnet/runtime:5.0 0.0s
=> [internal] load build context 2.1s
=> => transferring context: 1.35MB 2.1s
=> [build 1/18] FROM mcr.microsoft.com/dotnet/sdk:5.0@sha256:c4e077f49300f7f624ae7624c87a12599c32c146d25dea6b62d4405d067a2ec1 2.1s
=> => resolve mcr.microsoft.com/dotnet/sdk:5.0@sha256:c4e077f49300f7f624ae7624c87a12599c32c146d25dea6b62d4405d067a2ec1 0.0s
=> => sha256:9de0f41d10e468114e385ab1160a345f5fc22a08b9470d94a17e58fd9e60846e 13.63MB / 27.56MB 2.1s
=> => sha256:9a62ac752fdce16f8531a11e900d9851a6316fd978a23e2a589fc4534fd7d6c7 14.68MB / 106.09MB 2.1s
=> => sha256:d11f0b2c983ad35ae7b129745ce4bc33c29720f4e746658fb856a776271c013e 2.01kB / 2.01kB 0.0s
[+] Building 464.0s (10/28)
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 2.60kB 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for mcr.microsoft.com/dotnet/sdk:5.0 0.1s
=> [internal] load metadata for mcr.microsoft.com/dotnet/runtime:5.0 0.0s
=> ERROR [internal] load build context 463.8s
=> => transferring context: 5.77GB 386.1s
=> [build 1/18] FROM mcr.microsoft.com/dotnet/sdk:5.0@sha256:c4e077f49300f7f624ae7624c87a12599c32c146d25dea6b62d4405d067a2ec1 13.2s
=> => resolve mcr.microsoft.com/dotnet/sdk:5.0@sha256:c4e077f49300f7f624ae7624c87a12599c32c146d25dea6b62d4405d067a2ec1 0.0s
=> => sha256:9de0f41d10e468114e385ab1160a345f5fc22a08b9470d94a17e58fd9e60846e 27.56MB / 27.56MB 3.5s
=> => sha256:9a62ac752fdce16f8531a11e900d9851a6316fd978a23e2a589fc4534fd7d6c7 106.09MB / 106.09MB 6.6s
=> => sha256:d11f0b2c983ad35ae7b129745ce4bc33c29720f4e746658fb856a776271c013e 2.01kB / 2.01kB 0.0s
=> => sha256:4541344c527ed4f6515a5408c21c56a032b1087ddda44314e0d5bc91d4fa6138 7.11kB / 7.11kB 0.0s
=> => sha256:d1c77e057844e46417d0d034b7a976e2f0a36b9f40e3abb2371a89d2b7f4eadc 8.65MB / 8.65MB 1.6s
=> => sha256:c4e077f49300f7f624ae7624c87a12599c32c146d25dea6b62d4405d067a2ec1 2.17kB / 2.17kB 0.0s
=> => sha256:3bcabca0b205c751ff0f7d8178bf36817aac273eacc8fa79164daa823d19b6c1 12.69MB / 12.69MB 3.3s
=> => extracting sha256:d1c77e057844e46417d0d034b7a976e2f0a36b9f40e3abb2371a89d2b7f4eadc 0.4s
=> => extracting sha256:9de0f41d10e468114e385ab1160a345f5fc22a08b9470d94a17e58fd9e60846e 2.0s
=> => extracting sha256:9a62ac752fdce16f8531a11e900d9851a6316fd978a23e2a589fc4534fd7d6c7 5.4s
=> => extracting sha256:3bcabca0b205c751ff0f7d8178bf36817aac273eacc8fa79164daa823d19b6c1 0.7s
=> [base 1/2] FROM mcr.microsoft.com/dotnet/runtime:5.0 0.0s
=> CACHED [base 2/2] WORKDIR /app 0.0s
=> CACHED [final 1/2] WORKDIR /app 0.0s
=> [build 2/18] WORKDIR /src 0.5s
------CHED [final 1/2] WORKDIR /app 0.0s
[internal] load build context:
rpc error: code = Canceled desc = grpc: the client connection is closing


PS C:\Users\user\source\repos\christian289_Ecremmoce> docker build --tag awesomeautoimageslice:v1 -f ./AwesomeSwagWeb/AwesomeAutoImageSlice/Dockerfile .
[+] Building 579.3s (10/28)
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 32B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for mcr.microsoft.com/dotnet/sdk:5.0 0.0s
=> [internal] load metadata for mcr.microsoft.com/dotnet/runtime:5.0 0.0s
=> CANCELED [internal] load build context 579.0s
=> => transferring context: 4.87GB 578.4s
=> [build 1/18] FROM mcr.microsoft.com/dotnet/sdk:5.0 0.0s
=> [base 1/2] FROM mcr.microsoft.com/dotnet/runtime:5.0 0.0s
=> CACHED [base 2/2] WORKDIR /app 0.0s
=> CACHED [final 1/2] WORKDIR /app 0.0s
=> CACHED [build 2/18] WORKDIR /src 0.0s
context canceled


PS C:\Users\user\source\repos\christian289_Ecremmoce> docker build --tag awesomeautoimageslice:v1 -f ./AwesomeSwagWeb/AwesomeAutoImageSlice/Dockerfile .
[+] Building 658.2s (9/28)
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 2.70kB 0.0s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 2B
=> [internal] load build definition from Dockerfile 0.1scrosoft.com/dotnet/sdk:5.0
=> => transferring dockerfile: 2.70kB 0.0scrosoft.com/dotnet/runtime:5.0
=> [internal] load .dockerignore 0.1sm/dotnet/sdk:5.0
=> => transferring context: 2B 0.0s
=> [internal] load metadata for mcr.microsoft.com/dotnet/sdk:5.0 0.0s
=> [internal] load metadata for mcr.microsoft.com/dotnet/runtime:5.0 0.0sotnet/runtime:5.0
=> [build 1/18] FROM mcr.microsoft.com/dotnet/sdk:5.0 0.0s
[+] Building 755.2s (21/28)
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 2.70kB 0.0s
=> [internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for mcr.microsoft.com/dotnet/sdk:5.0 0.0s
=> [internal] load metadata for mcr.microsoft.com/dotnet/runtime:5.0 0.0s
=> [build 1/18] FROM mcr.microsoft.com/dotnet/sdk:5.0 0.0s
=> [internal] load build context 749.6s
=> => transferring context: 26.22GB 749.0s
=> [base 1/2] FROM mcr.microsoft.com/dotnet/runtime:5.0 0.0s
=> CACHED [base 2/2] WORKDIR /app 0.0s
=> CACHED [final 1/2] WORKDIR /app 0.0s
=> CACHED [build 2/18] WORKDIR /src 0.0s
=> [build 3/18] COPY [AwesomeSwagWeb/AwesomeAutoImageSlice/Nuget.config, .] 3.5s
=> [build 4/18] COPY [Translate/Translate/Translate/nuget.config, ./Translate/] 0.2s
=> [build 5/18] COPY [AwesomeSwagWeb/AwesomeAutoImageSlice/AwesomeAutoImageSlice.csproj, ./AwesomeAutoImageSlice/] 0.1s
=> [build 6/18] COPY [AwesomeSwagWeb/AwesomeSwagSDK/AwesomeSwagSDK.csproj, ./AwesomeSwagSDK/] 0.1s
=> [build 7/18] COPY [Crawling/ElevenStreet/ElevenStreet.csproj, ./Crawling/ElevenStreet/] 0.1s
=> [build 8/18] COPY [Crawling/NaverSmartStore/NaverSmartStore.csproj, ./Crawling/NaverSmartStore/] 0.1s
=> [build 9/18] COPY [ShopeeV2/ShopeeSDKV2/ShopeeSDKV2.csproj, ./ShopeeV2/ShopeeSDKV2/] 0.1s
=> [build 10/18] COPY [Translate/Translate/Translate/Translate.csproj, ./Translate/] 0.1s
=> [build 11/18] COPY [Crawling/GMarket/GMarket.csproj, ./Crawling/GMarket/] 0.1s
=> [build 12/18] COPY [AwesomeSwagWeb/AwesomeFunctionInfraStructure/AwesomeFunctionInfraStructure.csproj, ./AwesomeFunctionInfraStructure/] 0.1s
=> ERROR [build 13/18] RUN sed -i “s|||” nuget.config 0.5s
[build 13/18] RUN sed -i “s|||” nuget.config:
#21 0.421 sed: can’t read nuget.config: No such file or directory
executor failed running [/bin/sh -c sed -i “s||<add key=“Username” value=“PAT” /><add key=“ClearTextPassword” value=”${PAT}" />|" nuget.config]: exit code: 2
PS C:\Users\user\source\repos\christian289_Ecremmoce>

위 로그는 docker build를 3회 수행한 로그입니다.

좋아요 1

프로젝트 참조는 빌드가 시작되면 참조된 프로젝트가 순차적으로 빌드한 뒤 본 프로젝트가 빌드되고, nuget을 이용하면 이미 빌드된 dll을 가져오는 거라 차이가 있을 것 같아요.

좋아요 4

네 결국 실제로 해봤는데 엄청나게 빨라졌습니다.

내부적으로 Docker 이미지를 빌드할 때는 프로젝트 참조를 걷어내고 Nuget 패키지만 참조해서 Docker 이미지로 만들거나 배포하는 것으로 협의했습니다.

좋아요 3