如何在同一Azure DevOps流水线中将构建制品复制到同流程Docker镜像
核心问题答复
已下载制品的实际存放路径
只要download步骤执行成功,且未自定义path参数指定下载位置,my_artifact会默认存储在流水线工作区下的$(Pipeline.Workspace)/my_artifact目录。
需要特别注意:这个目录和代码拉取后的源码目录是完全独立的,源码默认存放在$(Pipeline.Workspace)/s/路径下,两者没有自动关联。很多开发者会混淆两个目录的层级,误以为下载的制品会自动出现在代码拉取的目录中,这是最常见的认知偏差。
COPY后镜像目录为空的原因
这个问题的根本原因是Docker构建的上下文范围没有覆盖已下载的制品目录:
Docker@2任务默认的构建上下文是源码目录$(Build.SourcesDirectory),而你下载的制品存储在独立的工作区子目录中,完全不在默认上下文的覆盖范围内。Docker构建过程只能检索到上下文范围内的文件,找不到对应的whl安装包,最终就会出现镜像内目标目录为空的结果。
可落地的实现方案
可以根据现有工程的结构选择以下任意一种方案:
方案1:调整构建上下文范围覆盖制品目录
在Docker@2的build任务输入中,手动将构建上下文指定为流水线工作区根目录,确保上下文可以覆盖制品的存储路径:
- task: Docker@2 displayName: Build inputs: command: build containerRegistry: myConnection repository: myRepository # 新增配置,指定构建上下文为流水线工作区根目录 context: $(Pipeline.Workspace)
对应调整Dockerfile内的COPY指令路径,匹配上下文根下的实际目录结构:
# 上下文为工作区根目录,whl文件存放在my_artifact子文件夹下 COPY my_artifact/*.whl /myDir/
方案2:将制品拷贝到默认构建上下文目录
在download步骤和Docker构建任务之间新增文件复制任务,把下载好的制品文件直接拷贝到源码目录(也就是Docker@2默认的构建上下文路径)下,不需要修改原有Dockerfile的指令:
- download: current artifact: my_artifact # 新增文件拷贝任务 - task: CopyFiles@2 displayName: 拷贝制品文件到构建目录 inputs: SourceFolder: $(Pipeline.Workspace)/my_artifact Contents: "**/*.whl" TargetFolder: $(Build.SourcesDirectory) - task: Docker@2 displayName: Build inputs: command: build containerRegistry: myConnection repository: myRepository
这种方式下,你原本在Dockerfile中编写的COPY *.whl /myDir/指令可以直接正常生效,不需要做路径调整。
容易踩的坑
- 你最初提供的download步骤YAML存在缩进错误:
artifact是download步骤的配置字段,缩进需要和download保持对齐,否则会出现YAML解析失败的问题。 - 如果在download步骤中手动配置了
path参数指定自定义下载路径,实际制品的存放位置以该配置为准,不需要套用默认路径规则。 - Docker构建上下文不能设置为工作区范围外的路径,否则会触发上下文路径无效的构建报错。
内容的提问来源于stack exchange,提问作者Corbie

