Dela via


Tjänstcontainrar

Azure DevOps Services

Om din pipeline kräver stöd för en eller flera tjänster vill du i många fall skapa, ansluta till och rensa varje tjänst per jobb. En pipeline kan till exempel köra integreringstester som kräver åtkomst till en databas och en minnescache. Databasen och minnescachen måste skapas nyligen för varje jobb i pipelinen.

En container är ett enkelt och portabelt sätt att köra en tjänst som din pipeline är beroende av. Med en tjänstcontainer kan du automatiskt skapa, nätverka och hantera livscykeln för din containertjänst. Varje tjänstcontainer är endast tillgänglig för det jobb som behöver den. Tjänstcontainrar fungerar med alla typer av jobb, men de används oftast med containerjobb.

Krav

Tjänstcontainrar måste definiera en CMD eller ENTRYPOINT. Pipelinen körs docker run för den angivna containern utan ytterligare argument.

Azure Pipelines kan köra Linux- eller Windows-containrar. Använd antingen värdbaserad Ubuntu för Linux-containrar eller den värdbaserade Windows-containerpoolen för Windows-containrar. (Den värdbaserade macOS-poolen stöder inte containrar som körs.)

Jobb med en enda container

Ett enkelt exempel på hur du använder containerjobb:

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

Den här pipelinen hämtar containrarna nginx och buildpack-deps från Docker Hub och startar sedan containrarna. Containrarna nätverkas tillsammans så att de kan nå varandra med deras services namn.

Inifrån den här jobbcontainern nginx matchas värdnamnet till rätt tjänster med hjälp av Docker-nätverk. Alla containrar i nätverket exponerar automatiskt alla portar för varandra.

Enstaka jobb

Du kan också använda tjänstcontainrar utan en jobbcontainer. Ett enkelt exempel:

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

Den här pipelinen startar de senaste nginx containrarna. Eftersom jobbet inte körs i en container finns det ingen automatisk namnmatchning. Det här exemplet visar hur du i stället kan nå tjänster med hjälp localhostav . I exemplet ovan anger vi porten explicit (till exempel 8080:80).

En annan metod är att låta en slumpmässig port tilldelas dynamiskt vid körning. Du kan sedan komma åt dessa dynamiska portar med hjälp av variabler. I ett Bash-skript kan du komma åt en variabel med hjälp av processmiljön. Dessa variabler har formatet : agent.services.<serviceName>.ports.<port>. I exemplet ovan redis tilldelas en slumpmässig tillgänglig port på värden. Variabeln agent.services.redis.ports.6379 innehåller portnumret.

Flera jobb

Tjänstcontainrar är också användbara för att köra samma steg mot flera versioner av samma tjänst. I följande exempel körs samma steg mot flera versioner av 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

Portar

När du anger en containerresurs eller en infogad container kan du ange en matris ports med som ska exponeras för containern.

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

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

Du ports behöver inte ange om jobbet körs i en container eftersom containrar i samma Docker-nätverk automatiskt exponerar alla portar för varandra som standard.

Om jobbet körs på värden måste du ports ha åtkomst till tjänsten. En port har formatet <hostPort>:<containerPort> eller bara <containerPort>, med ett valfritt /<protocol> i slutet, till exempel 6379/tcp för att exponera tcp via port 6379, som är bunden till en slumpmässig port på värddatorn.

För portar som är bundna till en slumpmässig port på värddatorn skapar pipelinen en variabel i formuläret agent.services.<serviceName>.ports.<port> så att den kan nås av jobbet. Matchar till exempel agent.services.redis.ports.6379 den slumpmässigt tilldelade porten på värddatorn.

Volymer

Volymer är användbara för att dela data mellan tjänster eller för att bevara data mellan flera körningar av ett jobb.

Du kan ange volymmonteringar som en matris med volumes. Volymer kan antingen heta Docker-volymer, anonyma Docker-volymer eller bindningsmonteringar på värden.

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

Volymer har formatet <source>:<destinationPath>, där <source> kan vara en namngiven volym eller en absolut sökväg på värddatorn och <destinationPath> är en absolut sökväg i containern.

Anteckning

Om du använder våra värdbaserade pooler sparas inte dina volymer mellan jobben eftersom värddatorn rensas när jobbet har slutförts.

Andra alternativ

Tjänstcontainrar delar samma containerresurser som containerjobb. Det innebär att du kan använda samma ytterligare alternativ.

Hälsokontroll

Om någon tjänstcontainer anger en HEALTHCHECK väntar agenten tills containern är felfri innan jobbet körs.

Exempel på flera containrar med tjänster

I det här exemplet finns det en Django Python-webbcontainer ansluten till två databascontainrar – PostgreSQL och MySQL. PostgreSQL-databasen är den primära databasen och dess container har namnet db. Containern db använder volym /data/db:/var/lib/postgresql/data och det finns tre databasvariabler som skickas till containern via env. Containern mysql använder port 3306:3306 och det finns även databasvariabler som skickas via env. Containern web är öppen med port 8000. I stegen pip installerar beroenden och sedan körs Django-testet. Om du vill konfigurera ett fungerande exempel behöver du en Django-webbplats med två databaser. Det här exemplet förutsätter att filen manage.py finns i rotkatalogen och att Django-projektet finns i den katalogen. Du kan behöva uppdatera /__w/1/s/ sökvägen i /__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