Udostępnij za pośrednictwem


Kontenery usługi

Azure DevOps Services

Jeśli potok wymaga obsługi co najmniej jednej usługi, może być konieczne utworzenie, nawiązanie połączenia i wyczyszczenie usług na zadanie. Na przykład potok może uruchamiać testy integracji, które wymagają dostępu do nowo utworzonej bazy danych i pamięci podręcznej dla każdego zadania w potoku.

Kontener zapewnia prosty i przenośny sposób uruchamiania usługi, od którego zależy potok. Kontener usługi umożliwia automatyczne tworzenie, sieć i zarządzanie cyklem życia konteneryzowanej usługi. Każdy kontener usługi jest dostępny tylko dla zadania , które go wymaga. Kontenery usługi działają z dowolnym rodzajem zadania, ale są najczęściej używane z zadaniami kontenera.

Wymagania

  • Kontenery usługi muszą definiować element CMD lub ENTRYPOINT. Potok jest uruchamiany docker run dla podanego kontenera bez żadnych argumentów.

  • Usługa Azure Pipelines może uruchamiać kontenery systemu Linux lub Windows. Możesz użyć hostowanej puli kontenerów systemu Ubuntu dla kontenerów systemu Linux lub hostowanej puli systemu Windows dla kontenerów systemu Windows. Hostowana pula systemu macOS nie obsługuje uruchomionych kontenerów.

Uwaga

Kontenery usługi nie są obsługiwane w potokach klasycznych.

Jedno zadanie kontenera

Poniższa przykładowa definicja potoku YAML przedstawia jedno zadanie kontenera.

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

Powyższy potok pobiera nginx kontenery i buildpack-deps z usługi Docker Hub , a następnie uruchamia kontenery. Kontenery są połączone w sieć, aby mogły się ze sobą łączyć według ich services nazwy.

Z poziomu tego kontenera nginx zadań nazwa hosta jest rozpoznawana jako poprawne usługi przy użyciu sieci platformy Docker. Wszystkie kontenery w sieci automatycznie uwidaczniają sobie wszystkie porty.

Jedno zadanie niekontenerowe

Kontenery usług można również używać bez kontenera zadań, jak w poniższym przykładzie.

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

Poprzedni potok uruchamia najnowsze nginx kontenery. Ponieważ zadanie nie jest uruchomione w kontenerze, nie ma automatycznego rozpoznawania nazw. Zamiast tego możesz uzyskać dostęp do usług przy użyciu polecenia localhost. Przykład jawnie udostępnia 8080:80 port.

Alternatywną metodą jest dynamiczne przypisywanie losowego portu w czasie wykonywania. Następnie możesz uzyskać dostęp do tych portów dynamicznych przy użyciu zmiennych. Te zmienne mają postać: agent.services.<serviceName>.ports.<port>. W skryscie powłoki Bash można uzyskać dostęp do zmiennych przy użyciu środowiska przetwarzania.

W poprzednim przykładzie redis przypisano losowy dostępny port na hoście. Zmienna agent.services.redis.ports.6379 zawiera numer portu.

Wiele zadań

Kontenery usługi są również przydatne do uruchamiania tych samych kroków w wielu wersjach tej samej usługi. W poniższym przykładzie te same kroki są wykonywane względem wielu wersji bazy danych 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

Porty

Podczas wywoływania zasobu kontenera lub wbudowanego kontenera można określić tablicę ports do uwidocznienia w kontenerze, jak w poniższym przykładzie.

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

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

Określenie ports nie jest wymagane, jeśli zadanie jest uruchomione w kontenerze, ponieważ kontenery w tej samej sieci platformy Docker automatycznie uwidaczniają wszystkie porty do siebie domyślnie.

Jeśli zadanie jest uruchomione na hoście, ports wymagane jest uzyskanie dostępu do usługi. Port przyjmuje formularz <hostPort>:<containerPort> lub po prostu <containerPort> opcjonalny /<protocol> na końcu. Na przykład 6379/tcp uwidacznia tcp port 6379, powiązany z losowym portem na maszynie hosta.

W przypadku portów powiązanych z losowym portem na maszynie hosta potok tworzy zmienną formularza agent.services.<serviceName>.ports.<port> , dzięki czemu zadanie może uzyskać dostęp do portu. Na przykład agent.services.redis.ports.6379 jest rozpoznawany losowo przypisany port na maszynie hosta.

Woluminy

Woluminy są przydatne do udostępniania danych między usługami lub utrwalania danych między wieloma przebiegami zadania. Woluminy są określane jako tablica volumes formularza <source>:<destinationPath>, gdzie <source> może być nazwanym woluminem lub ścieżką bezwzględną na maszynie hosta i <destinationPath> jest ścieżką bezwzględną w kontenerze. Woluminy mogą mieć nazwę Woluminy platformy Docker, anonimowe woluminy platformy Docker lub powiązane instalacje na hoście.

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

Uwaga

Jeśli używasz pul hostowanych przez firmę Microsoft, woluminy nie są utrwalane między zadaniami, ponieważ maszyna hosta jest czyszczona po zakończeniu każdego zadania.

Opcje uruchamiania

Kontenery usługi współdzielą te same zasoby kontenera co zadania kontenera. Oznacza to, że można użyć tych samych opcji uruchamiania.

Sprawdzanie kondycji

Jeśli jakikolwiek kontener usługi określa HEALTHCHECK, agent może opcjonalnie poczekać, aż kontener będzie w dobrej kondycji przed uruchomieniem zadania.

Przykład wielu kontenerów z usługami

Poniższy przykład zawiera kontener internetowy Django Python połączony z kontenerami baz danych PostgreSQL i MySQL.

  • Baza danych PostgreSQL jest podstawową bazą danych, a jej kontener nosi nazwę db.
  • Kontener db używa woluminu /data/db:/var/lib/postgresql/datai istnieją trzy zmienne bazy danych przekazywane do kontenera za pośrednictwem polecenia env.
  • Kontener mysql używa portu 3306:3306i istnieją również zmienne bazy danych przekazywane za pośrednictwem polecenia env.
  • Kontener web jest otwarty z portem 8000.

W krokach zainstaluje zależności, pip a następnie uruchomi testy Django.

Aby skonfigurować działający przykład, musisz skonfigurować witrynę Django z dwoma bazami danych. W przykładzie przyjęto założenie, że plik manage.py znajduje się w katalogu głównym, a projekt Django znajduje się również w tym katalogu. Jeśli nie, może być konieczne zaktualizowanie ścieżki /__w/1/s/ w pliku /__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