Kubernetes 上のコンテナの中で docker コマンドを使えるようにしたい、そんなとき...
実現方法として DinD と DooD のどちらを採用すべきか...
DooD(Docker Outside Of Docker)
- ホストマシンの Dockerデーモン をマウントして、Docker コンテナ内で Docker コマンドを使えるようにする手法
実装方法
- Kubernetes のホストマシンの
/var/run
を共有し、Docker デーモン にアクセスできるようにするだけ
apiVersion: v1
kind: Pod
metadata:
name: dood
spec:
containers:
- name: docker
image: docker:19.03
command: ["docker", "run", "nginx:latest"]
volumeMounts:
- mountPath: /var/run
name: docker-sock
volumes:
- name: docker-sock
hostPath:
path: /var/run
Pros
- 実装が簡単
- 特別な権限を与える必要がない
Cons
- docker デーモンを共有しているので、Pod 上のコンテナからホストマシンで動作しているコンテナを操作できてしまう
DinD(Docker In Docker)
-
Docker が提供している docker:dind イメージを使用し、Docker コンテナ内でさらに Docker デーモンを稼働させることで、Docker コンテナ内でさらに Docker コンテナを配置できるようにする手法
-
コマンドラインで DinD を起動する方法は下記の通り
docker run --rm -it --privileged --name dind-test -d docker:stable-dind
実装方法
- docker コマンドを実行するコンテナのサイドカーとして Docker デーモンコンテナを動かし、docker コマンドがサイドカーに対してアクセスするように設定する
apiVersion: v1
kind: Pod
metadata:
name: dind
spec:
containers:
- name: docker
image: docker:19.03
command: ["docker", "run", "nginx:latest"]
env:
- name: DOCKER_HOST
value: tcp://localhost:2375
- name: dind-daemon
image: docker:19.03-dind
env:
- name: DOCKER_TLS_CERTDIR
value: ""
resources:
requests:
cpu: 20m
memory: 512Mi
securityContext:
privileged: true
ちなみに
- dind-daemon コンテナの
DOCKER_TLS_CERTDIR
を""
にするのが重要 -
DOCKER_TLS_CERTDIR
を""
にしないと Docker デーモンが2376
Portで起動し、TLSモードになるので証明書が必要 - Dockerhub の Docker イメージの Description の TLS の説明の中に、環境変数
DOCKER_TLS_CERTDIR
で指定されたディレクトリにTLS証明書を自動的に生成する仕様が、19.03 以降はデフォルトで有効になったと記載がある - 19.03の Docker のソースコードで、起動 Port の分岐箇所はこちら
Pros
- ホストマシンの Docker デーモンとは別に Pod 内のコンテナの中に Docker デーモンが作成されるので、ホストマシンに影響を与えることなく Pod 内で完結する
Cons
- サイドカーコンテナが1つ増える
- dockerデーモンのサイドカーコンテナは
privileged 権限(特権モード)
で実行する必要がある - コンテナ内の
/var/lib/docker
は 暗黙的にData Volume
が使われるので、コンテナの再生成を繰り返すと不要になったData Volume
が溜まっていくため注意が必要
大変参考になったリンク
KubernetesのPodでDockerコンテナを実行する
A case for Docker-in-Docker on Kubernetes (Part 2)
Dockerコンテナ内からDockerを使うことについて
Docker in Docker のベタープラクティス
do-not-use-docker-in-docker-for-ci/
コンテナからコンテナを操作する