Contenedores de servicio

Azure Pipelines

Si la canalización requiere la compatibilidad de uno o varios servicios, en muchos casos querrá crear, conectarse y limpiar cada servicio por trabajo. Por ejemplo, una canalización puede ejecutar pruebas de integración que requieren acceso a una base de datos y una memoria caché. La base de datos y la memoria caché deben crearse recientemente para cada trabajo de la canalización.

Un contenedor proporciona una manera sencilla y portátil de ejecutar un servicio del que depende la canalización. Un contenedor de servicios permite crear, conectar y administrar automáticamente el ciclo de vida del servicio en contenedores. Solo el trabajo que lo requiere puede acceder a cada contenedor de servicios. Los contenedores de servicio funcionan con cualquier tipo de trabajo,pero se usan con más frecuencia con trabajos de contenedor.

Requisitos

Los contenedores de servicios deben definir CMD o ENTRYPOINT . La canalización será docker run el contenedor proporcionado sin argumentos adicionales.

Azure Pipelines puede ejecutar Linux o Windows Containers. Use Ubuntu hospedado para contenedores de Linux o hosted Windows Container pool for Windows containers (Grupo de contenedores hospedados Windows Linux). (El grupo de macOS hospedado no admite la ejecución de contenedores).

Trabajo de contenedor único

Un ejemplo sencillo de uso de trabajos de contenedor:

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

Esta canalización captura los contenedores nginxbuildpack-deps y de nginx y, a continuación, inicia los contenedores. Los contenedores están en red para que puedan comunicarse entre sí por su services nombre.

Desde dentro de este contenedor de trabajos, los nginx nombres de host se resuelven en los servicios correctos mediante redes de Docker. Todos los contenedores de la red exponen automáticamente todos los puertos entre sí.

Trabajo único

También puede usar contenedores de servicio sin un contenedor de trabajos. Un ejemplo sencillo:

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

Esta canalización inicia los contenedores más nginx recientes. Puesto que el trabajo no se ejecuta en un contenedor, no hay ninguna resolución automática de nombres. En este ejemplo se muestra cómo puede llegar a los servicios mediante localhost . En el ejemplo anterior se proporciona el puerto explícitamente (por ejemplo, 8080:80 ).

Un enfoque alternativo es permitir que un puerto aleatorio se asigne dinámicamente en tiempo de ejecución. A continuación, puede acceder a estos puertos dinámicos mediante variables. En un script de Bash, puede acceder a una variable mediante el entorno de proceso. Estas variables tienen la forma: agent.services.<serviceName>.ports.<port> . En el ejemplo anterior, redis se asigna un puerto disponible aleatorio en el host. La agent.services.redis.ports.6379 variable contiene el número de puerto.

Varios trabajos

Los contenedores de servicios también son útiles para ejecutar los mismos pasos en varias versiones del mismo servicio. En el ejemplo siguiente, los mismos pasos se ejecutan en varias versiones de 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

Puertos

Al especificar un recurso de contenedor o un contenedor en línea, puede especificar una matriz de para ports exponer en el contenedor.

resources:
  containers:
  - container: my_service
    image: my_service:latest
    ports:
    - 8080:80
    - 5432

services:
  redis:
    image: redis
    ports:
    - 6379/tcp

No es necesario especificar si el trabajo se ejecuta en un contenedor porque los contenedores de la misma red de Docker exponen automáticamente todos los puertos entre ports sí de forma predeterminada.

Si el trabajo se ejecuta en el host, es ports necesario tener acceso al servicio. Un puerto toma la forma o simplemente , con un opcional al final, por ejemplo, para exponer sobre el puerto , enlazado a un puerto aleatorio <hostPort>:<containerPort><containerPort> en el equipo /<protocol>6379/tcptcp6379 host.

Para los puertos enlazados a un puerto aleatorio en el equipo host, la canalización crea una variable con el formato para que el trabajo pueda acceder agent.services.<serviceName>.ports.<port> a él. Por ejemplo, agent.services.redis.ports.6379 se resuelve en el puerto asignado aleatoriamente en el equipo host.

Volúmenes

Los volúmenes son útiles para compartir datos entre servicios o para conservar datos entre varias ejecuciones de un trabajo.

Puede especificar montajes de volumen como una matriz de volumes . Los volúmenes se pueden denominar volúmenes de Docker, volúmenes de Docker anónimos o montajes de enlace en el host.

services:
  my_service:
    image: myservice:latest
    volumes:
    - mydockervolume:/data/dir
    - /data/dir
    - /src/dir:/dst/dir

Los volúmenes tienen el formato , donde puede ser un volumen con nombre o una ruta de acceso absoluta en el equipo host, y es una ruta de acceso <source>:<destinationPath><source> absoluta en el <destinationPath> contenedor.

Nota

Si usa nuestros grupos hospedados, los volúmenes no se conservarán entre trabajos porque la máquina host se limpia una vez completado el trabajo.

Otras opciones

Los contenedores de servicio comparten los mismos recursos de contenedor que los trabajos de contenedor. Esto significa que puede usar las mismas opciones adicionales.

Healthcheck

Opcionalmente, si algún contenedor de servicios especifica healthcheck, el agente espera hasta que el contenedor esté en buen estado antes de ejecutar el trabajo.