Docker-in-Docker とは?コンテナ内で Docker を実行する
Docker-in-Docker(DinD)は、コンテナ内で完全な Docker daemon を実行し、コンテナ化された CI job が自身のイメージを build して実行できるようにします。
CI job はしばしばコンテナ内で実行されますが、それでも Docker イメージを build する必要があります。これは鶏と卵の問題です。job には Docker が必要ですが、すでにコンテナ内にいるのです。Docker-in-Docker はネストした daemon を実行することでこれを解決します - もっとも、よりシンプルな socket 共有のアプローチのほうが好ましいことが多いのですが。
ネストした daemon のアプローチ
DinD は job のコンテナ内で dockerd を実行します(一般的には docker:dind イメージを介して)。job はこの内側の daemon と対話し、それが host から隔離された状態でイメージを build します。通常は privileged コンテナを必要とします。
socket-mount という代替手段
ネストする代わりに、host の Docker socket(/var/run/docker.sock)を job に mount します。すると job の docker コマンドは host daemon を制御します。これは軽量ですが、job は host daemon とそのセキュリティ境界を共有します。
トレードオフ
- DinD: 隔離は優れているが、privileged モードが必要で遅い。
- Socket mount: 高速でシンプルだが、隔離は弱い。
- rootless または daemonless の builder(BuildKit、Buildah)は両方の落とし穴を回避する。
daemonless の builder が台頭している理由
BuildKit(buildx 経由)や Buildah のようなツールは、privileged な daemon なしに OCI イメージを build でき、DinD のセキュリティと複雑さにまつわる話の多くを回避します。今では多くの pipeline がそれらを好みます。
CI における DinD
多くのマネージド runner では、runner 上で Docker がすでに利用可能なため、ネストした daemon を完全に避けて、直接イメージを build できます。それにより、DinD を配線するよりも build がシンプルで高速になります。
重要なポイント
- DinD は、コンテナ化された job がイメージを build できるよう、ネストした Docker daemon を実行します。
- host の socket を mount するほうがシンプルですが、host daemon のセキュリティ境界を共有します。
- daemonless の builder(BuildKit、Buildah)が、その問題そのものを回避することが増えています。