服务容器
Azure DevOps Services
如果你的管道需要支持一个或多个服务,则在许多情况下,你需要在每个作业的基础上创建、连接和清理每个服务。 例如,管道可能会运行需要访问数据库和内存缓存的集成测试。 需要为管道中的每个作业全新创建数据库和内存缓存。
容器提供一种简单、可移植的方式来运行管道所依赖的服务。 利用 服务容器 ,你可以自动创建、网络和管理容器化服务的生命周期。 每个服务容器只能由需要它的作业访问。 服务容器适用于任何类型的 作业,但它们最常用于 容器作业。
要求
服务容器必须定义 CMD 或 ENTRYPOINT 。
管道将为提供的容器运行 docker run ,无需其他参数。
Azure Pipelines 可以运行 Linux 或Windows 容器。 使用适用于 Linux 容器的托管 Ubuntu 或 Windows 容器的托管 Windows 容器池。 (托管的 macOS 池不支持运行容器。 )
单个容器作业
使用 容器作业的简单示例:
resources:
containers:
- container: my_container
image: buildpack-deps:focal
- container: nginx
image: nginx
pool:
vmImage: 'ubuntu-20.04'
container: my_container
services:
nginx: nginx
steps:
- script: |
curl nginx
displayName: Show that nginx is running
此管道从Docker Hub提取 nginx 和 buildpack-deps 容器,然后启动容器。 容器一起联网,以便它们可以按 services 名称相互联系。
在此作业容器内, nginx 主机名解析为使用 Docker 网络的正确服务。
网络上的所有容器自动相互公开所有端口。
单个作业
你还可以使用没有作业容器的服务容器。 一个简单的示例:
resources:
containers:
- container: nginx
image: nginx
ports:
- 8080:80
env:
NGINX_PORT: 80
- container: redis
image: redis
ports:
- 6379
pool:
vmImage: 'ubuntu-18.04'
services:
nginx: nginx
redis: redis
steps:
- script: |
curl localhost:8080
echo $AGENT_SERVICES_REDIS_PORTS_6379
此管道启动最新 nginx 的容器。 由于作业未在容器中运行,因此不会自动进行名称解析。
此示例演示如何使用 localhost 来访问服务。
在上面的示例中,我们显式地 (提供端口, 8080:80 如) 。
另一种方法是让随机端口在运行时动态分配。 然后,你可以通过使用 变量来访问这些动态端口。
在 Bash 脚本中,可以使用进程环境访问变量。 这些变量采用以下格式: agent.services.<serviceName>.ports.<port> 。
在上面的示例中, redis 为分配了主机上随机可用的端口。
agent.services.redis.ports.6379变量包含端口号。
多个作业
对于同一服务的多个版本,服务容器也很有用。 在下面的示例中,将对多个版本的 PostgreSQL 运行相同的步骤。
resources:
containers:
- container: my_container
image: ubuntu:18.04
- container: pg12
image: postgres:12
- container: pg11
image: postgres:11
pool:
vmImage: 'ubuntu-18.04'
strategy:
matrix:
postgres12:
postgresService: pg12
postgres11:
postgresService: pg11
container: my_container
services:
postgres: $[ variables['postgresService'] ]
steps:
- script: printenv
端口
指定容器资源或内联容器时,可以指定要在容器中公开的数组 ports 。
resources:
containers:
- container: my_service
image: my_service:latest
ports:
- 8080:80
- 5432
services:
redis:
image: redis
ports:
- 6379/tcp
如果作业在容器中运行,则不需要指定 ports ,因为同一 Docker 网络上的容器在默认情况下会自动公开所有端口。
如果作业正在主机上运行,则 ports 需要访问该服务。 端口采用的格式 <hostPort>:<containerPort><containerPort> 为,在末尾提供可选 /<protocol> 的,例如 6379/tcp ,通过端口 6379 公开 tcp ,并绑定到主机上的随机端口。
对于绑定到主机上的随机端口的端口,管道将创建一个窗体的变量,以便可以由作业访问该窗体 agent.services.<serviceName>.ports.<port> 。 例如, agent.services.redis.ports.6379 解析为主机上随机分配的端口。
卷
卷可用于在服务之间共享数据,或在多个作业运行之间保留数据。
可以将卷装载指定为的 volumes 数组。 卷可以命名为 Docker 卷、匿名 Docker 卷或绑定到主机上的装载。
services:
my_service:
image: myservice:latest
volumes:
- mydockervolume:/data/dir
- /data/dir
- /src/dir:/dst/dir
卷采用格式 <source>:<destinationPath> ,其中 <source> 可以是主机上的命名卷或绝对路径, <destinationPath> 是容器中的绝对路径。
注意
如果使用我们的托管池,则将不会在作业之间保留卷,因为作业完成后主机会被清除。
其他选项
服务容器与容器作业共享相同的容器资源。 这意味着你可以使用相同的 附加选项。
Healthcheck
(可选)如果任何服务容器指定 HEALTHCHECK,则在运行作业之前,代理将等待,直到该容器运行正常。
包含服务的多个容器示例
在此示例中,有一个 Django Python web 容器连接到两个数据库容器-PostgreSQL 和 MySQL。 PostgreSQL 数据库是主数据库,其容器的名称 db 为。 db容器使用卷 /data/db:/var/lib/postgresql/data ,并通过 env 三个数据库变量传递到容器。 mysql容器使用端口 3306:3306 ,并且还通过 env 传递数据库变量。 web容器已打开,其中包含端口 8000 。 在步骤中, pip 将安装依赖项,然后运行 Django 测试。 如果你想要设置工作示例,你将需要一个 具有两个数据库的 Django 站点设置。 此示例假设 manage.py 文件位于根目录中,并且 Django 项目在该目录中。 可能需要更新中 /__w/1/s/manage.py test 的 /__w/1/s/ 路径。
resources:
containers:
- container: db
image: postgres
volumes:
- '/data/db:/var/lib/postgresql/data'
env:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
- container: mysql
image: 'mysql:5.7'
ports:
- '3306:3306'
env:
MYSQL_DATABASE: users
MYSQL_USER: mysql
MYSQL_PASSWORD: mysql
MYSQL_ROOT_PASSWORD: mysql
- container: web
image: python
volumes:
- '/code'
ports:
- '8000:8000'
pool:
vmImage: 'ubuntu-latest'
container: web
services:
db: db
mysql: mysql
steps:
- script: |
pip install django
pip install psycopg2
pip install mysqlclient
displayName: set up django
- script: |
python /__w/1/s/manage.py test