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

CI/CDジョブを分離されたDockerコンテナで実行することができます。

ローカルマシンでDockerを実行すれば、専用のCI/CDサーバでテストするのではなく、コンテナ内でテストを実行できます。

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

  1. 全てのジョブがDockerコンテナで実行されるようにRunnerを登録します。登録時にDocker Executorを選択します。
  2. ジョブを実行するコンテナを指定します。.gitlab-ci.yml ファイルでイメージを指定します。
  3. オプション。MySQL のような他のサービスをコンテナで実行します。.gitlab-ci.yml ファイルでサービスを指定します。

Docker Executorを使用する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

次に、このテンプレートを使用してランナーを登録します:

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

登録されたランナーはruby:2.6 Dockerイメージを使用し、postgres:latestmysql:latest の2つのサービスを実行します。

imageとは

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

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

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

.gitlab-ci.yml ファイルでimage を定義します。

すべてのジョブで使用するイメージと、実行時に使用するサービスのリストを定義できます:

default:
  image: ruby:2.6
  services:
    - postgres:11.7
  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設定オプション

GitLabとGitLab Runner 9.4で導入されました。

imageservices のエントリには文字列やマップを使うことができます:

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

例えば、以下の2つの定義は等しくなります。

  • imageservices の文字列:

     image: "registry.example.com/my/image:latest"
       
     services:
       - postgresql:14.3
       - redis:latest
    
  • image およびservices のマップ。image:name は必須です:

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

スクリプトの実行場所

CIジョブがDockerコンテナで実行される場合、before_script,script,after_script のコマンドは/builds/<project-path>/ ディレクトリで実行されます。あなたのイメージでは、異なるデフォルトがWORKDIR 定義 WORKDIRされているかもしれません。ジョブの実行中にコンテナ内で参照できるようにWORKDIRWORKDIRWORKDIR を環境変数として保存してください。

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

GitLabとGitLab Runnerの9.4で導入されました。詳細は拡張設定オプションを参照してください。

利用可能なエントリーポイントのオーバーライド方法を説明する前に、Runner がどのように起動するかを説明しましょう。CI/CDジョブで使うコンテナにはDockerイメージを使います:

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

Dockerイメージのエントリーポイントをオーバーライドするには、.gitlab-ci.yml ファイルで空のentrypoint を定義します。そうすれば、Runnerは無駄なシェルレイヤーを起動しません。ただし、これはすべてのDockerバージョンで機能するわけではありません。

  • Docker 17.06以降では、entrypoint に空の値を設定できます。
  • Docker 17.03およびそれ以前のバージョンでは、entrypoint/bin/sh -c/bin/bash -c 、またはイメージで利用可能な同等のShellに設定できます。

image:entrypoint の構文はDockerfileENTRYPOINT と似ています。

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

拡張Docker設定オプションでは、代わりに:

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

.gitlab-ci.yml ファイルでentrypoint を定義することができます。

Docker 17.06以降の場合:

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

Docker 17.03以前の場合:

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

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

[runners.docker]セクションを参照します:

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

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

非公開コンテナレジストリからのイメージへのアクセス

GitLab Runnerプロセスで、プライベートコンテナのレジストリにアクセスできます。

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

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

要件と制限

  • GitLab Runner 13.1以降のKubernetes executorで利用可能。
  • クレデンシャルストアと クレデンシャルヘルパーは、GitLab Runner$PATH にバイナリを追加する必要があり、そのためにはアクセスが必要です。そのため、これらの機能は共有ランナーや、ユーザーがランナーがインストールされている環境にアクセスできないその他のランナーでは利用できません。

静的に定義された認証情報の使用

非公開レジストリにアクセスするには、2つの方法があります。どちらも CI/CD 変数DOCKER_AUTH_CONFIG に適切な認証情報を設定する必要があります。

  1. ジョブごと:非公開レジストリにアクセスするように1つのジョブを設定するには、CI/CD変数としてDOCKER_AUTH_CONFIG を追加します。
  2. ランナー単位:すべてのジョブが非公開レジストリにアクセスできるようにランナーを設定するには、ランナーの設定にDOCKER_AUTH_CONFIG を環境変数として追加します。

それぞれの例は以下を参照してください。

DOCKER_AUTH_CONFIG データの決定

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

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

キー
レジストリregistry.example.com:5000
ユーザー名my_username
パスワード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 を読み取ることができないので、必要なbase64エンコード版の${username}:${password} を用意し、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. Docker設定ファイルの内容を値としてCI/CD変数 DOCKER_AUTH_CONFIG

    {
        "auths": {
            "registry.example.com:5000": {
                "auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ="
            }
        }
    }
    
  2. これで、image またはservices で定義したregistry.example.com:5000 の非公開イメージを.gitlab-ci.yml ファイルで使用できるようになります:

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

    上の例では、GitLab Runner はregistry.example.com:5000 からnamespace/image:tag のイメージを探します。

上記のように、"auths" ハッシュにさらにレジストリを追加して、必要な数だけレジストリの設定を追加できます。

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

ランナーの設定

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

これは、Runner上のどのジョブも、プロジェクトにまたがっても、同じ権限でレジストリにアクセスできることを意味します。レジストリへのアクセスを制御する必要がある場合は、ランナーへのアクセスを確実に制御する必要があります。

ランナーにDOCKER_AUTH_CONFIG

  1. ランナーの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で認証情報ストアを使うには、2つの方法があります。

    • Docker設定ファイルの内容を値としてCI/CD変数 DOCKER_AUTH_CONFIG

         {
           "credsStore": "osxkeychain"
         }
      
    • または、セルフマネージドランナーを実行している場合は、上記のJSONを${GITLAB_RUNNER_HOME}/.docker/config.json に追加します。 GitLab Runnerはこの設定ファイルを読み込み、特定のリポジトリに必要なヘルパーを使用します。

credsStoreすべてのレジストリにアクセスするために使われます。非公開レジストリからのイメージとDocker Hubからの公開イメージの両方を使用すると、Docker Hubからのプルに失敗します。Dockerデーモンはすべてのレジストリで同じ認証情報を使用しようとします。

クレデンシャルヘルパーの使用

GitLab Runner 12.0で導入されました。

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

<aws_account_id>.dkr.ecr.<region>.amazonaws.comのアクセスを設定するには、以下の手順に従います:

  1. GitLab Runner$PATHdocker-credential-ecr-login が利用可能であることを確認します。
  2. 以下のAWSの認証情報を持つ場合、GitLab Runnerがこの認証情報でAWSへアクセスできることを確認してください。
  3. GitLab Runnerで認証情報ストアを使うには、2つの方法があります。

    • Docker設定ファイルの内容を値としてCI/CD変数 DOCKER_AUTH_CONFIG

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

      これはDockerが特定のレジストリでCredential Helperを使用するように設定します。

      代わりに、すべてのAmazon Elastic Container Registry(ECR) レジストリでCredential Helperを使用するようにDockerを設定できます:

       {
         "credsStore": "ecr-login"
       }
      
    • または、セルフマネージドランナーを実行している場合は、前述のJSONを${GITLAB_RUNNER_HOME}/.docker/config.json に追加します。 GitLab Runnerはこの設定ファイルを読み込み、この特定のリポジトリに必要なヘルパーを使用します。

  4. image および/またはservices で定義された<aws_account_id>.dkr.ecr.<region>.amazonaws.com の非公開イメージを.gitlab-ci.yml ファイルで使用できます:

    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   (...)