定义 YAML) (容器作业
Azure DevOps Services | Azure DevOps Server 2020 | Azure DevOps Server 2019
默认情况下, 作业 在安装了 代理 的主机上运行。 这很方便,通常非常适合刚刚开始采用Azure Pipelines的项目。 随着时间的推移,你可能会发现你希望更好地控制任务运行的上下文。 YAML 管道为此级别的控制提供容器作业。
在 Linux 和Windows代理上,作业可以在主机或容器中运行。 (macOS 和 Red Hat Enterprise Linux 6 上,容器作业不可用。) 容器提供与主机的隔离,并允许固定特定版本的工具和依赖项。 主机作业需要较少的初始设置和基础结构才能维护。
容器通过主机操作系统提供轻型抽象。 可以选择生成所需的操作系统、工具和依赖项的确切版本。 在管道中指定容器时,代理将首先提取并启动容器。 然后,作业的每个步骤都将在容器内运行。 不能有嵌套容器。 当代理已在容器中运行时,不支持容器。
如果需要在各个步骤级别进行精细控制, 则步骤目标 允许你为每个步骤选择容器或主机。
要求
基于 Linux 的容器
Azure Pipelines系统需要基于 Linux 的容器中的一些内容:
- Bash
- 基于 glibc
- 可以运行代理提供) Node.js (
- 不定义
ENTRYPOINT USER有权访问groupadd其他特权命令,而无需sudo
在代理主机上:
- 确保已安装 Docker
- 代理必须具有访问 Docker 守护程序的权限
请确保容器提供了每个可用的工具。 Docker Hub上提供的一些极其精简的容器,尤其是基于 Alpine Linux 的容器,不符合这些最低要求。 具有容器ENTRYPOINT的容器可能无法正常工作,因为Azure Pipelines将docker create等待容器和docker exec一系列预期容器始终启动并运行的命令。
注意
对于基于Windows的 Linux 容器,必须预安装Node.js。
Windows 容器
Azure Pipelines还可以运行Windows容器。 Windows服务器版本 1803 或更高版本是必需的。 必须安装 Docker。 确保管道代理有权访问 Docker 守护程序。
Windows容器必须支持运行Node.js。 基本Windows Nano Server 容器缺少运行 Node 所需的依赖项。
托管代理
仅 windows-2019 支持运行容器的 ubuntu-* 映像。
macOS 映像不支持运行容器。
单个作业
一个简单的示例:
pool:
vmImage: 'ubuntu-18.04'
container: ubuntu:18.04
steps:
- script: printenv
这会告知系统从Docker Hub提取ubuntu标记18.04的图像,然后启动容器。 运行 printenv 命令时,它将在容器内 ubuntu:18.04 发生。
Windows示例:
pool:
vmImage: 'windows-2019'
container: mcr.microsoft.com/windows/servercore:ltsc2019
steps:
- script: set
注意
Windows要求主机和容器的内核版本匹配。
由于此示例使用 Windows 2019 映像,因此我们将使用2019容器的标记。
多个作业
容器还可用于在多个 作业中运行相同的步骤。
在以下示例中,相同的步骤在多个版本的 Ubuntu Linux 中运行。
(我们不必提及关键字 jobs ,因为只有一个作业定义。)
pool:
vmImage: 'ubuntu-18.04'
strategy:
matrix:
ubuntu14:
containerImage: ubuntu:14.04
ubuntu16:
containerImage: ubuntu:16.04
ubuntu18:
containerImage: ubuntu:18.04
container: $[ variables['containerImage'] ]
steps:
- script: printenv
终结点
容器可以托管在公共Docker Hub注册表以外的注册表上。 若要在Azure 容器注册表或其他专用容器注册表上托管映像, (包括专用Docker Hub注册表) ,请向专用注册表添加服务连接。 然后,可以在容器规格中引用它:
container:
image: registry:ubuntu1604
endpoint: private_dockerhub_connection
steps:
- script: echo hello
或
container:
image: myprivate.azurecr.io/windowsservercore:1803
endpoint: my_acr_connection
steps:
- script: echo hello
其他容器注册表也可能正常工作。 Amazon ECR 目前不起作用,因为将 AWS 凭据转换为 Docker 可用于进行身份验证的其他客户端工具。
注意
Red Hat Enterprise Linux 6 版本的代理不会运行容器作业。 选择其他 Linux 风格,例如 Red Hat Enterprise Linux 7 或更高版本。
选项
如果需要控制容器启动,可以指定 options。
container:
image: ubuntu:18.04
options: --hostname container-test --ip 192.168.0.1
steps:
- script: echo hello
运行 docker create --help 将提供受支持的选项列表。 可以使用命令中可用的docker create任意选项。
可重用容器定义
在以下示例中,容器在“资源”部分中定义。
然后,每个容器稍后通过引用其分配的别名来引用。
(此处,我们显式列出 jobs 关键字,以便清楚起见。)
resources:
containers:
- container: u14
image: ubuntu:14.04
- container: u16
image: ubuntu:16.04
- container: u18
image: ubuntu:18.04
jobs:
- job: RunInContainer
pool:
vmImage: 'ubuntu-18.04'
strategy:
matrix:
ubuntu14:
containerResource: u14
ubuntu16:
containerResource: u16
ubuntu18:
containerResource: u18
container: $[ variables['containerResource'] ]
steps:
- script: printenv
非基于 glibc 的容器
Azure Pipelines代理提供运行任务和脚本所需的Node.js副本。 Node.js版本根据托管云中使用的 C 运行时(通常为 glibc)进行编译。 Linux 的某些变体使用其他 C 运行时。 例如,Alpine Linux 使用 musl。
如果要将基于非 glibc 的容器用作作业容器,则需要自行安排一些操作。 首先,必须提供自己的Node.js副本。 其次,必须将标签添加到图像中,告知代理在何处查找Node.js二进制文件。 最后,股票 Alpine 不包含Azure Pipelines依赖的其他依赖项:bash、sudo 和 groupadd。
自带Node.js
你负责将 Node 二进制文件添加到容器。
节点 14 是一个安全的选择。
可以从映像开始 node:14-alpine 。
告知代理Node.js
代理将读取容器标签“com.azure.dev.pipelines.handler.node.path”。
如果此标签存在,则它必须是Node.js二进制文件的路径。
例如,在基于映像 node:10-alpine的映像中,将此行添加到 Dockerfile:
LABEL "com.azure.dev.pipelines.agent.handler.node.path"="/usr/local/bin/node"
添加要求
Azure Pipelines假定安装了通用管理包的基于 Bash 的系统。
Alpine Linux 尤其不包含所需的多个包。
安装 bash, sudo并 shadow 涵盖基本需求。
RUN apk add bash sudo shadow
如果依赖于任何内置任务或市场任务,则还需要提供所需的二进制文件。
Dockerfile 的完整示例
FROM node:10-alpine
RUN apk add --no-cache --virtual .pipeline-deps readline linux-pam \
&& apk add bash sudo shadow \
&& apk del .pipeline-deps
LABEL "com.azure.dev.pipelines.agent.handler.node.path"="/usr/local/bin/node"
CMD [ "node" ]
具有单个托管代理上的代理池的多个作业
容器作业使用基础主机代理 Docker config.json 进行映像注册表授权,该授权在 Docker 注册表容器初始化结束时注销。 后续注册表映像拉取授权可能会被拒绝进行“未经授权的身份验证”,因为已在系统中注册的用于身份验证的 Docker config.json 文件已被另一个并行运行的容器作业注销。
解决方案是设置特定于托管代理上运行的每个代理池服务的 Docker 环境变量 DOCKER_CONFIG 。 导出 DOCKER_CONFIG 每个代理池的 runsvc.sh 脚本:
#insert anything to set up env when running as a service
export DOCKER_CONFIG=./.docker