【问题标题】:How can I cache C# dotnet core package in Dockerfile properly?如何在 Dockerfile 中正确缓存 C# dotnet 核心包?
【发布时间】:2018-11-27 23:48:02
【问题描述】:

我正在尝试构建高效的dockerfile,因此只有在删除/添加/更新包时才会触发包还原。这是我尝试过的(基于official sample):

FROM microsoft/dotnet:2.0-sdk-stretch AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY ./src/myapp.csproj ./
RUN dotnet restore && \
    dotnet add package ILLink.Tasks -v 0.1.4-preview-981901 -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json

# Copy everything else and build
COPY ./src ./
RUN dotnet publish -c Release -o out -r linux-x64

# Build runtime image
FROM microsoft/dotnet:2.0-runtime-deps
RUN useradd -d /home/dotnet -ms /bin/bash dotnet
USER dotnet
WORKDIR /home/dotnet/app
ENV ASPNETCORE_URLS=http://+:9999
COPY --from=build-env /app/out ./
ENTRYPOINT ["./myapp"]

我正在复制csprog,运行dotnet restore,然后复制其余文件,然后构建。这应该具有预期的行为 - 仅在需要时恢复包。但这不是发生的事情 - 出于某种原因(在文档中找不到任何关于它的内容)dotnet publish 触发恢复,尽管包已经被缓存:

Sending build context to Docker daemon  131.3MB
Step 1/13 : FROM microsoft/dotnet:2.0-sdk-stretch AS build-env
 ---> 17fc4fa98e0b
Step 2/13 : WORKDIR /app
 ---> Using cache
 ---> 9b13d975844b
Step 3/13 : COPY ./src/myapp.csproj ./
 ---> Using cache
 ---> fed39192abce
Step 4/13 : RUN dotnet restore &&     dotnet add package ILLink.Tasks -v 0.1.4-preview-981901 -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json
 ---> Using cache
 ---> efcdaf201661
Step 5/13 : COPY ./src ./
 ---> a50fd8fa6106
Removing intermediate container 9eadb5543dbe
Step 6/13 : RUN dotnet publish -c Release -o out -r linux-x64
 ---> Running in 3bf17790a376
Microsoft (R) Build Engine version 15.7.177.53362 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restoring packages for /app/myapp.csproj...
  Restore completed in 1.4 sec for /app/Hamuste.csproj.
  Installing <redacted>
  Installing <redacted>
  Installing <redacted>

我错过了什么?如何改进这个 docker 文件?

【问题讨论】:

  • myapp 是否有其他项目依赖项? app/Hamuste.csproj 是什么?
  • 我忘记编辑的东西 :) 不,csproj 只有常规的 NuGet 依赖项。
  • 你找到答案了吗?

标签: c# docker .net-core docker-build


【解决方案1】:

总的来说,它看起来是正确的。 dotnet publish(或dotnet build)将触发包恢复——这是你不能忽略的。但它应该只是确保一切都到位,而不是安装任何东西。

但是我怀疑是dotnet add package 导致了这个问题。我从未使用过该命令,但从https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-add-package 我了解,它只是将包添加到依赖项,然后您应该运行dotnet restore。 Doc 说,您不必这样做,因为 new build run(显然是 publish)无论如何都会运行 restore

我的建议是您恢复第 4/13 步命令。首先,执行dotnet add package,然后执行dotnet restore。或之后添加另一个dotnet restore。 看看这是否有帮助。

如果没有帮助,请尝试跟踪在publish 期间安装了哪些软件包。也许第 5/13 步(COPY ..)覆盖了 dotnet add package 创建的条目,而 publish 中的 restore 只是带​​回了 add package 删除的内容。

【讨论】:

  • 更改顺序(dotnet adddotnet restore)没有帮助。它可能与 COPY 指令有关,但我不确定如何解决:(
  • 您可以跳过构建阶段的dotnet add package 并将其简单地放入csproj 文件中吗?为什么在构建脚本时需要它?
  • 它在那里是因为我正在创建一个自包含的应用程序(嗯,几乎是自包含的:))这是基于 Microsoft 官方示例构建自包含应用程序,所以我想这很重要...
  • 你所有的 dockerfile 都是正确的。我有相同的结构,它完美地工作。唯一的区别是这个dotnet add package 电话。 AFAIK 此命令将在开发期间使用,而不是在构建期间使用。它修改 csproj 文件。我认为你应该从 dockerfile 中删除它,只需在你的电脑上调用它并提交它所做的更改。
  • 哦,是的,你可能是对的。添加后的 COPY 重新复制 csporj,这可能会触发它。我会检查并更新
【解决方案2】:

--no-restore 添加到您的dotnet publish 命令中。

如果您正在构建一个包含多个已发布项目并共享本地依赖项的多项目解决方案,请另外添加一个构建步骤:RUN dotnet build -c Release --no-restore PROJECT_NAME,然后在单独的命令 RUN dotnet publish -c Release -o out --no-restore --no-build PROJECT_NAME 中发布。这样构建层可以被重用和缓存以发布后续项目。

【讨论】:

    猜你喜欢
    • 2019-04-26
    • 2017-09-27
    • 2020-02-18
    • 2017-12-07
    • 1970-01-01
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    相关资源
    最近更新 更多