在 Visual Studio 中使用相同的 docker 文件构建 docker 映像的 Azure Pipeline 失败

Posted

技术标签:

【中文标题】在 Visual Studio 中使用相同的 docker 文件构建 docker 映像的 Azure Pipeline 失败【英文标题】:Azure Pipeline to build docker images fails using same docker file in Visual Studio 【发布时间】:2019-10-16 14:45:49 【问题描述】:

我正在尝试创建一个部署管道以将我的映像部署到 Kubernetes 集群。此过程的第一步是基于 docker 文件创建映像。我正在使用的 docker 文件是在我添加 docker 支持时从 Visual Studio 生成的,并在右键单击 docker 图像并选择创建它时成功创建了图像。当我配置 Azure Pipeline 时,创建 docker 映像一旦尝试构建实际解决方案就会失败。上一步抓取了所有源文件,但随后在 docker 镜像创建中失败了

[error]COPY failed: stat/var/lib/docker/tmp/docker-builder158012929/DockerTest/DockerTest.csproj:
 no such file or directory

[error]/usr/bin/docker failed with return code: 1

以下是从 Visual Studio 生成的 docker 文件,并被 azure 管道阶段引用以创建 docker 映像。

 FROM mcr.microsoft.com/dotnet/core/runtime:2.2-stretch-slim AS base

 WORKDIR /app   
 FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS
 build 

 WORKDIR /src      
 COPY ["DockerTest/DockerTest.csproj", "DockerTest/"]      
 RUN dotnet restore "DockerTest/DockerTest.csproj"      
 COPY . .      
 WORKDIR "/src/DockerTest"      
 RUN dotnet build "DockerTest.csproj" -c Release -o /app  

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

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

##[section]开始:构建容器镜像 ==================================================== ============================ 任务:Docker 描述:构建、标记、推送或运行 Docker 映像,或 运行 Docker 命令。任务可以与 Docker 或 Azure 容器一起使用 注册表。版本:0.150.6 作者:Microsoft Corporation 帮助: [更多信息]https://go.microsoft.com/fwlink/?linkid=848006) ==================================================== ============================ [命令]/usr/bin/docker build -f /home/vsts/work/1/s/DockerTest/Dockerfile -t ihacontainers.azurecr.io/dockertest:6 /home/vsts/work/1/s/DockerTest 将构建上下文发送到 Docker 守护进程 6.144kB 步骤 1/15:FROM mcr.microsoft.com/dotnet/core/runtime:2.2-stretch-slim AS 基础 2.2-stretch-slim:从 dotnet/core/runtime 拉取 743f2d6c1f65:拉取 fs 层 074da88b8de0:拉取 fs 层 ac831735b47a:拉取 fs layer 3adcc844418d: 拉取 fs layer 3adcc844418d: Waiting ac831735b47a:下载完成 743f2d6c1f65:验证校验和 743f2d6c1f65:下载完成 074da88b8de0:验证校验和 074da88b8de0:下载完成 3adcc844418d:验证校验和 zadcc844418d:下载完成 743f2d6c1f65:拉取完成 074da88b8de0:拉动完成 ac831735b47a:拉动完成 3adcc844418d: 拉取完整的摘要: sha256:066c31b113b0a20e6155d3bd8a314563c688d2ec31c11d7e551af5bc2595f30c 状态:已下载更新的图像 mcr.microsoft.com/dotnet/core/runtime:2.2-stretch-slim ---> c0f9ab44ecc1 步骤 2/15:WORKDIR /app ---> 在 6d1a5f5600dd 中运行 移除中间容器 6d1a5f5600dd ---> 527fcebeaf1f 步骤 3/15:来自 mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS 构建 2.2-stretch:从dotnet/core/sdk拉c5e155d5a1d1:拉fs层221d80d00ae9:拉fs层4250b3117dca:拉fs层 3b7ca19181b2:拉 fs 层 3466298fc231:拉 fs 层 310737d73ed1:拉取 fs 层 dc981de74fae:拉取 fs 层 3b7ca19181b2:等待 3466298fc231:等待 310737d73ed1:等待 dc981de74fae:等待 4250b3117dca:验证校验和 4250b3117dca: 下载完整的 221d80d00ae9:验证校验和 221d80d00ae9: 下载完整的 3466298fc231:验证校验和 3466298fc231: 下载完整的 c5e155d5a1d1:验证校验和 c5e155d5a1d1: 下载完整的 3b7ca19181b2:验证校验和 3b7ca19181b2: 下载完成 c5e155d5a1d1:拉取完成 221d80d00ae9:拉取 完成 310737d73ed1:验证校验和 310737d73ed1:下载 完成 4250b3117dca:提取完成 dc981de74fae:验证校验和 dc981de74fae:下载完成 3b7ca19181b2:拉取完成 3466298fc231:拉动完成 310737d73ed1:拉动完成 dc981de74fae: 拉取完整的摘要: sha256:222cc0bb0bc93875ee0f6be626b2838beea838f65e53653e07c33eb9d00b0163 状态:已下载更新的图像 mcr.microsoft.com/dotnet/core/sdk:2.2-stretch ---> e4747ec2aaff 步骤 4/15 : WORKDIR /src ---> 在 a7ebcac87f68 中运行 中间容器 a7ebcac87f68 ---> d7541674a9da 步骤 5/15: 复制 ["DockerTest/DockerTest.csproj", "DockerTest/"] 复制失败:统计 /var/lib/docker/tmp/docker-builder158012929/DockerTest/DockerTest.csproj:no 这样的文件或目录

##[错误]复制失败:stat/var/lib/docker/tmp/docker-builder158012929/DockerTest/DockerTest.csproj:no 这样的文件或目录

##[error]/usr/bin/docker failed with return code: 1 ##[section]Finishing: Build a container image

【问题讨论】:

【参考方案1】:

我通过使用与 Visual Studio 中相同的 dockerfile 将 buildContext 设置为“$(Build.Repository.LocalPath)”解决了这个问题,而无需调整路径:

在 YAML-Konfiguration 中,我添加了以下行:

buildContext: '$(Build.Repository.LocalPath)'

【讨论】:

这应该是公认的答案。 Pipelines 默认在 Dockerfile 所在的目录(在项目级别)中运行命令,而 Visual Studio 在 Repository/Solution 级别运行它 这对我也有用.. 确保将它放在设置:输入下的 yaml 文件中(无论如何都在天蓝色)。我也在当地为此苦苦挣扎。但结果是一样的.. 指定你的 dockerfile 或根目录的相对路径 你也可以使用 buildContext: '$(Build.SourcesDirectory)',因为 $(Build.SourcesDirectory) 是 $(Build.Repository.LocalPath) 的同义词。见docs.microsoft.com/en-us/azure/devops/pipelines/build/…【参考方案2】:

[错误]复制失败:stat/var/lib/docker/tmp/docker-builder158012929/DockerTest/DockerTest.csproj:没有这样的文件或目录

根据这个错误信息,错误发生在你的dockerfile的那一行:COPY ["DockerTest/DockerTest.csproj", "DockerTest/"]

首先,请确认您没有使用.dockerignore 文件排除此文件:DockerTest/DockerTest.csproj,该文件必须存在于您运行构建的目录中。

如果.dockerignore 文件没有忽略它,那么您需要考虑您的 dockerfile 位置级别。

DockerTest.csproj 文件不应放在较低的源文件路径级别。您需要更改上下文的来源,将其移动到更高的级别。所以手动修改你的dockerfile:

COPY ["DockerTest.csproj", "DockerTest/"]

【讨论】:

所以这确实让我克服了第一个错误,但现在它抱怨它在运行以下命令时没有合适的静态主入口点(当然它确实如此)。运行 dotnet build "DockerTest.csproj" -c Release -o /app 程序不包含适合入口点的静态“Main”方法[/src/DockerTest/DockerTest.csproj] 另一个副作用是现在从 Visual Studio 本地构建 docker 映像失败,因为我们更改了位置。也许有办法在获取源代码时从构建管道中设置正确的位置,这样我就不必修改dockerfile了。 实际上我认为我已修复它并允许它在任一位置工作。我恢复到工作室生成的原始 dockerfile,然后我取消选中构建映像任务上的“使用默认构建上下文”,然后清除它列出的文件夹“DockerTest”。现在整个事情从天蓝色和本地完成。感谢您的帮助。 @Geekn 的最新评论为我解决了这个问题(取消选中使用默认构建上下文)。它应该被添加为答案并标记为最佳答案!【参考方案3】:

当您通过 Visual Studio(至少 v16.3.9)生成 Docker 支持并且您在 Azure Pipeline 中使用预定义的 Docker 管道模板或在老式的一切点击中使用此生成的项目时,会出现此问题称为经典编辑器的方式或称为现代编辑器的新 4 步易于点击的方式。

生成文件的变化来自

COPY ["DockerTest/DockerTest.csproj", "DockerTest/"]

COPY ["DockerTest.csproj", "DockerTest/"]

使用 Azure Pipeline 解决问题,但它会破坏您在 Visual Studio 中的本地构建。

添加

buildContext: '$(Build.Repository.LocalPath)'

现代编辑器生成的 YAML 文件会破坏构建任务。现代编辑器中使用的模板依赖于默认构建上下文,解析器将无法识别buildContext 命令。

解决此问题的唯一可能方法是覆盖默认构建上下文。此覆盖将在 Visual Studio 或 Azure Pipeline 中保留构建功能。

可以在经典编辑器的构建映像任务中覆盖构建上下文。

【讨论】:

您在此处看到的“意外属性 buildContext”错误是由于属性缩进不正确造成的。它需要缩进到与“命令”属性相同的级别 @JeffreyABecker 实际上,这是 YAML 解析器中的一个问题。如果我尝试手动更新文件,解析器会让我这样做,因为无论我把它放在哪里,解析器都会识别出带有构建上下文的行。如果我使用任务 Web 表单,一切正常。【参考方案4】:

对我来说,它适用于以下 yaml 设置

步骤:

任务:Docker@2

displayName:构建泊坞窗

输入:

命令:'buildAndPush'

Dockerfile: '**/Dockerfile'

buildContext: '$(Build.Repository.LocalPath)'

dockerfile 可以保留为 Visual Studio 生成的。

【讨论】:

【参考方案5】:

就我而言,我的文件夹结构如下:

+-- [REPOSITORY FOLDER]
|   +-- [SOLUTION FOLDER]
|   |   +-- [*.SLN]
|   |   +-- [PROJECT Folder]
|   |   |   +-- [*.CSPROJ]
|   |   |   +-- [dockerfile]

我的 docker 文件在项目文件夹中。 在修改为仅使用第一个副本中的 CSPROJ 文件后,收到缺少的 MAIN 方法错误,没有合适的静态主入口点,我修复了它,将“copy ..”替换为“COPY . [project_name]/”


FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["SampleApi1.csproj", "SampleApi1/"]
RUN dotnet restore "SampleApi1/SampleApi1.csproj"
COPY . SampleApi1/
WORKDIR "/src/SampleApi1"
RUN dotnet build "SampleApi1.csproj" -c Release -o /app/build

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

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

【讨论】:

【参考方案6】:

尝试将 Dockerfile 移至根目录,以及 .sln 文件。

其他答案都不适合我,它永远找不到 csproj 文件的项目路径。

我的项目只包含一个需要容器化的项目,还有一些支持dll的项目,所以我把Visual Studio创建的原始Dockerfile和.sln文件一起移到了根目录下,我们的管道构建了镜像并部署了它到我们的 ACR 没问题。

我认为其他解决方案,如果它们对你有用,会更好,但如果不是,它会在你的情况下工作,试一试。

【讨论】:

以上是关于在 Visual Studio 中使用相同的 docker 文件构建 docker 映像的 Azure Pipeline 失败的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Visual Studio 中显示特定提示

Visual Studio:XP和Windows7中相同可执行文件的内存大小不同

DEVc++ 和 Visual Studio 有相同的库吗?

Visual Studio 2013 - 添加对前台应用程序和后台任务的相同引用

在 Visual Studio 中构建错误

Visual Studio相同的标记突出显示