次の方法で共有


サービス コンテナー

Azure DevOps Services

パイプラインで 1 つ以上のサービスのサポートが必要な場合は、ジョブごとにサービスの作成、接続、クリーンアップが必要になる場合があります。 たとえば、パイプラインでは、新しく作成されたデータベースと、パイプライン内の各ジョブのメモリ キャッシュへのアクセスを必要とする統合テストを実行できます。

コンテナーは、パイプラインが依存するサービスを簡単かつ移植可能な方法で実行できます。 サービス コンテナーを使用すると、コンテナー化されたサービスのライフサイクルを自動的に作成、ネットワーク化、管理できます。 各サービス コンテナーには、それを必要とする job のみがアクセスできます。 サービス コンテナーはあらゆる種類のジョブで動作しますが、 コンテナー ジョブで最もよく使用されます。

要件

  • サービス コンテナーでは、CMD または ENTRYPOINT を定義する必要があります。 パイプラインは、指定されたコンテナーに対して引数なしで docker run 実行されます。

  • Azure Pipelines では、Linux コンテナーまたは Windows コンテナーを実行できます。 Linux コンテナー用のホストされた Ubuntu コンテナー プールまたは Windows コンテナー用のホストされた Windows プールを使用できます。 ホストされている macOS プールは、コンテナーの実行をサポートしていません。

Note

サービス コンテナーは、クラシック パイプラインではサポートされていません。

単一コンテナー ジョブ

次の YAML パイプライン定義の例は、1 つのコンテナー ジョブを示しています。

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

上記のパイプラインは、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-latest'

services:
  nginx: nginx
  redis: redis

steps:
- script: |
    curl localhost:8080
    echo $AGENT_SERVICES_REDIS_PORTS_6379

上記のパイプラインは、最新の nginx コンテナーを開始します。 ジョブはコンテナーで実行されていないため、名前の自動解決は行われません。 代わりに、 localhostを使用してサービスにアクセスできます。 この例では、 8080:80 ポートを明示的に提供します。

また、実行時にランダムなポートを動的に割り当てる方法もあります。 その後、変数を使用してこれらの動的ポートにアクセスできます。 これらの変数は、agent.services.<serviceName>.ports.<port> の形式になります。 Bash スクリプトでは、プロセス環境を使用して変数にアクセスできます。

前の例では、 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

Port

コンテナー リソースまたはインライン コンテナーを呼び出すときに、次の例のように、コンテナーで公開する 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>を受け取るか、末尾に省略可能な/<protocol>を使用して<containerPort>します。 たとえば、6379/tcpは、ホスト コンピューター上のランダムなポートにバインドされたポート 6379経由でtcpを公開します。

ホスト マシン上のランダム ポートにバインドされたポートの場合、パイプラインは、ジョブがポートにアクセスできるように、 agent.services.<serviceName>.ports.<port> 形式の変数を作成します。 たとえば、agent.services.redis.ports.6379 はホスト コンピューター上のランダムに割り当てられたポートに解決されます。

ボリューム

ボリュームは、サービス間でデータを共有したり、ジョブの複数の実行間でデータを保持したりする場合に便利です。 ボリューム マウントは、フォーム <source>:<destinationPath>volumesの配列として指定します。ここで、<source>はホスト コンピューター上の名前付きボリュームまたは絶対パスを指定でき、<destinationPath>はコンテナー内の絶対パスです。 ボリュームには、Docker ボリューム、匿名 Docker ボリューム、またはホスト上のバインド マウントという名前を付けることができます。

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

Note

Microsoft でホストされているプールを使用する場合、各ジョブが完了した後にホスト マシンがクリーンアップされるため、ジョブ間でボリュームは保持されません。

スタートアップ オプション

サービス コンテナーは、コンテナー ジョブと同じコンテナー リソースを共有します。 つまり、同じ スタートアップ オプションを使用できます

正常性チェック

いずれかのサービス コンテナーで HEALTHCHECK が指定されている場合、エージェントは必要に応じて、コンテナーが正常になるまで待機してからジョブを実行できます。

サービスを含む複数のコンテナーの例

次の例では、PostgreSQL と MySQL データベース コンテナーに接続された Django Python Web コンテナーがあります。

  • PostgreSQL データベースはプライマリ データベースであり、そのコンテナーには db という名前が付けられています。
  • db コンテナーはボリューム /data/db:/var/lib/postgresql/dataを使用し、envを介してコンテナーに渡される 3 つのデータベース変数があります。
  • mysql コンテナーはポート 3306:3306を使用し、env経由で渡されるデータベース変数もあります。
  • web コンテナーはポート 8000で開いています。

この手順では、 pip 依存関係をインストールしてから、Django テストを実行します。

作業例を設定するには、2 つのデータベースを使用して 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