はじめに
dockerコンテナ内からコンテナを制御する方法の1つにDooD(Docker outside of Docker)がありますが、コンテナを制御するときにホストとコンテナ両方ともにdocker-composeを使用できるか検証してみました。
検証では、CentOS 7.6にdocker-ce(19.03)とdocker-compose(1.25.2)をインストールして検証しました。構成としては、下のような構成で、Ubuntuからアクセスして設定しています。
準備
CentOS 7.6 のminimalインストールの状態からdockerとdocker-composeをインストールし、ついでにdoodコンテナイメージを自作します。
dockerのインストール
参考:http://docs.docker.jp/engine/installation/linux/docker-ce/centos.html
- CentOS 7のバージョンを7.6の固定してupdateする。
- yum-utils、device-mapper-persistent-data、lvm2をインストールする。
- docker-ceをインストールする。
# echo 7.6.1810 > /etc/yum/vars/releasever
# sed -i".org" -e "s/^mirror/#mirror/" -e "s/^#baseurl/baseurl/g" -e "s/mirror.centos/vault.centos/g" /etc/yum.repos.d/CentOS-Base.repo
# yum update
# yum install -y yum-utils device-mapper-persistent-data lvm2
# yum install docker-ce-19.03.8-3.el7
# yum clean all
dockerdの設定変更
*この設定は半分くらい趣味です。dockerのimageやvolume情報等は、デフォルトでは/var/lib/docker以下に格納されますが、そのディレクトリを/home/docker/system以下に変更します。
- docker.serviceが起動している場合は、停止させる。
- /usr/lib/systemd/system/docker.service をviで以下のように修正する。
- /var/lib/docker/以下のファイルをすべて削除する。
- daemon reload後、docker.serviceを再起動する。
# systemctl stop docker
# mkdir /home/docker; mkdir /home/docker/system; mkdir /home/docker/container
# vi /usr/lib/systemd/system/docker.service
--------------------------------------------------------------------------------
(修正前)
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
(修正後)
ExecStart=/usr/bin/dockerd -g /home/docker/system --storage-driver overlay2 -H fd:// --containerd=/run/containerd/containerd.sock
--------------------------------------------------------------------------------
# rm -rf /var/lib/docker/
# systemctl daemon-reload
# systemctl restart docker
docker起動確認
公式のhttpdイメージを使って動作確認します。
- docker hubからhttpdコンテナイメージをpullする。
- port 58080をfirewallの許可ポートに設定する。(port 58080からアクセスさせるため)
- httpdコンテナをport 58080 -> 80に転送するようにオプションを設定して起動する。
- Ubuntuのブラウザから
http://192.168.1.10:58080
にアクセスし、「It works!」が表示されることを確認する。
# docker image pull httpd
# firewall-cmd --add-port=58080/tcp --zone=public --permanent
# docker container run -d --rm --name web -p 58080:80 httpd:latest
(動作確認後)
# docker container stop web
docker-composeのインストール
githubのdocker-composeプロジェクトのreleaseからdocker-composeを取得する。(下のコマンドはreleaseの手順より)
# curl -L https://github.com/docker/compose/releases/download/v1.25.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
DooDコンテナイメージ作成
DooDを実施するだけならば、dockerhub公式のdockerイメージを活用すると良いです。今回はDooDコンテナ内に入ってデバッグ等することを考慮して、準備作業で作ったCentOS7.6をまるごとコンテナ化してDooDコンテナイメージを作成します。
- /root/workspace/container_base を作成し、この中に/ 以下の必要なディレクトリをコピーしたり、空ディレクトリを作成したりする。
- docker image importを使用して、centos7-dood:0.0としてローカルリポジトリに登録する。
# mkdir /root/workspace/container_base
# cd /root/workspace/container_base
# cp -r /etc /run /srv /usr /var .
# mkdir boot dev home media opt proc root sys tmp
# chmod 777 tmp
# ln -s usr/bin; ln -s usr/sbin; ln -s usr/lib; ln -s usr/lib64
# cd /root/workspace/container_base/root;cp /root/.* .
# cd /root/workspace/container_base/home;cp -r /home/guest .; chown -R guest:guest guest; chmod 755 guest
# cd /root/workspace/container_base; tar cvf centos7-dood.tar *
# cat centos7-dood.tar | docker import - centos7-dood:0.0
確認
現時点で、centos7.6にはhttpdイメージとcentos7-doodイメージがローカルリポジトリ登録されたことになります。
(centos7-doodコンテナは自作なのでサイズがデカイです。多言語の言語ファイルやfirmware等のゴミを削除すればもう少し小さくなります。)
# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
centos7-dood 0.0 e5fb14d9d88a XX hours ago 1.48GB
httpd latest b2c2ab6dcf2e YY hours ago 166MB
検証
docker-compose.ymlの構成
/home/docker/container以下にdocker-compose.ymlを作成し、以下のようにdirectorサービスとwebサービスを定義します。directorがDooDを実施するコンテナであり、コンテナ内でwebサービスの起動を実施します。DooDをするため、ホストのdocker.sockをコンテナ内にマウントします。
# docker-compose.yml
version: '3'
services:
director:
image: centos7-dood:0.0
privileged: true
tty: true
stdin_open: true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /home/docker/container/docker-compose.yml:/home/docker/container/docker-compose.yml:ro
command: /bin/bash
web:
image: httpd:latest
ports:
- "58080:80"
ホスト側での動作確認
docker-compose up -dで実行し、コンテナが起動することを確認します。また、httpdが立ち上がったことを確認するため、Ubuntuのブラウザからhttp://192.168.1.10:58080
にアクセスし、「It works!」が表示されることを確認します。
# cd /home/docker/container/
# docker-compose up -d
Creating network "container_default" with the default driver
Creating container_web_1 ... done
Creating container_director_1 ... done
(動作確認後)
# docker-compose down
止める前に、docker inspectにてcontainer_director_1の中身を確認してみます。
# docker container inspect container_director_1
(中略)
"Labels": {
"com.docker.compose.config-hash": "a93046・・・・・・"
(後略)
docker-composeのソースコードを確認していないのでこれは推測となりますが、このconfig-hash生成の一部にdocker-compose.ymlのパス情報が含まれます。(そのため、-fオプションでymlファイルを指定して、yumファイルごとにcompose制御できます。)
そのため、ホストとコンテナでdocker-composeの情報を共有するならば、ホストと同じディレクトリにホストと同じdocker-compose.ymlを配置
すればいい、とわかります。上記のdocker-compose.ymlで/home/docker/container/docker-compose.yml:/home/docker/container/docker-compose.yml:ro
としているのは、そのためです。
*2020/5/3(日) 一部訂正:ホストとコンテナで同じディレクトリにdocker-compose.ymlを配置する必要はなかったです。
追調査したところ、docker-compose.ymlが格納されるディレクトリ名称が同じならば大丈夫でした。例えば、
「/home/docker/container
/docker-compose.yml:/home/container
/docker-compose.yml:ro」
とcontainerが揃っていればOKです。
DooDの実施
ホストにてdirectorサービスを立ち上げた後、directorコンテナ内に入り、docker-composeでwebサービスを立ち上げます。確認は上記と同様にUbuntuのブラウザからhttp://192.168.1.10:58080
にアクセスし、「It works!」が表示されることを確認します。
(区別がつくように、@centos1 と表示されているときはホスト、@a8784c960fe6 と表示されているときはコンテナの操作となります。)
[root@centos1 ~]# cd /home/docker/container/
[root@centos1 container]# docker-compose up -d director
Creating network "container_default" with the default driver
Creating container_director_1 ... done
[root@centos1 container]# docker-compose ps
Name Command State Ports
------------------------------------------------
container_director_1 /bin/bash Up
[root@centos1 container]# docker-compose exec director /bin/bash
[root@a8784c960fe6 /]# docker-compose -f /home/docker/container/docker-compose.yml ps
Name Command State Ports
------------------------------------------------
container_director_1 /bin/bash Up
[root@a8784c960fe6 /]# docker-compose -f /home/docker/container/docker-compose.yml up -d web
Creating container_web_1 ... done
[root@a8784c960fe6 /]# docker-compose -f /home/docker/container/docker-compose.yml ps
Name Command State Ports
-----------------------------------------------------------------------
container_director_1 /bin/bash Up
container_web_1 httpd-foreground Up 0.0.0.0:58080->80/tcp
まとめ
DooDするときに、docker-composeの情報をホストとコンテナで共有できます。これ単独では旨味が少ないですが、Docker Remote APIと組み合わせて、外部サーバからDooDコンテナにコンテナ起動指示を出すことで、複数コンテナの同時制御ができるようになります。