Skip to content

Commit 0dd98df

Browse files
Merge pull request #8232 from v-thepet/pipelines10
Freshness: Azure Pipelines 10
2 parents 5ef4982 + 28924a0 commit 0dd98df

File tree

1 file changed

+51
-65
lines changed

1 file changed

+51
-65
lines changed

docs/pipelines/process/container-phases.md

Lines changed: 51 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,63 @@
11
---
2-
title: Container jobs in YAML
3-
description: Learn about configuring and running pipeline jobs inside containers.
2+
title: YAML pipeline container jobs
3+
description: Learn about configuring and running Azure Pipelines YAML pipeline jobs inside containers.
44
ms.assetid: 8d35f78a-f386-4699-9280-7bd933de9e7b
55
ms.topic: conceptual
6-
ms.date: 07/08/2024
6+
ms.date: 08/19/2025
77
monikerRange: "<=azure-devops"
8+
#customer intent: As an Azure Pipelines builder and tester, I want to learn about running pipeline jobs in containers so I can build and test pipelines in various agent configurations.
89
---
910

1011
# Container jobs in YAML pipelines
1112

1213
[!INCLUDE [version-gt-eq-2019](../../includes/version-gt-eq-2019.md)]
1314

14-
This article explains container jobs in Azure Pipelines.
15+
This article explains container jobs in Azure Pipelines. Containers are lightweight abstractions from the host operating system that provide all the necessary elements to run a job in a specific environment.
1516

16-
By default, Azure Pipelines [jobs](phases.md) run directly on the host machines where the agent is installed. Hosted agent jobs are convenient, require little initial setup and infrastructure to maintain, and are well-suited for basic projects.
17+
By default, Azure Pipelines [jobs](phases.md) run directly on [agents](../agents/agents.md) installed on host machines. Hosted agent jobs are convenient, require little initial setup or infrastructure maintenance, and are well-suited for basic projects. For more control over task context, you can define and run pipeline jobs in containers to get the exact versions of operating systems, tools, and dependencies you want.
1718

18-
If you want more control over task context, you can define and run jobs in containers. Containers are a lightweight abstraction over the host operating system that provides isolation from the host. When you run jobs in containers, you can select the exact versions of operating systems, tools, and dependencies that your build requires.
19+
For a container job, the agent first fetches and starts the container, and then runs each step of the job inside the container. If you need finer-grained control of individual build steps, you can use [step targets](tasks.md#step-target) to choose a container or host for each step.
1920

20-
Linux and Windows [agents](../agents/agents.md) can run pipeline jobs directly on the host or in containers. Container jobs aren't available on macOS.
21+
## Requirements for container jobs
2122

22-
For a container job, the agent first fetches and starts the container. Then each step of the job runs inside the container.
23-
24-
::: moniker range="<=azure-devops"
25-
If you need fine-grained control at the individual build step level, [step targets](tasks.md#step-target) let you choose a container or host for each step.
26-
::: moniker-end
27-
28-
## Prerequisites
29-
30-
- Use a YAML pipeline. Classic pipelines do not support container jobs.
31-
- Use a hosted Windows or Ubuntu agent. Only `windows-*` and `ubuntu-*` agents support running containers. The `macos-*` agents don't support running containers.
32-
- Your agent is set up for container jobs.
33-
- Windows and Linux agents must have Docker installed, and need permission to access the Docker daemon.
34-
- Containers aren't supported when the agent is already running inside a container. You can't have nested containers.
35-
36-
### Additional container requirements
23+
- A YAML-based pipeline. Classic pipelines don't support container jobs.
24+
- A Windows or Ubuntu hosted agent. MacOS agents don't support containers. To use non-Ubuntu Linux agents, see [Nonglibc-based containers](#nonglibc-based-containers).
25+
- Docker installed on the agent, with permission to access the Docker daemon.
26+
- Agent running directly on the host, not already inside a container. Nested containers aren't supported.
3727

3828
### [Linux](#tab/linux)
3929

40-
Linux-based containers have the following requirements. For workarounds, see [Nonglibc-based containers](#nonglibc-based-containers).
30+
Linux-based containers also have the following requirements:
4131

42-
- Bash installed
43-
- GNU C Library (glibc)-based
44-
- No `ENTRYPOINT`
45-
- Provide `USER` with access to `groupadd` and other privileged commands without using `sudo`
46-
- Can run Node.js, which the agent provides
47-
> [!NOTE]
48-
> Node.js must be pre-installed for Linux containers on Windows hosts.
32+
- Bash installed.
33+
- GNU C Library (`glibc`)-based. Nonglibc containers require added setup. For more information, see [Nonglibc-based containers](#nonglibc-based-containers).
34+
- No `ENTRYPOINT`. Containers with an `ENTRYPOINT` might not work, because [docker exec](https://docs.docker.com/reference/cli/docker/container/exec) expects the container to always be running.
35+
- `USER` provided with access to `groupadd` and other privileged commands without using `sudo`.
36+
- Ability to run Node.js, which the agent provides.
37+
>[!NOTE]
38+
>Node.js must be preinstalled for Linux containers on Windows hosts.
4939
50-
Some stripped-down containers available on Docker Hub, especially containers based on Alpine Linux, don't satisfy these requirements. Containers with an `ENTRYPOINT` might not work because Azure Pipelines `docker create` and `docker exec` expect that the container is always up and running.
40+
Some stripped-down containers available on Docker Hub, especially containers based on Alpine Linux, don't satisfy these requirements. For more information, see [Nonglibc-based containers](#nonglibc-based-containers).
5141

5242
### [Windows](#tab/windows)
5343

54-
[Windows containers](/virtualization/windowscontainers/about/) must meet the following requirements:
44+
[Windows containers](/virtualization/windowscontainers/about/) also have the following requirements:
5545

56-
- Windows Server version 1803 or higher
57-
- Matching host and container kernel versions
58-
- Can run Node.js
59-
> [!NOTE]
60-
> A base Windows Nano Server container doesn't have the required dependencies to run Node.js.
46+
- Windows Server version 1803 or higher.
47+
- Matching host and container kernel versions.
48+
- Ability to run Node.js, which the agent provides.
49+
>[!NOTE]
50+
>A base Windows Nano Server container doesn't have the required dependencies to run Node.js.
6151
6252
---
6353

64-
## Single job examples
54+
## Single job
6555

66-
The following examples define a Windows or Linux container for a single job.
56+
The following example defines a Windows or Linux single-job container.
6757

6858
### [Linux](#tab/linux)
6959

70-
The following simple example defines a Linux container:
60+
This example tells the system to fetch the `ubuntu` image tagged `18.04` from [Docker Hub](https://hub.docker.com) and then start the container. The `printenv` command runs inside the `ubuntu:18.04` container.
7161

7262
```yaml
7363
pool:
@@ -79,11 +69,9 @@ steps:
7969
- script: printenv
8070
```
8171
82-
The preceding example tells the system to fetch the `ubuntu` image tagged `18.04` from [Docker Hub](https://hub.docker.com) and then start the container. The `printenv` command runs inside the `ubuntu:18.04` container.
83-
8472
### [Windows](#tab/windows)
8573
86-
The following example defines a Windows container:
74+
For Windows, the kernel version of the host and container must match. Since the following example uses a Windows 2019 host image, it uses the `2019` tag for the container.
8775

8876
```yaml
8977
pool:
@@ -95,13 +83,11 @@ steps:
9583
- script: set
9684
```
9785

98-
For Windows, the kernel version of the host and container must match. Since the preceding example uses a Windows 2019 host image, it uses the `2019` tag for the container.
99-
10086
---
10187

10288
## Multiple jobs
10389

104-
You can use containers to run the same step in multiple jobs. The following example runs the same step in multiple versions of Ubuntu Linux. You don't have to mention the `jobs` keyword because only a single job is defined.
90+
You can use containers to run the same step in multiple jobs. The following example runs the same step in multiple versions of Ubuntu Linux. You don't have to use the `jobs` keyword, because only a single job is defined.
10591

10692
```yaml
10793
pool:
@@ -122,11 +108,13 @@ steps:
122108
- script: printenv
123109
```
124110

125-
### Multiple jobs with agent pools on a single agent host
111+
### Multiple jobs on a single agent host
126112

127-
A container job uses the underlying host agent's Docker configuration file for image registry authorization. This file signs out at the end of the Docker registry container initialization. Registry image pulls for subsequent container jobs might be denied for `unauthorized authentication` because another job running in parallel already signed out the Docker configuration file.
113+
A container job uses the underlying host agent's Docker configuration file for image registry authorization. This file signs out at the end of the Docker registry container initialization.
128114

129-
The solution is to set a Docker environment variable `DOCKER_CONFIG` that's specific to each agent pool running on the hosted agent. Export the `DOCKER_CONFIG` in each agent pool's *runsvc.sh* script as follows:
115+
Registry image pulls for container jobs could be denied for unauthorized authentication if another job running in parallel on the agent already signed out the Docker configuration file. The solution is to set a Docker environment variable called `DOCKER_CONFIG` for each agent pool running on the hosted agent.
116+
117+
Export the `DOCKER_CONFIG` in each agent pool's *runsvc.sh* script as follows:
130118

131119
```bash
132120
export DOCKER_CONFIG=./.docker
@@ -135,7 +123,7 @@ export DOCKER_CONFIG=./.docker
135123
<a name="options"></a>
136124
## Startup options
137125

138-
You can specify `options` to control container startup, as in the following example:
126+
You can use the `options` property to specify options for container startup.
139127

140128
```yaml
141129
container:
@@ -146,13 +134,13 @@ steps:
146134
- script: echo hello
147135
```
148136

149-
Running `docker create --help` gives you the list of options that you can pass to Docker invocation. Not all of these options are guaranteed to work with Azure DevOps. Check first to see if you can use a `container` property to accomplish the same goal.
137+
Run `docker create --help` to get the list of options you can pass to Docker invocation. Not all these options are guaranteed to work with Azure Pipelines. Check first to see if you can use a `container` property for the same purpose.
150138

151-
For more information, see the [docker create](https://docs.docker.com/engine/reference/commandline/create) command reference and the [resources.containers.container definition](/azure/devops/pipelines/yaml-schema/resources-containers-container) in the Azure DevOps YAML schema reference.
139+
For more information, see the [docker container create](https://docs.docker.com/reference/cli/docker/container/create/) command reference and the [resources.containers.container](/azure/devops/pipelines/yaml-schema/resources-containers-container) definition in the [YAML schema reference for Azure Pipelines](/azure/devops/pipelines/yaml-schema).
152140

153141
## Reusable container definition
154142

155-
The following example defines the containers in the `resources` section, and then references them by their assigned aliases. The `jobs` keyword is explicitly listed for clarity.
143+
The following YAML example defines the containers in the `resources` section, and then references them by their assigned aliases. The `jobs` keyword is used for clarity.
156144

157145
```yaml
158146
resources:
@@ -188,7 +176,7 @@ jobs:
188176

189177
## Service endpoints
190178

191-
You can host containers on other registries than public Docker Hub. To host an image on [Azure Container Registry](/azure/container-registry/) or another private container registry, including a private Docker Hub registry, add a [service connection](../library/service-endpoints.md) to access the registry. Then you can reference the endpoint in the container definition.
179+
You can host containers on registries other than public Docker Hub. To host an image on [Azure Container Registry](/azure/container-registry/) or another private container registry, including a private Docker Hub registry, add a [service connection](../library/service-endpoints.md#docker-registry-service-connection) to access the registry. Then you can reference the endpoint in the container definition.
192180

193181
Private Docker Hub connection:
194182

@@ -207,25 +195,23 @@ container:
207195
```
208196

209197
>[!NOTE]
210-
>Azure Pipelines can't set up a service connection for Amazon Elastic Container Registry (ECR), because Amazon ECR requires other client tools to convert AWS credentials into something Docker can use to authenticate.
198+
>Azure Pipelines can't set up a service connection for Amazon Elastic Container Registry (ECR), because Amazon ECR requires other client tools to convert Amazon Web Services (AWS) credentials to be usable for Docker authentication.
211199

212200
## Nonglibc-based containers
213201

214-
The Azure Pipelines agent supplies a copy of Node.js, which is required to run tasks and scripts. To find out the version of Node.js for a hosted agent, see [Microsoft-hosted agents](../agents/hosted.md#software).
215-
216-
The version of Node.js compiles against the C runtime used in the hosted cloud, typically glibc. Some Linux variants use other C runtimes. For instance, Alpine Linux uses musl.
202+
The hosted Azure Pipelines agents supply Node.js, which is required to run tasks and scripts. The Node.js version compiles against the C runtime used in the hosted cloud, typically `glibc`. Some Linux variants use other C runtimes. For instance, Alpine Linux uses `musl`. For more information, see [Microsoft-hosted agents](../agents/hosted.md#software).
217203

218-
If you want to use a nonglibc-based container, you need to:
204+
If you want to use a nonglibc-based container in a pipeline, you must:
219205

220206
- Supply your own copy of Node.js.
221-
- Add a label to your image telling the agent where to find the Node.js binary.
222-
- Provide other dependencies that Azure Pipelines depends on: `bash`, `sudo`, `which`, and `groupadd`.
207+
- Add a label to your image pointing to the location of the Node.js binary.
208+
- Provide the `bash`, `sudo`, `which`, and `groupadd` Azure Pipelines dependencies.
223209

224210
### Supply your own Node.js
225211

226-
If you use a nonglibc-based container, you're responsible for adding a Node binary to your container. Node.js 18 is a safe choice. Start from the `node:18-alpine` image.
212+
If you use a nonglibc-based container, you must add a Node binary to your container. Node.js 18 is a safe choice. Start from the `node:18-alpine` image.
227213

228-
### Tell the agent about Node.js
214+
### Direct the agent to Node.js
229215

230216
The agent reads the container label `"com.azure.dev.pipelines.handler.node.path"`. If this label exists, it must be the path to the Node.js binary.
231217

@@ -237,13 +223,13 @@ LABEL "com.azure.dev.pipelines.agent.handler.node.path"="/usr/local/bin/node"
237223

238224
### Add required packages
239225

240-
Azure Pipelines assumes a Bash-based system with common administrative packages installed. Alpine Linux in particular doesn't come with several of the packages needed. Install `bash`, `sudo`, and `shadow` to cover the basic needs.
226+
Azure Pipelines requires a Bash-based system to have common administrative packages installed. Alpine Linux doesn't have several of the needed packages. Install `bash`, `sudo`, and `shadow` to cover basic needs.
241227

242228
```dockerfile
243229
RUN apk add bash sudo shadow
244230
```
245231

246-
If you depend on any in-box or Marketplace tasks, also supply the binaries they require.
232+
If you depend on any built-in or Marketplace tasks, also supply the binaries they require.
247233

248234
### Full Dockerfile example
249235

0 commit comments

Comments
 (0)