Контейнеры служб
Azure DevOps Services
Если для конвейера требуется поддержка одной или нескольких служб, во многих случаях требуется создать, подключиться к каждой службе и очистить каждую службу по каждому заданию. Например, конвейер может выполнять тесты интеграции, которым требуется доступ к базе данных и кэшу памяти. Для каждого задания в конвейере необходимо создать базу данных и кэш памяти.
Контейнер позволяет легко запускать службу, от которой зависит конвейер, с возможностью переноса. Контейнер службы позволяет автоматически создать контейнерную службу, подключить ее, а также управлять ею. Каждый контейнер службы доступен только заданию, которому он требуется. Контейнеры служб работают с заданиями любого типа, но чаще всего используются с заданиями контейнеров.
Требования
Контейнеры служб должны определять CMD
или ENTRYPOINT
.
Конвейер будет выполняться docker run
для предоставленного контейнера без дополнительных аргументов.
Azure Pipelines может запускать контейнеры Linux или Windows. Используйте размещенные контейнеры Ubuntu для Linux или размещенный пул контейнеров Windows для контейнеров Windows. (Размещенный пул macOS не поддерживает запущенные контейнеры.)
Задание одного контейнера
Простой пример использования заданий контейнера:
resources:
containers:
- container: my_container
image: buildpack-deps:focal
- container: nginx
image: nginx
pool:
vmImage: 'ubuntu-latest'
container: my_container
services:
nginx: nginx
steps:
- script: |
curl nginx
displayName: Show that nginx is running
Этот конвейер извлекает nginx
контейнеры и buildpack-deps
из Docker Hub, а затем запускает контейнеры. Контейнеры объединяются в сеть, чтобы они могли связаться друг с другом по имени 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-latest'
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:22.04
- container: pg15
image: postgres:15
- container: pg14
image: postgres:14
pool:
vmImage: 'ubuntu-latest'
strategy:
matrix:
postgres15:
postgresService: pg15
postgres14:
postgresService: pg14
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
для предоставления через tcp
порт 6379
, привязанного к случайному порту на хост-компьютере.
Для портов, привязанных к случайному порту на хост-компьютере, конвейер создает переменную формы 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, агент ожидает, пока контейнер не будет работоспособным, прежде чем запускать задание.
Пример использования нескольких контейнеров со службами
В этом примере есть веб-контейнер Django Python, подключенный к двум контейнерам баз данных : 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/
путь в /__w/1/s/manage.py test
.
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
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по