Dockerエクゼキュータ

GitLab RunnerはDockerイメージ上でジョブを実行するためにDocker Executorを使用します。

Docker Executorを使うと以下のことができます:

  • ジョブごとに同じビルド環境を維持。
  • CIサーバーでジョブを実行しなくても、同じイメージを使ってローカルでコマンドをテストできます。

Docker ExecutorはDocker Engineを使用して、各ジョブを分離された個別のコンテナで実行します。Docker Engineに接続するために、Executorは以下を使用します:

Docker Executorのワークフロー

Docker Executorは、準備、プレジョブ、ポストジョブのステップを実行するツールを含むAlpine Linuxベースの特別なDockerイメージを使用します。特別なDockerイメージの定義を見るには、GitLab Runnerリポジトリを参照してください。

Docker Executorはジョブをいくつかのステップに分割します:

  1. 準備サービスの作成と起動。
  2. プレジョブ:クローンを作成し、キャッシュを復元し、前のステージからアーティファクトをダウンロードします。特別なDockerイメージ上で実行します。
  3. ジョブ:Runner用に設定したDockerイメージでビルドを実行します。
  4. ポストジョブ:キャッシュを作成し、アーティファクトをGitLabにアップロードします。特別なDockerイメージ上で実行します。

サポートされる設定

Docker Executorは以下の設定をサポートしています。

既知のイシューとWindows設定の追加要件については、Windowsコンテナを使用するを参照してください。

Runnerは以下にインストールされます:Executor は次のとおりです:コンテナは実行中です:
Windowsdocker-windowsWindows
WindowsdockerLinux
LinuxdockerLinux

これらの設定はサポートされていません

Runnerは以下にインストールされます:Executor は次のとおりです:コンテナは実行中です:
Linuxdocker-windowsLinux
LinuxdockerWindows
Linuxdocker-windowsWindows
WindowsdockerWindows
Windowsdocker-windowsLinux
note
GitLab RunnerはDocker Engine APIv1.25を使ってDocker Engineと通信します。これは、Linuxサーバー上でサポートされるDockerの最小バージョンは 1.13.0Windows ServerではWindows Serverバージョンを識別するためにもっと新しいバージョンである必要があることを意味します。

Dockerエクゼキュータを使う

Dockerエクゼキュータを使用するには、config.toml でDockerをエクゼキュータとして定義します。

以下のサンプルでは、Dockerをエクゼキュータとして定義し、設定例を示しています。これらの値の詳細については、高度な設定を参照してください。

concurrent = 4

[[runners]]
name = "myRunner"
url = "https://gitlab.com/ci"
token = "......"
executor = "docker"
[runners.docker]
  tls_verify = true
  image = "my.registry.tld:5000/alpine:latest"
  privileged = false
  disable_entrypoint_overwrite = false
  oom_kill_disable = false
  disable_cache = false
  volumes = [
    "/cache",
  ]
  shm_size = 0
  allowed_pull_policies = ["always", "if-not-present"]
  allowed_images = ["my.registry.tld:5000/*:*"]
  allowed_services = ["my.registry.tld:5000/*:*"]
  [runners.docker.volume_driver_ops]
    "size" = "50G"

イメージとサービスの設定

前提条件:

  • ジョブが実行されるイメージには、オペレーティングシステムPATH で動作するシェルが必要です。サポートされているシェルは以下の通りです:
    • Linux の場合:
    • Windows 用:

Dockerエクゼキュータを設定するには、.gitlab-ci.ymlconfig.tomlでDockerイメージとサービスを定義します。

以下のキーワードを使用してください:

  • image:Runnerがジョブを実行するために使用するDockerイメージの名前。
    • ローカルのDocker Engineのイメージ、またはDocker Hubの任意のイメージを入力してください。詳細はDockerのドキュメントを参照してください。
    • イメージのバージョンを定義するには、コロン (:) を使用してタグを追加します。タグを指定しない場合、Dockerはlatest をバージョンとして使用します。
  • services:別のコンテナを作成し、image にリンクする追加イメージ。 サービスの種類については、「サービス」を参照してください。

でイメージとサービスを定義します。.gitlab-ci.yml

Runnerがすべてのジョブで使用するイメージと、ビルド時に使用するサービスのリストを定義します。

使用例:

image: ruby:2.7

services:
  - postgres:9.3

before_script:
  - bundle install

test:
  script:
  - bundle exec rake spec

ジョブごとに異なる画像とサービスを定義する場合:

before_script:
  - bundle install

test:2.6:
  image: ruby:2.6
  services:
  - postgres:9.3
  script:
  - bundle exec rake spec

test:2.7:
  image: ruby:2.7
  services:
  - postgres:9.4
  script:
  - bundle exec rake spec

.gitlab-ci.ymlimage を定義しない場合、ランナーはconfig.tomlで定義されたimage を使用します。

画像とサービスはconfig.toml

ランナーによって実行されるすべてのジョブにイメージとサービスを追加するには、config.toml[runners.docker] を更新します。.gitlab-ci.ymlimage を定義しない場合、ランナーはconfig.tomlで定義されたイメージを使用します。

使用例:

[runners.docker]
  image = "ruby:2.7"

[[runners.docker.services]]
  name = "mysql:latest"
  alias = "db"

[[runners.docker.services]]
  name = "redis:latest"
  alias = "cache"

この例では、テーブルの配列構文を使用します。

非公開レジストリからのイメージの定義

前提条件:

非公開レジストリからイメージを定義するには、.gitlab-ci.yml にレジストリ名とイメージを指定します。

使用例:

image: my.registry.tld:5000/namepace/image:tag

この例では、GitLab Runner はレジストリmy.registry.tld:5000 からイメージnamespace/image:tag を検索します。

ネットワークの設定

CI/CDジョブにサービスを接続するには、ネットワークを設定する必要があります。

ネットワークを設定するには、以下のどちらかを行います:

  • 推奨ジョブごとにネットワークを作成するようにRunnerを設定します。
  • コンテナリンクを定義します。コンテナリンクはDockerのレガシー機能です。

ジョブごとにネットワークを作成

ジョブごとにネットワークを作成するようにRunnerを設定することができます。

このネットワークモードを有効にすると、Runnerはジョブごとにユーザー定義のDockerブリッジネットワークを作成して使用します。Docker環境変数はコンテナ間で共有されません。ユーザー定義のブリッジネットワークの詳細については、Dockerのドキュメントを参照してください。

このネットワーキングモードを使用するには、config.toml の機能フラグまたは環境変数のいずれかでFF_NETWORK_PER_BUILD を有効にします。

network_mode を設定しないでください。

使用例:

[[runners]]
  (...)
  executor = "docker"
  environment = ["FF_NETWORK_PER_BUILD = 1"]

または:

[[runners]]
  (...)
  executor = "docker"
  [runners.feature_flags]
    FF_NETWORK_PER_BUILD = true

デフォルトのDockerアドレスプールを設定するには、dockerddefault-address-pool 。 CIDR範囲が既にネットワークで使用されている場合、Dockerネットワークは他のDockerネットワークを含むホスト上の他のネットワークと衝突する可能性があります。

この機能は、DockerデーモンがIPv6を有効にして設定されている場合にのみ機能します。IPv6サポートを有効にするには、Docker設定でenable_ipv6true に設定します。詳しくはDockerのドキュメントをご覧ください。

Runnerはジョブコンテナを解決するためにbuild エイリアスを使用します。

ランナーが各ジョブのネットワークを作成する方法

ジョブが開始されると、Runnerは以下を行います:

  1. Dockerコマンドに似たブリッジネットワークを作成しますdocker network create <network>.
  2. サービスとコンテナをブリッジネットワークに接続します。
  3. ジョブの終了時にネットワークを削除します。

ジョブを実行するコンテナとサービスを実行するコンテナは、互いのホスト名とエイリアスを解決します。この機能はDockerによって提供されます。

DockerのレガシーコンテナリンクとデフォルトのDockerbridge を使用してジョブコンテナとサービスをリンクするネットワークモードを設定できます。このネットワークモードは、FF_NETWORK_PER_BUILD が有効になっていない場合のデフォルトです。

ネットワークを設定するには、config.toml ファイルでネットワークモードを指定します:

  • bridge:ブリッジネットワークを使用します。デフォルト。
  • host:コンテナ内のホストのネットワークスタックを使用します。
  • none:ネットワークなし。推奨しません。

使用例:

[[runners]]
  (...)
  executor = "docker"
[runners.docker]
  network_mode = "bridge"

例:network_mode に他の値を指定した場合、既存のDockerネットワーク名として扱われ、ビルドコンテナが接続します。

名前解決中、Dockerはコンテナ内の/etc/hosts ファイルをサービスコンテナのホスト名とエイリアスで更新します。ただし、サービスコンテナはコンテナ名を解決できません。コンテナ名を解決するには、ジョブごとにネットワークを作成する必要があります。

リンクされたコンテナは環境変数を共有します。

Dockerイメージとサービスの制限

Dockerイメージとサービスを制限するには、allowed_imagesallowed_services パラメータにワイルドカードパターンを指定します。

例えば、非公開Dockerレジストリからのイメージのみを許可する場合などです:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    allowed_images = ["my.registry.tld:5000/*:*"]
    allowed_services = ["my.registry.tld:5000/*:*"]

非公開 Docker レジストリからのイメージのリストに制限するには、次のようにします:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    allowed_images = ["my.registry.tld:5000/ruby:*", "my.registry.tld:5000/node:*"]
    allowed_services = ["postgres:9.4", "postgres:latest"]

アクセスサービスのホスト名

サービスのホスト名にアクセスするには、.gitlab-ci.ymlservices にサービスを追加します。

例えば、アプリケーションとのAPIインテグレーションをテストするためにWordpressインスタンスを使用するには、サービスイメージとしてtutum/wordpressを使用します:

services:
- tutum/wordpress:latest

ジョブが実行されると、tutum/wordpress サービスが開始します。ジョブが実行されると、tutum__wordpress サービスが開始します。ビルドコンテナから とtutum-wordpress というホスト名でアクセスできます。

指定されたサービスエイリアスに加えて、Runnerはサービスコンテナのエイリアスとしてサービスイメージの名前を割り当てます。これらのエイリアスのいずれかを使用できます。

Runnerは以下のルールを使用して、イメージ名に基づいてエイリアスを作成します:

  • : 以降はすべて取り除かれます。
  • 最初のエイリアスでは、スラッシュ (/) はダブルアンダースコア (__) に置き換えられます。
  • 2つ目のエイリアスの場合、スラッシュ (/) はシングルダッシュ (-) に置き換えられます。

非公開サービスイメージを使用する場合、Runnerは指定されたポートを取り除いてルールを適用します。サービスregistry.gitlab-wp.com:4999/tutum/wordpress は、ホスト名registry.gitlab-wp.com__tutum__wordpress およびregistry.gitlab-wp.com-tutum-wordpress になります。

サービスの設定

データベース名を変更したり、アカウント名を設定するには、サービスの環境変数を定義します。

Runnerが変数を渡す場合:

  • 変数はすべてのコンテナに渡されます。ランナーは特定のコンテナに変数を渡すことはできません。
  • セキュリティ変数はビルド・コンテナに渡されます。

設定変数の詳細については、対応するDocker Hubページで提供されている各イメージのドキュメントを参照してください。

ディレクトリをRAMにマウント

tmpfs オプションを使用すると、ディレクトリを RAM にマウントできます。データベースのようにI/O関連の作業が多い場合、テストに要する時間が短縮されます。

Runner設定でtmpfsservices_tmpfs オプションを使用すると、複数のパスを指定でき、それぞれにオプションを指定できます。詳細はDockerのドキュメントを参照してください。

たとえば、公式MySQLコンテナのデータディレクトリをRAMにマウントするには、config.toml

[runners.docker]
  # For the main container
  [runners.docker.tmpfs]
      "/var/lib/mysql" = "rw,noexec"

  # For services
  [runners.docker.services_tmpfs]
      "/var/lib/mysql" = "rw,noexec"

サービス内のディレクトリの構築

GitLab Runnerはすべての共有サービスに/builds ディレクトリをマウントします。

サービスの使い分けについては

GitLab Runner がサービスのヘルスチェックを行う方法

GitLab 16.0で複数のポートチェックを導入しました。

サービス開始後、GitLab Runnerはサービスの応答を待ちます。Docker Executorはサービスコンテナで公開されているサービスポートへのTCP接続を開こうとします。

  • GitLab 15.11以前では、最初に公開されたポートだけがチェックされます。
  • GitLab 16.0以降では、最初に公開された20のポートがチェックされます。

HEALTHCHECK_TCP_PORT サービス変数を使って特定のポートのヘルスチェックを行うことができます:

job:
  services:
    - name: mongo
      variables:
        HEALTHCHECK_TCP_PORT: "27017"

この実装を確認するには、health checkGoコマンドを使用してください。

Dockerドライバのオペレーション指定

ビルド用のボリュームを作成する際に、Dockerボリュームドライバに提供する引数を指定します。例えば、他のドライバ固有のオプションに加えて、これらの引数を使用して各ビルドの実行領域を制限することができます。以下の例では、config.toml 、各ビルドが消費できる上限を50GBに設定しています。

[runners.docker]
  [runners.docker.volume_driver_ops]
      "size" = "50G"

コンテナビルドとキャッシュ用のディレクトリの設定

コンテナ内のデータの保存場所を定義するには、config.toml[[runners]] セクションで/builds/cache ディレクトリを設定します。

/cache ストレージ・パスを変更した場合、そのパスを永続としてマークするには、config.toml[runners.docker] セクションの下にあるvolumes = ["/my/cache/"] で定義する必要があります。

デフォルトでは、Docker Executorはビルドとキャッシュを以下のディレクトリに保存します:

  • ビルド/builds/<namespace>/<project-name>
  • コンテナ内部/cache にキャッシュ。

Dockerキャッシュのクリア

GitLab Runner 13.9で導入された、作成されたすべてのRunnerリソースをクリーンアップします。

clear-docker-cache を使用して、Runner が作成した未使用のコンテナやボリュームを削除します。

オプションのリストについては、help オプションを付けてスクリプトを実行してください:

clear-docker-cache help

デフォルトのオプションはprune-volumes で、未使用のコンテナ(ダングリングおよび参照なし)とボリュームをすべて削除します。

キャッシュ・ストレージを効率的に管理するには

  • cronclear-docker-cache を定期的(たとえば週に1回)に実行します。
  • ディスク領域を取り戻す間、パフォーマンスのために最近のコンテナをいくつかキャッシュに保持します。

Dockerビルドイメージのクリア

DockerイメージはGitLab Runnerによってタグ付けされていないため、clear-docker-cache スクリプトはDockerイメージを削除しません。

Docker ビルドイメージを削除するには:

  1. 再生可能なディスク領域を確認します:

    clear-docker-cache space
       
    Show docker disk usage
    ----------------------
       
    TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
    Images          14        9         1.306GB   545.8MB (41%)
    Containers      19        18        115kB     0B (0%)
    Local Volumes   0         0         0B        0B
    Build Cache     0         0         0B        0B
    
  2. 未使用のコンテナ、ネットワーク、イメージ(ダングリングおよび未参照)、タグなしボリュームをすべて削除するには、docker system prune を実行します。

永続ストレージ

Dockerエクゼキュータはコンテナを実行する際に永続ストレージを提供します。volumes = で定義されたすべてのディレクトリは、ビルド間で永続的です。

volumes ディレクティブは以下のタイプのストレージをサポートしています:

  • ダイナミック・ストレージには、<path>.その <path>プロジェクトの同じ同時実行ジョブの後続の実行間で永続化されます。データはカスタム・キャッシュ・ボリュームにアタッチされます:runner-<short-token>-project-<id>-concurrent-<concurrency-id>-cache-<md5-of-path>.
  • ホスト・バウンド・ストレージの場合は、<host-path>:<path>[:<mode>] を使用します。<path> は、ホスト・システム上の<host-path> にバインドされます。オプションの<mode> は、このストレージが読み取り専用または読み取り/書き込み専用であることを指定します (デフォルト)。

ビルド用の永続ストレージ

/builds ディレクトリをホストバウンドのストレージにした場合、ビルドは に保存されます:/builds/<short-token>/<concurrent-id>/<namespace>/<project-name>に保存されます:

  • <short-token> はRunnerのトークン(最初の8文字)の短縮バージョンです。
  • <concurrent-id> はプロジェクト内で特定のRunnerのローカルジョブIDを識別するユニークな番号です。

IPCモード

DockerエクゼキュータはコンテナのIPC名前空間を他のロケーションと共有することをサポートしています。これはdocker run --ipc フラグに対応します。DockerドキュメントのIPC設定の詳細

特権モード

Docker Executorは、ビルドコンテナの微調整を可能にする多くのオプションをサポートしています。これらのオプションの1つにprivileged mode があります。

特権モードでDocker-in-Dockerを使用します。

設定されたprivileged フラグはビルドコンテナとすべてのサービスに渡されるため、Docker-in-Docker アプローチを簡単に使用できます。

まず、Runner (config.toml) をprivileged モードで実行するように設定します:

[[runners]]
  executor = "docker"
  [runners.docker]
    privileged = true

次に、ビルド・スクリプト(.gitlab-ci.yml)でDocker-in-Dockerコンテナを使用するようにします:

image: docker:git
services:
- docker:dind

build:
  script:
  - docker build -t my-image .
  - docker push my-image
caution
特権モードで実行するコンテナにはセキュリティリスクがあります。コンテナを特権モードで実行すると、コンテナのセキュリティ機構が無効になり、ホストが特権の昇格にさらされます。特権モードでコンテナを実行すると、コンテナの脱走につながる可能性があります。詳細については、実行時特権とLinuxの機能に関するDockerのドキュメントを参照してください。

特権モードを制限したルートレスDocker-in-Dockerの使用

このバージョンでは、Docker-in-Dockerのルートレスイメージのみが特権モードでサービスとして実行できます。

services_privileged およびallowed_privileged_services 設定パラメータは、特権モードでの実行を許可するコンテナを制限します。

制限付き特権モードでルートレスDocker-in-Dockerを使用するには:

  1. config.toml で、services_privilegedallowed_privileged_services を使用するように Runner を設定します:

    [[runners]]
      executor = "docker"
      [runners.docker]
        services_privileged = true
        allowed_privileged_services = ["docker.io/library/docker:*-dind-rootless", "docker.io/library/docker:dind-rootless", "docker:*-dind-rootless", "docker:dind-rootless"]
    
  2. .gitlab-ci.yml で、Docker-in-Dockerルートレス・コンテナを使用するようにビルド・スクリプトを編集します:

    image: docker:git
    services:
    - docker:dind-rootless
       
    build:
      script:
      - docker build -t my-image .
      - docker push my-image
    

allowed_privileged_services でリストしたDocker-in-Dockerルートレスイメージのみが特権モードで実行できます。ジョブやサービス用の他のコンテナはすべて非特権モードで実行されます。

これらは非ルートとして実行されるため、Docker-in-DockerルートレスやBuildkitルートレスのような特権モードイメージと併用しても_ほぼ安全_です。

セキュリティ問題の詳細については、Docker Executorのセキュリティリスクを参照してください。

Docker ENTRYPOINTの設定

デフォルトでは、Docker ExecutorはDockerイメージ](https://docs.docker.com/engine/reference/run/#entrypoint-default-command-to-execute-at-runtime) の[ENTRYPOINT を上書きせず、ジョブスクリプトを実行するコンテナを起動するためにsh またはbashCOMMAND として渡します。

ジョブが確実に実行できるようにするには、そのDockerイメージが必要です:

  • sh またはbash
  • 引数としてsh/bash を渡されたときにシェルを起動するENTRYPOINT を定義します。

Docker Executorは、以下のコマンドと同等のコマンドでジョブのコンテナを実行します:

docker run <image> sh -c "echo 'It works!'" # or bash

Dockerイメージがこのメカニズムをサポートしていない場合、プロジェクト設定で以下のようにイメージのENTRYPOINTを上書きすることができます:

# Equivalent of
# docker run --entrypoint "" <image> sh -c "echo 'It works!'"
image:
  name: my-image
  entrypoint: [""]

詳細については、イメージのエントリポイントを上書きする、およびDockerでCMDとENTRYPOINTがどのように相互作用するかを参照してください。

ENTRYPOINTとしてのジョブスクリプト

ENTRYPOINT を使用して、カスタム環境またはセキュリティモードでビルドスクリプトを実行するDockerイメージを作成することができます。

例えば、ENTRYPOINT 、ビルドスクリプトを実行しないDockerイメージを作成することができます。代わりに、Dockerイメージは定義済みのコマンドセットを実行して、ディレクトリからDockerイメージをビルドします。特権モードでビルドコンテナを実行し、Runnerのビルド環境をセキュリティで保護します。

  1. 新しいDockerfileを作成します:

    FROM docker:dind
    ADD / /entrypoint.sh
    ENTRYPOINT ["/bin/sh", "/entrypoint.sh"]
    
  2. ENTRYPOINT として使用する Bash スクリプト (entrypoint.sh) を作成します:

    #!/bin/sh
       
    dind docker daemon
        --host=unix:///var/run/docker.sock \
        --host=tcp://0.0.0.0:2375 \
        --storage-driver=vf &
       
    docker build -t "$BUILD_IMAGE" .
    docker push "$BUILD_IMAGE"
    
  3. イメージをDockerレジストリにプッシュします。

  4. privileged モードでDocker Executorを実行します。config.toml で定義します:

    [[runners]]
      executor = "docker"
      [runners.docker]
        privileged = true
    
  5. プロジェクト内部では、以下の.gitlab-ci.yml

    variables:
      BUILD_IMAGE: my.image
    build:
      image: my/docker-build:image
      script:
      - Dummy Script
    

Podmanを使ってDockerコマンドを実行します。

GitLab 15.3 で導入されました

GitLab RunnerがLinuxにインストールされている場合、ジョブはPodmanを使ってDocker ExecutorのコンテナランタイムとしてDockerを置き換えることができます。

前提条件:

  1. Linuxホストで、GitLab Runnerをインストールします。システムのパッケージマネージャを使ってGitLab Runnerをインストールした場合は、自動的にgitlab-runner ユーザーを作成します。
  2. GitLab Runnerを実行するユーザーとしてサインインします。pam_systemd を経由しない方法で行う必要があります。正しいユーザーで SSH を使うことができます。これで、このユーザーとしてsystemctl を実行できるようになります。
  3. あなたのシステムがルートレスPodmanセットアップの前提条件を満たしていることを確認してください。具体的には、ユーザーが/etc/subuid/etc/subgid](https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md#etcsubuid-and-etcsubgid-configuration)に[正しいエントリーを持つことを確認してください。
  4. Linuxホストで、Podmanをインストールします。
  5. Podmanソケットを有効にして起動します:

    systemctl --user --now enable podman.socket
    
  6. Podmanソケットがリッスンしていることを確認します:

    systemctl status --user podman.socket
    
  7. PodmanのAPIにアクセスしているListen キーのソケット文字列をコピーします。
  8. GitLab Runnerユーザーがログアウトした後も、Podmanソケットが利用可能であることを確認してください:

    sudo loginctl enable-linger gitlab-runner
    
  9. GitLab Runnerconfig.toml ファイルを編集し、[[runners.docker]] セクションの host エントリーにソケットの値を追加します。例えば

    [[runners]]
      name = "podman-test-runner-2022-06-07"
      url = "https://gitlab.com"
      token = "x-XxXXXXX-xxXxXxxxxx"
      executor = "docker"
      [runners.docker]
        host = "unix:///run/user/1012/podman/podman.sock"
        tls_verify = false
        image = "quay.io/podman/stable"
        privileged = true
    

Podman を使って Dockerfile からコンテナイメージをビルドします。

次の例では、Podman を使ってコンテナイメージをビルドし、そのイメージを GitLab Container レジストリにプッシュします。

Runnerconfig.toml のデフォルトのコンテナイメージはquay.io/podman/stable に設定されており、CIジョブはそのイメージを使用して含まれるコマンドを実行します。

variables:
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG

before_script:
  - podman login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY

oci-container-build:
  stage: build
  script:
    - podman build -t $IMAGE_TAG .
    - podman push $IMAGE_TAG
  when: manual

DockerfileからコンテナイメージをビルドするにはBuildahを使用します。

次の例では、Buildah を使ってコンテナイメージをビルドし、そのイメージを GitLab Container レジストリにプッシュしています。

image: quay.io/buildah/stable

variables:
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG

before_script:
  - buildah login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY

oci-container-build:
  stage: build
  script:
    - buildah bud -t $IMAGE_TAG .
    - buildah push $IMAGE_TAG
  when: manual

ジョブを実行するユーザーを指定します。

デフォルトでは、Runnerはコンテナ内のroot ユーザーとしてジョブを実行します。ジョブを実行するユーザーを root 以外に指定するには、Docker イメージの Dockerfile でUSER ディレクティブを使用します。

FROM amazonlinux
RUN ["yum", "install", "-y", "nginx"]
RUN ["useradd", "www"]
USER "www"
CMD ["/bin/bash"]

そのDockerイメージを使用してジョブを実行すると、指定したユーザーとして実行されます:

build:
  image: my/docker-build:image
  script:
  - whoami   # www

Runnerがイメージをプルする方法の設定

config.toml でプルポリシーを設定し、RunnerがレジストリからDockerイメージをプルする方法を定義します。単一のポリシー、ポリシーのリスト、または特定のプルポリシーを許可するように設定できます。

pull_policy には次の値を使用します:

  • always:ローカル・イメージが存在する場合でもイメージを引き出します。デフォルト
  • if-not-present:ローカルに画像が存在しない場合にのみ画像を取り出します。
  • never:ローカル・イメージのみを使用します。
[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    pull_policy = "always" # available: always, if-not-present, never

always プルポリシーの設定

デフォルトでオンになっているalways オプションは、コンテナを作成する前に常にプルを開始します。このオプションは、イメージが最新であることを確認し、ローカルイメージが存在する場合でも古いイメージを使用することを防ぎます。

このプルポリシーは、以下の場合に使用します:

  • ランナーは常に最新の画像をプルする必要があります。
  • Runnerは公開されており、オートスケールまたはGitLabインスタンス内の共有Runnerとして設定できます。

Runner がローカルに保存されたイメージを使用する必要がある場合は、このポリシーを使用しないでください。

config.tomlpull policy としてalways を設定します:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    pull_policy = "always"

if-not-present プルポリシーの設定

プルポリシーをif-not-present に設定すると、Runnerはまずローカルのイメージが存在するかどうかを確認します。ローカルに画像がない場合、Runnerはレジストリから画像をプルします。

if-not-present ポリシーを使用します:

  • ローカルイメージを使用しますが、ローカルイメージが存在しない場合はプルイメージも使用します。
  • 重いイメージやめったに更新されないイメージについて、Runnerがイメージレイヤの違いを分析する時間を短縮します。この場合、ローカルのDocker Engineストアから定期的に手動でイメージを削除して、イメージの更新を強制する必要があります。

このポリシーは使用しないでください:

  • ランナーを使用する異なるユーザーが非公開イメージにアクセスできる共有ランナーの場合。セキュリティ問題の詳細については、if-not-present pullポリシーによる非公開Dockerイメージの使用を参照してください。
  • ジョブが頻繁に更新され、最新のイメージバージョンで実行する必要がある場合。その結果、ローカルイメージを頻繁に削除する価値よりも、ネットワーク負荷の軽減が上回る可能性があります。

config.tomlif-not-present ポリシーを設定します:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    pull_policy = "if-not-present"

never プルポリシーの設定

前提条件:

  • ローカルイメージには、インストールされたDocker Engineと使用済みイメージのローカルコピーが含まれている必要があります。

プルポリシーをnever に設定すると、イメージのプルは無効になります。ユーザーは、Runnerが実行されるDockerホスト上で手動でプルされたイメージのみを使用できます。

never pullポリシーを使用してください:

  • Runnerユーザーが使用する画像をコントロールするため。
  • どのレジストリでも公開されていない特定の画像のみを使用できるプロジェクト専用の非公開ランナー用。

自動スケーリングされたDocker Executorにはnever プルポリシーを使用しないでください。never pullポリシーは、選択したクラウドプロバイダの事前定義されたクラウドインスタンスイメージを使用する場合にのみ使用できます。

config.tomlnever ポリシーを設定します:

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    pull_policy = "if-not-present"

複数のプルポリシーを設定

GitLab Runner 13.8で導入されました

プルに失敗した場合に実行する複数のプルポリシーをリストアップできます。Runner はプル試行が成功するかリストがなくなるまで、リストされた順番にプルポリシーを処理します。例えば、Runnerがalways プルポリシーを使用し、レジストリが利用できない場合、if-not-present を2つ目のプルポリシーとして追加し、ローカルにキャッシュされたDockerイメージを使用することができます。

このプルポリシーのセキュリティ上の意味については、if-not-presentプルポリシーによる非公開Dockerイメージの使用を参照してください。

複数のプルポリシーを設定するには、config.toml

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    pull_policy = ["always", "if-not-present"]

Dockerプルポリシーの許可

GitLab 15.1で導入されました

.gitlab-ci.yml ファイルで、プルポリシーを指定することができます。このポリシーは、CI/CDジョブがどのようにイメージをフェッチするかを決定します。

.gitlab-ci.yml ファイルで使用できるプルポリシーを制限するには、allowed_pull_policies を使用します。

例えば、alwaysif-not-present のプルポリシーのみを許可するには、config.toml

[[runners]]
  (...)
  executor = "docker"
  [runners.docker]
    (...)
    allowed_pull_policies = ["always", "if-not-present"]
  • allowed_pull_policies を指定しない場合、既定値はpull_policy キーワードの値となります。
  • pull_policy を指定しない場合、既定値はalways です。
  • 既存のpull_policy キーワード に、allowed_pull_policies で指定されていないプル・ポリシーを含めてはなりません。含めると、ジョブはエラーを返します。

画像プルエラーメッセージ

エラーメッセージ説明
Pulling docker image registry.tld/my/image:latest ... ERROR: Build failed: Error: image registry.tld/my/image:latest not foundランナーが画像を見つけられません。always プルポリシーが設定されている場合に表示されます。
Pulling docker image local_image:latest ... ERROR: Build failed: Error: image local_image:latest not foundイメージはローカルでビルドされ、公開またはデフォルトのDockerレジストリに存在しません。always pull ポリシーが設定されている場合に表示されます。
Pulling docker image registry.tld/my/image:latest ... WARNING: Cannot pull the latest version of image registry.tld/my/image:latest : Error: image registry.tld/my/image:latest not found WARNING: Locally found image will be used instead.Runner はイメージをプルする代わりにローカルイメージを使用しました。GitLab Runner 1.8以前のバージョンで、always pullポリシーが設定されている場合に表示されます。
Pulling docker image local_image:latest ... ERROR: Build failed: Error: image local_image:latest not foundイメージがローカルで見つかりません。never pull ポリシーが設定されている場合に表示されます。
WARNING: Failed to pull image with policy "always": Error response from daemon: received unexpected HTTP status: 502 Bad Gateway (docker.go:143:0s) Attempt #2: Trying "if-not-present" pull policy Using locally found image version due to "if-not-present" pull policyRunner はイメージのプルに失敗し、次にリストされているプルポリシーを使用してイメージのプルを試みます。複数のプルポリシーが設定されている場合に表示されます。

失敗したプルの再試行

失敗したイメージのプルを再試行するように Runner を設定するには、config.toml で同じポリシーを複数回指定します。

たとえば、この設定はプルを1回再試行します:

[runners.docker]
  pull_policy = ["always", "always"]

この設定は、個々のプロジェクトの.gitlab-ci.yml ファイルにあるretry ディレクティブ と似ていますが、特にDocker pullが最初に失敗した場合にのみ有効になります。

DockerとDocker-SSHの比較(およびDocker+MachineとDocker-SSH+Machineの比較) (削除)

この機能はGitLab Runner 10.0で非推奨となり、16.0で削除されました。

Windows コンテナを使う

GitLab Runner 11.11で導入されました

DockerエクゼキュータでWindowsコンテナを使うには、制限、サポートされるWindowsのバージョン、Windows Dockerエクゼキュータの設定に関する以下の情報に注意してください。

Nanoserverのサポート

GitLab Runner 13.6で導入されました

Windowsヘルパーイメージに導入されたPowerShell Coreのサポートにより、ヘルパーイメージのnanoserver バリアントを活用できるようになりました。

Windows上のDocker Executorの制限事項

以下はDocker executorでWindowsコンテナを使用する際の制限事項です:

  • Docker自体がサポートしていないため、Docker-in-Dockerはサポートされていません。
  • インタラクティブなウェブ端末はサポートされていません。
  • ホストデバイスのマウントには対応していません。
  • ボリュームディレクトリをマウントする場合、そのディレクトリが存在する必要があります。
  • docker-windows executorはWindows上で動作するGitLab Runnerでのみ実行できます。
  • Windows上のLinuxコンテナはまだ実験的なものなのでサポートされていません。詳しくは関連するイシューをお読みください。
  • Dockerの制限により、宛先パスのドライブ文字がc: でない場合、パスはサポートされません:

    つまり、f:\\cache_dir のような値はサポートされませんが、f: はサポートされます。ただし、宛先パスがc: ドライブ上にある場合は、パスもサポートされます(例:c:\\cache_dir )。

    Dockerデーモンがイメージとコンテナを保存する場所を設定するには、Dockerデーモンのdaemon.json ファイルのdata-root パラメータを更新します。

    詳細については、設定ファイルでDockerを設定するを参照してください。

対応Windowsバージョン

GitLab Runnerは、Windowsのサポートライフサイクルに沿って、以下のバージョンのWindowsのみをサポートしています:

  • Windows Server 2022 LTSC (21H2)
  • Windows Server 2019 LTSC (1809)

Windows Server の将来のバージョンについては、将来のバージョンのサポートポリシーがあります。

Dockerデーモンが実行されているOSバージョンと同じバージョンのコンテナしか実行できません。例えば、以下のWindows Server Core イメージを使用できます:

  • mcr.microsoft.com/windows/servercore:ltsc2022
  • mcr.microsoft.com/windows/servercore:ltsc2022-amd64
  • mcr.microsoft.com/windows/servercore:1809
  • mcr.microsoft.com/windows/servercore:1809-amd64
  • mcr.microsoft.com/windows/servercore:ltsc2019

サポートされるDockerバージョン

GitLab Runnerが動作しているWindows Serverは、最新のバージョンのDockerが動作している必要があります。なぜならGitLab RunnerはDockerを使ってWindows Serverのバージョンを検知するからです。

GitLab Runnerで動作しない既知のバージョンのDockerは、DockerがWindows Serverのバージョンを識別しないため、Docker 17.06 、以下のエラーが発生します:

unsupported Windows Version: Windows Server Datacenter

トラブルシューティングについてはこちらをご覧ください。

Windows Docker Executorの設定

note
--docker-volumes またはDOCKER_VOLUMES 環境変数を渡す際に、ランナーがソースディレクトリとしてc:\\cache で登録される場合、既知の問題があります。

下記はWindowsを実行するシンプルなDocker Executorの設定例です。

[[runners]]
  name = "windows-docker-2019"
  url = "https://gitlab.com/"
  token = "xxxxxxx"
  executor = "docker-windows"
  [runners.docker]
    image = "mcr.microsoft.com/windows/servercore:1809_amd64"
    volumes = ["c:\\cache"]

Docker Executorのその他の設定オプションについては、高度な設定のセクションを参照してください。

サービス

GitLab Runner 12.9以降ではジョブごとにネットワークを有効にすることでサービスを利用することができます。