1. はじめに
コンテナの中にコンテナを立てたい、コンテナ内からホストマシンのコンテナを操作したい、そんなことを考えた方も多いのではないでしょうか。
こうした要求にこたえられる手法がdind (docker-in-docker)
とdood (docker-outside-of-docker)
です。
- コンテナの中にコンテナを立てたい >> dind (docker-in-docker) を使います
- コンテナ内からホストマシンのコンテナを操作したい >> dood (docker-outside-of-docker) を使います
本記事では実際にdindとdoodを用いてコンテナを起動するまでを実施します。
想定読者
- コンテナの起動停止、コンテナに入っての作業など基本的な操作ができる方
- コンテナに関する基礎的な用語を理解している方
- dind、doodの概要を知りたい方
- dind、doodを使ってコンテナを利用したい方
2. dindとdoodについて
2.1 Dockerデーモンとtcp通信/Unixドメインソケット通信
コンテナの起動停止などを行う際にはdockerコマンドを用いてdockerデーモンに対して命令を送ります。
dockerコマンドを実行すると①TCP通信
または②Unixドメインソケット通信
のいずれかによりdockerデーモンへ命令が送られます。
従って、操作対象としたいマシンのdockerデーモンへ命令を送ることが出来れば、どのような環境からも対象マシン上のコンテナを操作することが出来ます。
この辺りはDocker を他のホスト・ポートや Unix ソケットに接続に記載があります。
dindやdoodではこの仕組みを利用し、命令の送り先として操作対象のマシンを明示的に指定することで実現されます。
なお、本記事では②Unixドメインソケット通信
を用いることとします。
2.2 dind (docker-in-docker)
dind (docker-in-docker) はコンテナ内にホストマシンとは完全に独立したdocker環境を構築する手法です。
下図では、ホストマシン上にdocker環境があり、これとは別にコンテナA内部にもdocker環境が構築されています。
ホストマシンとコンテナAとで異なるdocker.sock
ファイルを保持している点に注目してください。
docker.sock
は、一般的にソケットファイルと呼ばれるものでUnixドメインソケット通信に利用されます。
これはホストマシンのdockerとコンテナAのdockerが異なるdockerデーモンを操作対象としていることを意味しています。
従って、ホストマシン上でdockerコマンドを実行した場合はホストマシンのdockerデーモンに対して命令が送られます。
一方でコンテナA内部でdockerコマンドを実行した場合はコンテナAのdockerデーモンに対して命令が送られます。
ホストマシン上で起動したコンテナ(図中のコンテナA/B/C)の存在はホストマシン上からしか確認できず、コンテナA上で起動したコンテナ(図中のコンテナX/Y)はコンテナAからしか存在を確認できません。
また、当然のことながらコンテナAを停止するとコンテナX/Yも同時に停止されます。
2.3 dood (docker-outside-of-docker)
dood (docker-outside-of-docker) はコンテナ内からホストマシンのdockerを操作する手法です。
下図では、ホストマシン上にdocker環境があり、コンテナAはホストマシンのdocker環境に接続しています。
コンテナAにはホストマシンのdocker.sock
ファイルがマウントされている点に注目してください。
docker.sock
は、一般的にソケットファイルと呼ばれるものでUnixドメインソケット通信に利用されます。
コンテナAのdockerがホストマシンのdockerデーモンを操作対象としていることを意味しています。
従って、ホストマシン上でdockerコマンドを実行した場合も、コンテナA上でdockerコマンドを実行した場合もホストマシンのdockerデーモンに対して命令が送られます。
ホストマシン上からはホストマシン上で起動したコンテナ(図中のコンテナA/B/C)とコンテナA上で起動したコンテナ(図中のコンテナX/Y)の両方の存在を確認できます。
これは、逆にコンテナAからもすべてのコンテナ(図中のコンテナA/B/C/X/Y)の存在が確認できることを意味しています。
また、コンテナAを停止したとしてもホストマシン上で起動されているコンテナX/Yは停止されません。
3. dind (docker-in-docker) を試す
3.1 docker:dindイメージを利用したdind
まずは一般的によく使われているdocker:dind
のイメージを利用したdindの方法です。
以下のコマンドでコンテナを起動します。
docker run -it --rm --privileged --name dind -d docker:20-dind
起動したコンテナ内に入ってdocker ps
コマンドを実行すると何も表示されません。
これにより、コンテナ内にホストマシンとは異なる独立したコンテナ環境が構築できていることを確認できます。
C:\Users\user>docker exec -it dind sh
/ # docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3.2 CentOSイメージを利用したdind
docker:dind
のイメージを使うと簡単にdindが実現できることが分かりましたが、CentOSなどのイメージでdindを行いたい時があります。
この場合はコンテナ内で通常と同じ手順でdockerをインストールすると実現できます。
以下でcentosのコンテナを起動します。
コンテナ内でsystemctl
が使用できるように--privileged
オプションを使用しています。
C:\>docker run -d --privileged --name dind centos:7 /sbin/init
C:\>docker exec -it dind bash
起動したコンテナに入り、以下の手順に従ってdockerをインストールします。
[root@00587f333c1e /]# yum install -y yum-utils
[root@00587f333c1e /]# yum-config-manager \
> --add-repo \
> https://download.docker.com/linux/centos/docker-ce.repo
[root@00587f333c1e /]# yum install docker-ce docker-ce-cli containerd.io
[root@00587f333c1e /]# systemctl enable --now docker
インストール完了後にdocker psコマンドを実行するとコンテナが1つも起動していないことが確認できます。
これによりホストマシンとは異なるdocker環境がコンテナ内に構築できていることが確認できました。
[root@00587f333c1e /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4. dood (docker-outside-of-docker) を試す
4.1 dockerイメージを利用したdood
doodを実現するために、下記のコマンドでdockerイメージを起動します。
-v /var/run/docker.sock:/var/run/docker.sock
オプションによりホストマシンのソケットファイルをコンテナ内へマウントさせています。
docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock --name dood docker:20
起動したコンテナ内からdocker ps
コマンドを実行してみるとホストマシン上で稼働しているコンテナ(この場合だと自分自身のコンテナ)が確認できます。
/ # docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
af159e03e643 docker:20 "docker-entrypoint.s…" 3 seconds ago Up 2 seconds dood
4.2 CentOSイメージを利用したdood
dindと同じく、centosなどを用いてもdoodは実現できます。
先ほどと同じく、ソケットファイルをマウントしてコンテナを起動します。
docker run -d -v /var/run/docker.sock:/var/run/docker.sock --name dood centos:7 /sbin/init
コンテナ内へ入り、docker-cli
をインストールします。
doodではコンテナ内でdockerデーモンを起動するわけではないのでインストールするのはCLIのみで大丈夫です。
[root@86a4aff52d05 /]# yum install -y yum-utils
[root@86a4aff52d05 /]# yum-config-manager \
> --add-repo \
> https://download.docker.com/linux/centos/docker-ce.repo
[root@86a4aff52d05 /]# yum install docker-ce-cli
インストール完了後にdockerコマンドを実行すると、ホストマシン上で起動しているコンテナを確認することができました。
[root@86a4aff52d05 /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
86a4aff52d05 centos:7 "/sbin/init" 16 minutes ago Up 16 minutes dood
00587f333c1e centos:7 "/sbin/init" 24 minutes ago Up 24 minutes dind