次の方法で共有


YAML パイプライン内のコンテナー ジョブ

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

この記事では、Azure Pipelines のコンテナー ジョブについて説明します。

既定では、Azure Pipelines jobs エージェントがインストールされているホスト マシンで直接実行されます。 ホストされるエージェント ジョブは便利で、初期セットアップと保守のためのインフラストラクチャはほとんど必要なく、基本的なプロジェクトに適しています。

タスク コンテキストをより詳細に制御する場合は、コンテナーでジョブを定義して実行できます。 コンテナーは、ホストから分離を提供するホスト オペレーティング システムに対する軽量の抽象化です。 コンテナーでジョブを実行する場合は、ビルドに必要なオペレーティング システム、ツール、依存関係の正確なバージョンを選択できます。

Linux および Windows agents は、ホストまたはコンテナーでパイプライン ジョブを直接実行できます。 コンテナー ジョブは macOS では使用できません。

コンテナー ジョブの場合、エージェントは最初にコンテナーをフェッチして開始します。 その後、ジョブの各ステップがコンテナー内で実行されます。

個々のビルド ステップ レベルできめ細かな制御が必要な場合は、 ステップ ターゲット 各ステップのコンテナーまたはホストを選択できます。

要件と制限

Azure Pipelines エージェントのホストまたはコンテナーには、次の要件と制限が適用されます。

エージェント ホスト

  • windows-*ubuntu-* のイメージのみがコンテナーの実行をサポートします。 macos-* イメージでは、コンテナーの実行はサポートされていません。
  • コンテナーを実行するには、Windows および Linux エージェント ホストに Docker がインストールされていて、Docker デーモンにアクセスするためのアクセス許可が必要です。
  • エージェントがコンテナー内で既に実行されている場合、コンテナーはサポートされません。 入れ子になったコンテナーを使用することはできません。

Containers

Linux ベースのコンテナーには、次の要件があります。 回避策については、 Nonglibc ベースのコンテナーを参照してください。

  • Bash がインストールされている
  • GNU C ライブラリ (glibc) ベース
  • ENTRYPOINT なし
  • を使用せずに、groupaddやその他の特権コマンドへのアクセスをUSERに提供するsudo
  • エージェントが提供するNode.jsを実行できます

    Note

    Node.jsは、Windows ホスト上の Linux コンテナー用にプレインストールする必要があります。

Docker Hub で使用できる一部の削除されたコンテナー (特に Alpine Linux に基づくコンテナー) は、これらの要件を満たしていません。 Azure Pipelines がdocker createし、コンテナーが常に稼働docker exec想定しているため、ENTRYPOINTを持つコンテナーが機能しない可能性があります。

単一ジョブの例

次の例では、1 つのジョブの Windows または Linux コンテナーを定義します。

次の簡単な例では、Linux コンテナーを定義します。

pool:
  vmImage: 'ubuntu-latest'

container: ubuntu:18.04

steps:
- script: printenv

前の例では、Docker Hub から18.04タグ付けされたubuntuイメージをフェッチしコンテナーを開始するようにシステムに指示します。 printenv コマンドは、ubuntu:18.04 コンテナー内で実行されます。

複数のジョブ

コンテナーを使用して、複数のジョブで同じ手順を実行できます。 次の例では、複数のバージョンの Ubuntu Linux で同じ手順を実行します。 1 つのジョブのみが定義されているため、 jobs キーワードに言及する必要はありません。

pool:
  vmImage: 'ubuntu-latest'

strategy:
  matrix:
    ubuntu16:
      containerImage: ubuntu:16.04
    ubuntu18:
      containerImage: ubuntu:18.04
    ubuntu20:
      containerImage: ubuntu:20.04

container: $[ variables['containerImage'] ]

steps:
- script: printenv

1 つのエージェント ホスト上のエージェント プールを持つ複数のジョブ

コンテナー ジョブは、基になるホスト エージェントの Docker 構成ファイルを使用して、イメージ レジストリの承認を行います。 このファイルは、Docker レジストリ コンテナーの初期化の最後にサインアウトします。 並列で実行されている別のジョブが既に Docker 構成ファイルをサインアウトしているため、後続のコンテナー ジョブのレジストリ イメージ プルが unauthorized authentication に対して拒否される可能性があります。

解決策は、ホストされているエージェントで実行されている各エージェント プールに固有の Docker 環境変数 DOCKER_CONFIG を設定することです。 各エージェント プールのrunsvc.sh スクリプトのDOCKER_CONFIGを次のようにエクスポートします。

export DOCKER_CONFIG=./.docker

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

次の例のように、コンテナーの起動を制御する options を指定できます。

container:
  image: ubuntu:18.04
  options: --hostname container-test --ip 192.168.0.1

steps:
- script: echo hello

docker create --helpを実行すると、Docker 呼び出しに渡すことができるオプションの一覧が表示されます。 これらのオプションのすべてが Azure DevOps で動作することが保証されているわけではありません。 最初に、 container プロパティを使用して同じ目標を達成できるかどうかを確認します。

詳細については、azure DevOps YAML スキーマ リファレンスの docker create コマンド リファレンスと resources.containers.container 定義 を参照してください。

再利用可能なコンテナー定義

次の例では、 resources セクションでコンテナーを定義し、割り当てられたエイリアスでコンテナーを参照します。 わかりやすくするために、 jobs キーワードが明示的に一覧表示されています。

resources:
  containers:
  - container: u16
    image: ubuntu:16.04

  - container: u18
    image: ubuntu:18.04

  - container: u20
    image: ubuntu:20.04

jobs:
- job: RunInContainer
  pool:
    vmImage: 'ubuntu-latest'

  strategy:
    matrix:
      ubuntu16:
        containerResource: u16
      ubuntu18:
        containerResource: u18
      ubuntu20:
        containerResource: u20

  container: $[ variables['containerResource'] ]

  steps:
  - script: printenv

サービス エンドポイント

パブリック Docker Hub 以外のレジストリでコンテナーをホストできます。 Azure Container Registry またはプライベート Docker Hub レジストリを含む別のプライベート コンテナー レジストリでイメージをホストするには、サービス接続を追加してレジストリにアクセスします。 その後、コンテナー定義内のエンドポイントを参照できます。

プライベート Docker Hub 接続:

container:
  image: registry:ubuntu1804
  endpoint: private_dockerhub_connection

Azure Container Registry 接続:

container:
  image: myprivate.azurecr.io/windowsservercore:1803
  endpoint: my_acr_connection

Note

Azure Pipelines は Amazon Elastic Container Registry (ECR) のサービス接続を設定できません。Amazon ECR では、AWS の資格情報を Docker が認証に使用できるものに変換するために他のクライアント ツールが必要であるためです。

非glibc ベースのコンテナー

Azure Pipelines エージェントは、タスクとスクリプトを実行するために必要な Node.js のコピーを提供します。 ホステッド エージェントの Node.js のバージョンを確認するには、「Microsoft ホステッド エージェント」を参照してください。

Node.jsのバージョンは、ホストされたクラウド (通常は glibc) で使用される C ランタイムに対してコンパイルされます。 一部の Linux バリアントでは、他の C ランタイムが使用されます。 たとえば、Alpine Linux は musl を使用します。

非glibc ベースのコンテナーを使用する場合は、次の手順を実行する必要があります。

  • Node.jsの独自のコピーを指定します。
  • Node.js バイナリを検索する場所をエージェントに伝えるラベルをイメージに追加します。
  • Azure Pipelines が依存するその他の依存関係 ( bashsudowhichgroupadd) を提供します。

独自のNode.jsを提供する

非glibc ベースのコンテナーを使用する場合は、Node バイナリをコンテナーに追加する必要があります。 Node.js 18は安全な選択です。 node:18-alpineイメージから開始します。

エージェントに Node.js について伝える

エージェントは、コンテナー ラベル "com.azure.dev.pipelines.handler.node.path"を読み取ります。 このラベルが存在する場合は、Node.js バイナリへのパスのはずです。

たとえば、 node:18-alpineに基づくイメージで、Dockerfile に次の行を追加します。

LABEL "com.azure.dev.pipelines.agent.handler.node.path"="/usr/local/bin/node"

必要なパッケージを追加する

Azure Pipelines では、共通の管理パッケージがインストールされた Bash ベースのシステムを想定しています。 特に、Alpine Linux には必要なパッケージがいくつかありません。 基本的なニーズに対応するために、 bashsudo、および shadow をインストールします。

RUN apk add bash sudo shadow

インボックス タスクまたは Marketplace タスクに依存している場合は、必要なバイナリも指定します。

完全な Dockerfile の例

FROM node:18-alpine

RUN apk add --no-cache --virtual .pipeline-deps readline linux-pam \
  && apk add bash sudo shadow \
  && apk del .pipeline-deps

LABEL "com.azure.dev.pipelines.agent.handler.node.path"="/usr/local/bin/node"

CMD [ "node" ]