正式なドキュメントは英語版であり、この日本語訳はAI支援翻訳により作成された参考用のものです。日本語訳の一部の内容は人間によるレビューがまだ行われていないため、翻訳のタイミングにより英語版との間に差異が生じることがあります。最新かつ正確な情報については、英語版をご参照ください。

DockerコンテナでCI/CDジョブを実行する

  • プラン: Free、Premium、Ultimate
  • 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated

CI/CDジョブは、専用のCI/CDビルドサーバー、またはローカルマシンでホスティングされているDockerコンテナで実行できます。

DockerコンテナでCI/CDジョブを実行するには、次の操作が必要です:

  1. Docker executorを使用するようにRunnerを登録し、設定します。
  2. .gitlab-ci.ymlファイルでCI/CDジョブを実行するコンテナイメージを指定します。
  3. (オプション)MySQLなどの他のサービスをコンテナで実行します。そのためには、.gitlab-ci.ymlファイルでサービスを指定します。

Docker executorを使用するGitLab Runnerを登録する

GitLab RunnerをDockerで使用するには、Docker executorを使用するRunnerを登録する必要があります。

この例は、サービスを提供するための一時的なテンプレートの設定方法を示しています:

cat > /tmp/test-config.template.toml << EOF
[[runners]]
[runners.docker]
[[runners.docker.services]]
name = "postgres:latest"
[[runners.docker.services]]
name = "mysql:latest"
EOF

次に、以下のテンプレートを使用してRunnerを登録します:

sudo gitlab-runner register \
  --url "https://gitlab.example.com/" \
  --token "$RUNNER_TOKEN" \
  --description "docker-ruby:2.6" \
  --executor "docker" \
  --template-config /tmp/test-config.template.toml \
  --docker-image ruby:3.3

登録されたRunnerはruby:2.6Dockerイメージを使用し、postgres:latestmysql:latestの2つのサービスを実行します。どちらもビルドプロセス中にアクセスできます。

イメージとは

imageキーワードは、Docker executorがCI/CDジョブの実行に使用するDockerイメージの名前です。

デフォルトでは、executorはDocker Hubからイメージをプルします。ただし、レジストリの場所はgitlab-runner/config.tomlファイルで設定できます。たとえば、ローカルイメージを使用するようにDockerプルポリシーを設定できます。

イメージとDocker Hubの詳細については、Dockerの概要を参照してください。

イメージの要件

CI/CDジョブの実行に使用するイメージには、次のアプリケーションがインストールされている必要があります:

  • shまたはbash
  • grep

.gitlab-ci.ymlファイル内でimageを定義する

すべてのジョブで使用するイメージと、ランタイム中に使用するサービスのリストを定義できます:

default:
  image: ruby:2.6
  services:
    - postgres:16.10
  before_script:
    - bundle install

test:
  script:
    - bundle exec rake spec

イメージ名は、次のいずれかの形式にする必要があります:

  • image: <image-name>latestタグを付けて<image-name>を使用するのと同じ)
  • image: <image-name>:<tag>
  • image: <image-name>@<digest>

拡張Docker設定オプション

imageまたはservicesエントリには、文字列またはマップを使用できます:

  • 文字列には、完全なイメージ名を含める必要があります(Docker Hub以外のレジストリからイメージをダウンロードする場合は、レジストリも必要)。
  • マップには少なくともnameオプションを含める必要があり、その値には文字列設定と同じイメージ名を指定します。

たとえば、次の2つの定義は同じです:

  • 文字列でimageservicesを指定する:

    image: "registry.example.com/my/image:latest"
    
    services:
      - postgresql:16.10
      - redis:latest
  • マップでimageservicesを指定する。image:nameは必須です:

    image:
      name: "registry.example.com/my/image:latest"
    
    services:
      - name: postgresql:16.10
      - name: redis:latest

スクリプトが実行される場所

CIジョブがDockerコンテナで実行される場合、before_scriptscriptafter_scriptの各コマンドは/builds/<project-path>/ディレクトリで実行されます。使用しているイメージで定義されたデフォルトのWORKDIRは、そのディレクトリとは異なる場合があります。WORKDIRに移動するには、ジョブのランタイム中にコンテナ内で参照できるように、WORKDIRを環境変数として保存します。

イメージのエントリポイントをオーバーライドする

エントリポイントをオーバーライドする方法を説明する前に、Runnerの起動方法についてご説明します。Runnerは、CI/CDジョブで使用するコンテナを起動する際にDockerイメージを使用します:

  1. Runnerは、定義されたエントリポイントを使用してDockerコンテナを起動します。Dockerfileのデフォルトは、.gitlab-ci.ymlファイルでオーバーライドされる場合があります。
  2. Runnerは、実行中のコンテナに接続します。
  3. Runnerは、スクリプト(before_scriptscriptafter_scriptの組み合わせ)を準備します。
  4. Runnerは、スクリプトをコンテナのShellのstdinに送信し、その出力を受信します。

Dockerイメージのエントリポイントをオーバーライドするには、.gitlab-ci.ymlファイルで次の手順を実行します:

  • Docker 17.06以降では、entrypointを空の値に設定します。
  • Docker 17.03以前では、entrypoint/bin/sh -c/bin/bash -c、またはイメージで使用可能な同等のShellに設定します。

image:entrypointの構文は、DockerfileのENTRYPOINTと同様です。

SQLデータベースを含むsuper/sql:experimentalイメージがあるとします。このデータベースバイナリを使用していくつかのテストを実行するため、ジョブのベースイメージとして使用します。また、このイメージには、/usr/bin/super-sql runがエントリポイントとして設定されているとします。追加のオプションを指定せずにコンテナを起動すると、データベースのプロセスが実行されます。Runnerは、イメージにエントリポイントがないこと、または、Shellコマンドを開始するようにエントリポイントが準備されていることを想定しています。

拡張Docker設定オプションが導入されたことで、次の操作を行う必要がなくなりました:

  • super/sql:experimentalに基づいて独自のイメージを作成する。
  • ENTRYPOINTをShellに設定する。
  • CIジョブで新しいイメージを使用する。

.gitlab-ci.ymlファイルでentrypointを定義できるようになりました。

For Docker 17.06 and later(Docker 17.06以降の場合):

image:
  name: super/sql:experimental
  entrypoint: [""]

For Docker 17.03 and earlier(Docker 17.03以前の場合):

image:
  name: super/sql:experimental
  entrypoint: ["/bin/sh", "-c"]

config.tomlでイメージとサービスを定義する

config.tomlファイルでは、次の内容を定義できます:

[runners.docker]
  image = "ruby:latest"
  services = ["mysql:latest", "postgres:latest"]

この方法で定義されたイメージとサービスは、そのRunnerが実行するすべてのジョブに追加されます。

プライベートコンテナレジストリからイメージにアクセスする

プライベートコンテナレジストリにアクセスするために、GitLab Runnerプロセスは以下を使用できます:

同じGitLabインスタンスでGitLabコンテナレジストリを使用する場合、GitLabはこのレジストリのデフォルトの認証情報を提供します。これらの認証情報を使用すると、CI_JOB_TOKENが認証に使用されます。ジョブトークンを使用するには、ジョブを開始するユーザーが、プライベートイメージがホストされているプロジェクトのデベロッパーロール以上を持っている必要があります。プライベートイメージをホスティングするプロジェクトも、他のプロジェクトがジョブトークンで認証できるように許可する必要があります。このアクセスはデフォルトで無効になっています。詳細については、CI/CDジョブトークンを参照してください。

どのオプションを使用するかを定義するために、Runnerプロセスは次の順序で設定を読み取ります:

  • /root/.dockerディレクトリ内のconfig.jsonファイル。
  • DOCKER_AUTH_CONFIG CI/CD変数
  • Runnerのconfig.tomlファイルで設定されたDOCKER_AUTH_CONFIG環境変数。
  • プロセスを実行するユーザーの$HOME/.dockerディレクトリにあるconfig.jsonファイル。--userフラグが指定され、子プロセスが非特権ユーザーとして実行される場合、メインRunnerプロセスユーザーのホームディレクトリが使用されます。

要件と制限事項

  • 認証情報ストア認証情報ヘルパーを使用するには、それらのバイナリをGitLab Runnerの$PATHに追加する必要があり、そのためのアクセス権が必要です。したがって、これらの機能は、インスタンスRunnerや、Runnerがインストールされている環境へのアクセス権を持たない他のRunnerでは使用できません。

静的に定義された認証情報を使用する

次の2つの方法を使用してプライベートレジストリにアクセスできます。どちらも、適切な認証情報を使用してCI/CD変数DOCKER_AUTH_CONFIGを設定する必要があります。

  1. ジョブごと: あるジョブがプライベートレジストリにアクセスできるように設定するには、CI/CD変数としてDOCKER_AUTH_CONFIGを追加します。
  2. Runnerごと: すべてのジョブがプライベートレジストリにアクセスできるようにRunnerを設定するには、Runnerの設定でDOCKER_AUTH_CONFIGを環境変数として追加します。

それぞれの例については、以下のセクションを参照してください。

DOCKER_AUTH_CONFIGデータを決定する

例として、registry.example.com:5000/private/image:latestイメージを使用するとします。このイメージはプライベートであり、プライベートコンテナレジストリにサインインする必要があります。

また、次のサインイン認証情報があるとします:

キー
registryregistry.example.com:5000
usernamemy_username
passwordmy_password

DOCKER_AUTH_CONFIGの値を決定するには、次のいずれかの方法を使用します:

  • ローカルマシンでdocker loginを実行します:

    docker login registry.example.com:5000 --username my_username --password my_password

    次に、~/.docker/config.jsonの内容をコピーします。

    自分のコンピューターからレジストリにアクセスする必要がない場合は、docker logoutを実行できます:

    docker logout registry.example.com:5000
  • 一部のセットアップでは、Dockerクライアントが利用可能なシステムキーストアを使用して、docker loginの結果を保存することがあります。その場合、~/.docker/config.jsonを読み取ることは不可能であるため、${username}:${password}をBase64でエンコードした値を準備し、Docker設定JSONを手動で作成する必要があります。ターミナルを開き、次のコマンドを実行します:

    # The use of printf (as opposed to echo) prevents encoding a newline in the password.
    printf "my_username:my_password" | openssl base64 -A
    
    # Example output to copy
    bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=

    ユーザー名に@などの特殊文字が含まれている場合は、認証の問題を防ぐために、バックスラッシュ(\)でエスケープする必要があります。

    Docker JSON設定の内容を次のように作成します:

    {
        "auths": {
            "registry.example.com:5000": {
                "auth": "(Base64 content from above)"
            }
        }
    }

ジョブを設定する

registry.example.com:5000のアクセス権を持つように単一ジョブを設定するには、次の手順を実行します:

  1. CI/CD変数DOCKER_AUTH_CONFIGを作成し、その値に、Docker設定ファイルの内容を指定します:

    {
        "auths": {
            "registry.example.com:5000": {
                "auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ="
            }
        }
    }
  2. これで、.gitlab-ci.ymlファイルのimageservicesに定義した、registry.example.com:5000上の任意のプライベートイメージを使用できるようになります:

    image: registry.example.com:5000/namespace/image:tag

    前の例では、GitLab Runnerはregistry.example.com:5000を参照してイメージnamespace/image:tagを探します。

レジストリの設定は必要な数だけ追加できます。前述のとおり、"auths"ハッシュにレジストリを追加します。

RunnerがDOCKER_AUTH_CONFIGと照合できるようにするには、すべての場所で完全なhostname:portの組み合わせを指定する必要があります。たとえば、.gitlab-ci.ymlファイルでregistry.example.com:5000/namespace/image:tagが指定されている場合、DOCKER_AUTH_CONFIGでもregistry.example.com:5000を指定する必要があります。registry.example.comのみを指定しても機能しません。

Runnerを設定する

同じレジストリにアクセスするパイプラインが多数ある場合は、Runnerレベルでレジストリアクセスを設定する必要があります。これにより、パイプライン作成者は、適切なRunnerでジョブを実行するだけでプライベートレジストリにアクセスできるようになります。また、レジストリの変更と認証情報のローテーションを簡素化するのにも役立ちます。

つまり、そのRunnerで実行されるジョブは、複数のプロジェクトをまたいでも同じ権限でレジストリにアクセスできます。レジストリへのアクセスを制御する必要がある場合は、Runnerへのアクセスを制御するようにしてください。

RunnerにDOCKER_AUTH_CONFIGを追加するには、次の手順を実行します:

  1. Runnerのconfig.tomlファイルを次のように変更します:

    [[runners]]
      environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"registry.example.com:5000\":{\"auth\":\"bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=\"}}}"]
    • DOCKER_AUTH_CONFIGデータに含まれる二重引用符は、バックスラッシュでエスケープする必要があります。これにより、TOMLとして解釈されるのを防ぎます。
    • environmentオプションはリストです。Runnerに既存のエントリがある場合は、それを置き換えるのではなく、リストに追加する必要があります。
  2. Runnerサービスを再起動します。

認証情報ストアを使用する

認証情報ストアを設定するには、次の手順を実行します:

  1. 認証情報ストアを使用するには、特定のキーチェーンまたは外部ストアとやり取りするための外部ヘルパープログラムが必要です。ヘルパープログラムがGitLab Runnerの$PATHで使用できることを確認します。

  2. GitLab Runnerでそれを使用するようにします。これは、次のいずれかのオプションを使用して実現できます:

    • CI/CD変数DOCKER_AUTH_CONFIGを作成し、その値に、Docker設定ファイルの内容を指定します:

        {
          "credsStore": "osxkeychain"
        }
    • または、Self-Managed Runnerを実行している場合は、${GITLAB_RUNNER_HOME}/.docker/config.jsonにJSONを追加します。GitLab Runnerはこの設定ファイルを読み取り、この特定のリポジトリに必要なヘルパーを使用します。

credsStoreは、すべてレジストリへのアクセスに使用されます。プライベートレジストリのイメージとDocker Hubのパブリックイメージの両方を使用すると、Docker Hubからのプルは失敗します。Dockerデーモンは、すべてレジストリに同じ認証情報を使用しようとします。

認証情報ヘルパーを使用する

例として、<aws_account_id>.dkr.ecr.<region>.amazonaws.com/private/image:latestイメージを使用するとします。このイメージはプライベートであり、プライベートコンテナレジストリにサインインする必要があります。

<aws_account_id>.dkr.ecr.<region>.amazonaws.comへのアクセス権を設定するには、次の手順を実行します:

  1. docker-credential-ecr-loginがGitLab Runnerの$PATHで使用できることを確認します。

  2. 次のいずれかのAWS認証情報設定を用意します。GitLab Runnerがその認証情報にアクセスできることを確認します。

  3. GitLab Runnerでそれを使用するようにします。これは、次のいずれかのオプションを使用して実現できます:

    • CI/CD変数DOCKER_AUTH_CONFIGを作成し、その値に、Docker設定ファイルの内容を指定します:

      {
        "credHelpers": {
          "<aws_account_id>.dkr.ecr.<region>.amazonaws.com": "ecr-login"
        }
      }

      これにより、特定のレジストリに対して認証情報ヘルパーを使用するようにDockerが設定されます。

      代わりに、すべてのAmazon Elastic Container Registry(ECR)レジストリに対して認証情報ヘルパーを使用するようにDockerを設定できます:

      {
        "credsStore": "ecr-login"
      }

      {"credsStore": "ecr-login"}を使用する場合は、AWS共有設定ファイル(~/.aws/config)でリージョンを明示的に設定します。ECR認証情報ヘルパーが認証トークンを取得するときは、リージョンが指定されていなければなりません。

    • または、Self-Managed Runnerを実行している場合は、上記のJSONを${GITLAB_RUNNER_HOME}/.docker/config.jsonに追加します。GitLab Runnerはこの設定ファイルを読み取り、この特定のリポジトリに必要なヘルパーを使用します。

  4. これで、.gitlab-ci.ymlファイルのimageservicesに定義した、<aws_account_id>.dkr.ecr.<region>.amazonaws.com上の任意のプライベートイメージを使用できるようになります:

    image: <aws_account_id>.dkr.ecr.<region>.amazonaws.com/private/image:latest

    この例では、GitLab Runnerは<aws_account_id>.dkr.ecr.<region>.amazonaws.comを参照してイメージprivate/image:latestを探します。

レジストリの設定は必要な数だけ追加できます。それには、"credHelpers"ハッシュにレジストリを追加します。

チェックサムを使用してイメージを保護する

.gitlab-ci.ymlファイルのジョブ定義でイメージチェックサムを使用して、イメージの整合性を検証します。イメージの整合性検証が失敗すると、変更されたコンテナを使用できなくなります。

イメージチェックサムを使用するには、チェックサムを末尾に追加する必要があります:

image: ruby:2.6.8@sha256:d1dbaf9665fe8b2175198e49438092fdbcf4d8934200942b94425301b17853c7

イメージチェックサムを取得するには、イメージのTAGで、DIGEST列を確認します。たとえば、Rubyイメージを確認してください。チェックサムは、6155f0235e95のようなランダムな文字列です。

システム上の任意のイメージについては、コマンドdocker images --digestsを使用してチェックサムを取得することもできます:

❯ docker images --digests
REPOSITORY                                                        TAG       DIGEST                                                                    (...)
gitlab/gitlab-ee                                                  latest    sha256:723aa6edd8f122d50cae490b1743a616d54d4a910db892314d68470cc39dfb24   (...)
gitlab/gitlab-runner                                              latest    sha256:4a18a80f5be5df44cb7575f6b89d1fdda343297c6fd666c015c0e778b276e726   (...)

カスタムGitLab Runner Dockerイメージを作成する

カスタムGitLab Runner Dockerイメージを作成して、AWS CLIとAmazon ECR認証情報ヘルパーをパッケージ化できます。この設定により、特にコンテナ化されたアプリケーションにおいて、AWSサービスとの安全で効率化されたやり取りが容易になります。たとえば、次の設定を使用して、Amazon ECR上のDockerイメージを管理、デプロイ、更新できます。この設定は、時間がかかってエラーが発生しやすい設定や、手動による認証情報の管理を回避するのに役立ちます。

  1. AWSに対してGitLabを認証します

  2. 次の内容を含むDockerfileを作成します:

    # Control package versions
    ARG GITLAB_RUNNER_VERSION=v17.3.0
    ARG AWS_CLI_VERSION=2.17.36
    
    # AWS CLI and Amazon ECR Credential Helper
    FROM amazonlinux as aws-tools
    RUN set -e \
        && yum update -y \
        && yum install -y --allowerasing git make gcc curl unzip \
        && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" --output "awscliv2.zip" \
        && unzip awscliv2.zip && ./aws/install -i /usr/local/bin \
        && yum clean all
    
    # Download and install ECR Credential Helper
    RUN curl --location --output  /usr/local/bin/docker-credential-ecr-login "https://github.com/awslabs/amazon-ecr-credential-helper/releases/latest/download/docker-credential-ecr-login-linux-amd64"
    RUN chmod +x /usr/local/bin/docker-credential-ecr-login
    
    # Configure the ECR Credential Helper
    RUN mkdir -p /root/.docker
    RUN echo '{ "credsStore": "ecr-login" }' > /root/.docker/config.json
    
    # Final image based on GitLab Runner
    FROM gitlab/gitlab-runner:${GITLAB_RUNNER_VERSION}
    
    # Install necessary packages
    RUN apt-get update \
        && apt-get install -y --no-install-recommends jq procps curl unzip groff libgcrypt20 tar gzip less openssh-client \
        && apt-get clean && rm -rf /var/lib/apt/lists/*
    
    # Copy AWS CLI and Amazon ECR Credential Helper binaries
    COPY --from=aws-tools /usr/local/bin/ /usr/local/bin/
    
    # Copy ECR Credential Helper Configuration
    COPY --from=aws-tools /root/.docker/config.json /root/.docker/config.json
  3. .gitlab-ci.ymlでカスタムGitLab Runner Dockerイメージをビルドするには、次の例のとおりに追加します:

    variables:
      DOCKER_DRIVER: overlay2
      IMAGE_NAME: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
      GITLAB_RUNNER_VERSION: v17.3.0
      AWS_CLI_VERSION: 2.17.36
    
    stages:
      - build
    
    build-image:
      stage: build
      script:
        - echo "Logging into GitLab container registry..."
        - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
        - echo "Building Docker image..."
        - docker build --build-arg GITLAB_RUNNER_VERSION=${GITLAB_RUNNER_VERSION} --build-arg AWS_CLI_VERSION=${AWS_CLI_VERSION} -t ${IMAGE_NAME} .
        - echo "Pushing Docker image to GitLab container registry..."
        - docker push ${IMAGE_NAME}
      rules:
        - changes:
            - Dockerfile
  4. Runnerを登録します