DockerコンテナでCI/CDジョブを実行する
- プラン: Free、Premium、Ultimate
- 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated
CI/CDジョブは、専用のCI/CDビルドサーバー、またはローカルマシンでホスティングされているDockerコンテナで実行できます。
DockerコンテナでCI/CDジョブを実行するには、次の操作が必要です:
- Docker executorを使用するようにRunnerを登録し、設定します。
.gitlab-ci.ymlファイルでCI/CDジョブを実行するコンテナイメージを指定します。- (オプション)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:latestとmysql:latestの2つのサービスを実行します。どちらもビルドプロセス中にアクセスできます。
イメージとは
imageキーワードは、Docker executorがCI/CDジョブの実行に使用するDockerイメージの名前です。
デフォルトでは、executorはDocker Hubからイメージをプルします。ただし、レジストリの場所はgitlab-runner/config.tomlファイルで設定できます。たとえば、ローカルイメージを使用するようにDockerプルポリシーを設定できます。
イメージとDocker Hubの詳細については、Dockerの概要を参照してください。
イメージの要件
CI/CDジョブの実行に使用するイメージには、次のアプリケーションがインストールされている必要があります:
shまたはbashgrep
.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つの定義は同じです:
文字列で
imageとservicesを指定する:image: "registry.example.com/my/image:latest" services: - postgresql:16.10 - redis:latestマップで
imageとservicesを指定する。image:nameは必須です:image: name: "registry.example.com/my/image:latest" services: - name: postgresql:16.10 - name: redis:latest
スクリプトが実行される場所
CIジョブがDockerコンテナで実行される場合、before_script、script、after_scriptの各コマンドは/builds/<project-path>/ディレクトリで実行されます。使用しているイメージで定義されたデフォルトのWORKDIRは、そのディレクトリとは異なる場合があります。WORKDIRに移動するには、ジョブのランタイム中にコンテナ内で参照できるように、WORKDIRを環境変数として保存します。
イメージのエントリポイントをオーバーライドする
エントリポイントをオーバーライドする方法を説明する前に、Runnerの起動方法についてご説明します。Runnerは、CI/CDジョブで使用するコンテナを起動する際にDockerイメージを使用します:
- Runnerは、定義されたエントリポイントを使用してDockerコンテナを起動します。
Dockerfileのデフォルトは、.gitlab-ci.ymlファイルでオーバーライドされる場合があります。 - Runnerは、実行中のコンテナに接続します。
- Runnerは、スクリプト(
before_script、script、after_scriptの組み合わせ)を準備します。 - 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]セクション: CI/CDジョブの実行に使用するコンテナイメージ[[runners.docker.services]]セクション: サービスコンテナ
[runners.docker]
image = "ruby:latest"
services = ["mysql:latest", "postgres:latest"]この方法で定義されたイメージとサービスは、そのRunnerが実行するすべてのジョブに追加されます。
プライベートコンテナレジストリからイメージにアクセスする
プライベートコンテナレジストリにアクセスするために、GitLab Runnerプロセスは以下を使用できます:
- 静的に定義された認証情報。特定のレジストリのユーザー名とパスワード。
- 認証情報ストア。詳細については、関連するDockerドキュメントを参照してください。
- 認証情報ヘルパー。詳細については、関連するDockerドキュメントを参照してください。
同じGitLabインスタンスでGitLabコンテナレジストリを使用する場合、GitLabはこのレジストリのデフォルトの認証情報を提供します。これらの認証情報を使用すると、CI_JOB_TOKENが認証に使用されます。ジョブトークンを使用するには、ジョブを開始するユーザーが、プライベートイメージがホストされているプロジェクトのデベロッパーロール以上を持っている必要があります。プライベートイメージをホスティングするプロジェクトも、他のプロジェクトがジョブトークンで認証できるように許可する必要があります。このアクセスはデフォルトで無効になっています。詳細については、CI/CDジョブトークンを参照してください。
どのオプションを使用するかを定義するために、Runnerプロセスは次の順序で設定を読み取ります:
/root/.dockerディレクトリ内のconfig.jsonファイル。DOCKER_AUTH_CONFIGCI/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を設定する必要があります。
- ジョブごと: あるジョブがプライベートレジストリにアクセスできるように設定するには、CI/CD変数として
DOCKER_AUTH_CONFIGを追加します。 - Runnerごと: すべてのジョブがプライベートレジストリにアクセスできるようにRunnerを設定するには、Runnerの設定で
DOCKER_AUTH_CONFIGを環境変数として追加します。
それぞれの例については、以下のセクションを参照してください。
DOCKER_AUTH_CONFIGデータを決定する
例として、registry.example.com:5000/private/image:latestイメージを使用するとします。このイメージはプライベートであり、プライベートコンテナレジストリにサインインする必要があります。
また、次のサインイン認証情報があるとします:
| キー | 値 |
|---|---|
| registry | registry.example.com:5000 |
| username | my_username |
| password | my_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のアクセス権を持つように単一ジョブを設定するには、次の手順を実行します:
CI/CD変数
DOCKER_AUTH_CONFIGを作成し、その値に、Docker設定ファイルの内容を指定します:{ "auths": { "registry.example.com:5000": { "auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=" } } }これで、
.gitlab-ci.ymlファイルのimageやservicesに定義した、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を追加するには、次の手順を実行します:
Runnerの
config.tomlファイルを次のように変更します:[[runners]] environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"registry.example.com:5000\":{\"auth\":\"bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=\"}}}"]DOCKER_AUTH_CONFIGデータに含まれる二重引用符は、バックスラッシュでエスケープする必要があります。これにより、TOMLとして解釈されるのを防ぎます。environmentオプションはリストです。Runnerに既存のエントリがある場合は、それを置き換えるのではなく、リストに追加する必要があります。
Runnerサービスを再起動します。
認証情報ストアを使用する
認証情報ストアを設定するには、次の手順を実行します:
認証情報ストアを使用するには、特定のキーチェーンまたは外部ストアとやり取りするための外部ヘルパープログラムが必要です。ヘルパープログラムがGitLab Runnerの
$PATHで使用できることを確認します。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へのアクセス権を設定するには、次の手順を実行します:
docker-credential-ecr-loginがGitLab Runnerの$PATHで使用できることを確認します。次のいずれかのAWS認証情報設定を用意します。GitLab Runnerがその認証情報にアクセスできることを確認します。
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はこの設定ファイルを読み取り、この特定のリポジトリに必要なヘルパーを使用します。
これで、
.gitlab-ci.ymlファイルのimageやservicesに定義した、<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イメージを管理、デプロイ、更新できます。この設定は、時間がかかってエラーが発生しやすい設定や、手動による認証情報の管理を回避するのに役立ちます。
次の内容を含む
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.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