Docker-in-Docker(DinD)はコンテナ内で Docker デーモンを実行します。イメージをビルドまたはテストする使い捨て CI ジョブには有用な場合がありますが、
特権カーネルアクセス、入れ子になったストレージ、キャッシュの複雑さが加わります。docker を呼び出すすべてのジョブで既定の選択にすべきではありません。
適切なビルドモデルの選択 #
一般的なモデルは 3 つあります。
- DinD: 専用デーモンがジョブのネットワーク名前空間で動作します。ホストデーモンから分離できますが、通常は特権モードが必要です。
- Docker-outside-of-Docker: ジョブがホストの Docker ソケットをマウントします。単純で高速ですが、ソケットを使えるプロセスはホストの Docker デーモンを制御できます。
- デーモンレスビルダー: BuildKit、Kaniko、Buildah、またはマネージドビルダーが、汎用ホストデーモンを公開せずに OCI イメージを作成します。
ビルドを支えられる中で最小権限の選択肢を使います。rootless BuildKit またはリモート BuildKit ビルダーなら、 CI ジョブにランナーの Docker ソケットへのアクセスを与えず、キャッシュ効率を維持できます。
TLS 付き DinD サービスの実行 #
公式の docker:dind イメージは dockerd を起動し、独立した Docker CLI コンテナまたは CI ジョブと組み合わせて使うことを想定しています。
デーモンを隔離ネットワークに置き、TCP リスナーには TLS を使います。
docker network create ci-build
docker volume create dind-certs
docker run -d --name dind --privileged --network ci-build \
-e DOCKER_TLS_CERTDIR=/certs \
-v dind-certs:/certs/client \
docker:27-dind
docker run --rm --network ci-build \
-e DOCKER_HOST=tcp://dind:2376 \
-e DOCKER_TLS_VERIFY=1 \
-e DOCKER_CERT_PATH=/certs/client \
-v dind-certs:/certs/client:ro \
docker:27-cli version--privileged フラグはサービスにホストカーネルの広範な機能を与えます。隔離された使い捨てランナーでのみ実行してください。
認証されていない dockerd の TCP ポートを公開してはいけません。到達できる人は特権コンテナを作成でき、通常はホストを制御できます。
キャッシュとクリーンアップの扱い #
DinD のイメージとレイヤーのキャッシュはサービスコンテナの /var/lib/docker にあります。
永続キャッシュボリュームは繰り返しビルドを高速化しますが、信頼できるプロジェクトまたはテナントに限定してください。
イメージレイヤーにはソースコードやビルドシークレットが含まれる可能性があります。共有 CI 基盤ではレジストリ対応の BuildKit キャッシュを優先します。
不変のコミット識別子に基づく一意のタグを使い、テスト合格後だけプッシュし、ランナーの保持ポリシーに従って一時コンテナとイメージを削除します。
Dockerfile の ARG や ENV でシークレットを渡してはいけません。代わりに BuildKit のシークレットマウントまたは CI システムのシークレット機構を使います。
コメント
GitHub で閲覧・コメントする(投稿にはログインが必要です)