我已经容器化了一个在.net framework 4.8上运行的简单Windows服务。应用程序和容器都可以使用此dockerfile在本地构建并正常运行:
FROM ourcontainerregistry.azurecr.io/net-framework-base:latest
WORKDIR /app
RUN cmd MSBuild.exe /property:Configuration=Release
COPY TopShelfServiceInstaller/bin/Release/ .
ENTRYPOINT ["TopShelfServiceInstaller.exe"]
当我在docker桌面上本地连接到容器时,我在C:/ app目录中看到了期望的文件,并可以确认该服务正在按预期运行。
但是,当我尝试使用Windows最新的构建代理在Azure Devops中的管道中运行此dockerfile时,我在COPY步骤中始终收到以下错误:
COPY failed: CreateFile \\?\C:\ProgramData\docker\tmp\docker-builder002424695\TopShelfServiceInstaller\bin\Release: The system cannot find the path specified.
有什么想法可能会发生这种情况以及如何解决?
编辑:azure-pipelines.yml用于构建:
resources:
repositories:
- repository: net-framework-base
type: git
name: Container_DotNetFrameworkBase
containers:
- container: net-framework-base
type: ACR
azureSubscription: ---
resourceGroup: ---
registry: ---
repository: net-framework-base
variables:
- name: dockerRegistryServiceConnection
value: ---
- name: imageRepository
value: "service"
- name: containerRegistry
value: ---
- name: prod-container-registry
value: ---
- name: dockerfilePath
value: "$(Build.SourcesDirectory)/Service/dockerfile"
- name: tag
value: "$(Build.BuildNumber)"
- name: vmImageName
value: "windows-latest"
trigger:
batch: true
branches:
include:
- feature/*
#pr:
stages:
- stage: container
displayName: New Docker Build
dependsOn: []
jobs:
- job: container
displayName: build container
pool:
vmImage: $(vmImageName)
steps:
- checkout: self
fetchDepth: 1
- checkout: net-framework-base
fetchDepth: 1
# this is the task that's failing
- task: Docker@2
displayName: build container
inputs:
containerRegistry: $(prod-container-registry)
repository: $(imageRepository)
command: "build"
Dockerfile: $(dockerfilePath)
tags: |
$(tag)
答案 0 :(得分:1)
我不认为COPY
命令会执行您认为的操作。 COPY
将文件从主机文件系统复制到容器中。它在本地工作的原因是因为您是在本地构建代码的,所以它将本地构建的版本复制到容器中。
应该要做的是COPY
将源代码放入容器,然后运行构建应用程序所需的任何步骤。使用multi-stage builds也是一个好习惯:使用SDK和构建工具链将源代码复制到容器中,进行构建,然后将结果输出复制到精简的运行时容器中,该容器仅包含运行时没有源代码的环境。
答案 1 :(得分:0)
我想添加另一个答案,以更好地解释我的问题以及如何解决。我的问题不是对COPY命令的误解,而是对在哪里构建的内容的误解。这是旧的dockerfile,其中说明了我要去哪里的错误:
FROM ourcontainerregistry.azurecr.io/net-framework-base:latest
WORKDIR /app
# As Daniel said, the reason it was working for me locally is because I had already built the solution from visual studio.
# So this command wasn't actually building anything because nothing existed on this container yet.
RUN cmd MSBuild.exe /property:Configuration=Release
# However, this was copying the files I had already built in VS locally.
# When this ran on the build agent in Azure DevOps, it would fail because the solution had not been built on the build agent.
COPY TopShelfServiceInstaller/bin/Release/ .
ENTRYPOINT ["TopShelfServiceInstaller.exe"]
这是我的新dockerfile,它使用多阶段构建,并附有关于何时以及为什么发生的注释:
# First stage is building the app.
# We do this with one container based on the .NET Framework 4.8 image that has the SDK installed on it.
FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2019 AS build
WORKDIR C:/build
# Next we copy all files from the host into the build container.
COPY . .
# Then we run MSBuild to build the solution.
RUN MSBuild.exe /property:Configuration=Release
# Next and last stage is creating a container that will actually run the app.
FROM ourcontainerregistry.azurecr.io/net-framework-base:latest AS runtime
WORKDIR C:/app
# And here we're copying files from the build container into the runtime container.
COPY --from=build C:/build/TopShelfServiceInstaller/bin/Release .
ENTRYPOINT [ "C:/app/TopShelfServiceInstaller.exe" ]
以这种方式构建的要点是,无论您是在本地工作还是在自动构建管道中运行它,它都允许您使用单个命令克隆存储库并构建容器,再次如Daniel所述。