GitLab CI でビルドする - GitLab CI
GitLab CI はリポジトリ内蔵の CI/CD 機能で、`.gitlab-ci.yml` で定義する。Kaniko や BuildKit の Runner と組み合わせれば DinD なしで安全にコンテナをビルドできる。
概念図
構文
.gitlab-ci.yml実例
Kaniko でビルド。Docker デーモンを持たず、特権も不要。
build:
stage: build
image:
name: gcr.io/kaniko-project/executor:latest
entrypoint: [""]
script:
- /kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}"
--destination "${CI_REGISTRY_IMAGE}:latest"DinD サービスを使う伝統的なパターン。Runner の設定に注意。
build:
stage: build
image: docker:26
services:
- docker:26-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
script:
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
- docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" .
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"GitLab CI の基本構造
GitLab では .gitlab-ci.yml に stages と job を書き、各ジョブがコンテナ内で実行されます。
プッシュ/マージリクエスト/タグなどのイベントでパイプラインが起動し、ステージ順にジョブが並列・直列で進みます。
特徴的なのは、リポジトリごとに専用のコンテナレジストリ($CI_REGISTRY_IMAGE)が用意されていることと、ジョブ環境に CI_ で始まる変数が大量に注入されること。
ビルドして自分のプロジェクトレジストリに push するまでは、ほぼ組み込みの仕組みで賄えます。
DinD・Kaniko・BuildKit の選択
| 方式 | 長所 | 短所 |
|---|---|---|
| DinD(Docker-in-Docker) | 既存の docker build 資産をそのまま使える |
Runner で特権モードが必要。ホストのカーネルを共有するため隔離が弱い |
| Kaniko | 特権不要でコンテナ内から直接ビルド・push できる | キャッシュ周りが Buildx ほど柔軟ではない |
| BuildKit(rootless)+ buildx | キャッシュやマルチアーキが強力 | Runner のセットアップが DinD より少し手間 |
マネージド SaaS の GitLab.com であれば Kaniko が素直で安全、自前 Runner を組む場合は BuildKit の rootless 構成が長期的には扱いやすい、というのが実務上の落としどころです。
組み込み変数とタグ付け
GitLab が注入する代表的な変数は次のとおり。
| 変数 | 値の例 |
|---|---|
$CI_REGISTRY |
registry.gitlab.com |
$CI_REGISTRY_IMAGE |
registry.gitlab.com/acme/web |
$CI_COMMIT_SHA / $CI_COMMIT_SHORT_SHA |
フル/短縮 SHA |
$CI_COMMIT_REF_SLUG |
ブランチ/タグを DNS-safe にしたもの |
$CI_PIPELINE_ID |
パイプライン ID |
典型的なタグ戦略は $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA(不変)+ $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG(ブランチ最新)+ latest(main の最新)です。
ロールバックを考えると、デプロイ時は SHA タグを指定するのが安全です。
Runner の責務と安全性
GitLab Runner にはいくつか executor があり、コンテナビルド用途では docker / kubernetes / shell などを選びます。
DinD を使う場合はプロジェクトの Runner が特権モードで動く必要があり、Runner ホストを共有すると「他プロジェクトからホストを侵害される」リスクが跳ね上がります。
対処の定番は、ビルド系のジョブは専用 Runner(タグ付け)に固定する、Kaniko or rootless BuildKit に寄せて特権モードを外す、機密変数は Protected フラグ付きで特定ブランチのみに渡す、といった組み合わせです。
関連トピック
GitHub Actions- GitHub Actions はリポジトリのイベントに応じてワークフローを実行する CI/CD サービス。`docker/build-push-action` を組み合わせれば、数十行の YAML でビルドとプッシュまで自動化できる。 registry push- ビルドしたイメージはレジストリに push して初めて本番で使える。GHCR・ECR・GAR・Docker Hub など目的地ごとに認証・命名・保管ポリシーが異なる。 buildx cache- BuildKit のキャッシュを CI で再利用すると、ビルド時間を大幅に短縮できる。GitHub Actions の `gha` キャッシュやレジストリ型キャッシュを使い分ける。 