docker run
コマンドで使える --pid
オプションを試す.Docker では以下のドキュメントに書いてある通り,デフォルトでは PID namespace でコンテナ同士を隔離する.よって,コンテナ同士でプロセスを共有することはできず,各コンテナでは PID 1 を含む「プロセス ID」を再利用できるようになっている.今回は一歩一歩確認しながら進めていく.
PID 1 を確認する
まず,デフォルトの挙動を確認する.以下のように docker run
コマンドで nginx コンテナを起動する.そして docker exec
コマンドでコンテナに接続をしてプロセス一覧を確認すると,nginx
プロセスが PID 1 になっていることがわかる.なお,Alpine Linux なので ps
コマンドを実行できるようにしておく必要がある.
$ docker run --rm -d -it nginx:1.21 9313d4a4fc73cf2a173569d3f5f76595169c1577b242b9cf7b019afe32785df0 $ docker exec -it 9313d4a4fc73 /bin/sh # apt update # apt install -y procps # ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 01:34 pts/0 00:00:00 nginx: master process nginx -g daemon off; nginx 32 1 0 01:34 pts/0 00:00:00 nginx: worker process nginx 33 1 0 01:34 pts/0 00:00:00 nginx: worker process nginx 34 1 0 01:34 pts/0 00:00:00 nginx: worker process nginx 35 1 0 01:34 pts/0 00:00:00 nginx: worker process root 36 0 0 01:35 pts/1 00:00:00 /bin/sh root 364 36 0 01:36 pts/1 00:00:00 ps -ef
次に docker run
コマンドで新しく Ubuntu コンテナを起動する(今回は sleep
コマンドでプロセスを常駐させておく).同じく docker exec
コマンドでコンテナに接続をしてプロセス一覧を確認すると,sleep
プロセスが PID 1 になっていることがわかる.よって,nginx も Ubuntu もコンテナ同士で隔離されていると言える.
$ docker run --rm -d -it ubuntu:21.10 /bin/sh -c 'sleep 300' 5c754ed1f167ece55849ac5760d902782f562b6815c2fff05dc472c1cb54bc35 $ docker exec -it 5c754ed1f167 /bin/sh # ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 01:31 pts/0 00:00:00 /bin/sh -c sleep 300 root 8 1 0 01:31 pts/0 00:00:00 sleep 100 root 9 0 0 01:32 pts/1 00:00:00 /bin/sh root 17 9 0 01:32 pts/1 00:00:00 ps -ef
--pid
オプション
次に docker run
コマンドの --pid
オプションを試す.既に起動している nginx コンテナ(9313d4a4fc73
)の PID namespace を共有した Ubuntu コンテナを起動するために --pid=container:9313d4a4fc73
のようにオプションを指定する.
$ docker run --rm -d --pid=container:9313d4a4fc73 -it ubuntu:21.10 /bin/sh -c 'sleep 300'
同じく docker exec
コマンドで Ubuntu に接続をしてプロセス一覧を確認すると,nginx コンテナのプロセスを確認できるようになった.そして Ubuntu コンテナの sleep
プロセスが PID 372 となり,PID 1 ではなくなっている.よって,コンテナ同士で PID namespace を共有できていると言える.
$ docker exec -it 06bbc0fb87f3 /bin/sh # ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 01:34 pts/0 00:00:00 nginx: master process nginx -g daemon off; 101 32 1 0 01:34 pts/0 00:00:00 nginx: worker process 101 33 1 0 01:34 pts/0 00:00:00 nginx: worker process 101 34 1 0 01:34 pts/0 00:00:00 nginx: worker process 101 35 1 0 01:34 pts/0 00:00:00 nginx: worker process root 372 0 0 02:03 pts/0 00:00:00 /bin/sh -c sleep 300 root 379 372 0 02:03 pts/0 00:00:00 sleep 300 root 380 0 0 02:04 pts/1 00:00:00 /bin/sh root 386 380 0 02:04 pts/1 00:00:00 ps -ef
--pid
オプションの活用例
では --pid
オプションをどのように活用すれば良いかと言うと「サイドカー」のように使える.書籍「分散システムデザインパターン」の「2章 : サイドカー」で brendanburns/topz イメージを使った例が載っているので,参考にしながら試していく.
既に起動している nginx コンテナ(9313d4a4fc73
)の PID namespace を共有した topz コンテナを起動する.そして http://localhost:8080/topz
にリクエストを送ると,nginx コンテナのプロセス一覧とリソース使用量を確認できる.このように「プロセスのモニタリング機能」を --pid
オプションで「サイドカー」として追加できるという活用に繋がる.
$ docker run --rm -d --pid=container:9313d4a4fc73 -p 8080:8080 brendanburns/topz:db0fa58 /server --addr=0.0.0.0:8080 $ curl http://localhost:8080/topz 1 0 0.21145721 nginx: master process nginx -g daemon off; 32 0 0.11457208 nginx: worker process 33 0 0.11457208 nginx: worker process 34 0 0.11457208 nginx: worker process 35 0 0.11457208 nginx: worker process 36 0 0.17175984 /server --addr=0.0.0.0:8080
Docker Compose と pid
オプション
今度は Docker Compose の場合にどうなるんだろう?と気になるため PID namespace を確認する.以下のように nginx コンテナと Ubuntu コンテナを含めた docker-compose.yml
を作る.
version: '3.9' services: nginx: image: nginx:1.21 ubuntu: image: ubuntu:21.10 command: sleep 300
そして docker compose up
コマンドでコンテナを起動して docker compose exec
コマンドで Ubuntu コンテナに接続をしてプロセス一覧を確認すると sleep
プロセスが PID 1 になっている.よって,デフォルトでは PID namespace でコンテナ同士を隔離していると言える.
なお,docker-compose.yml
に pid: "host"
を追加すると「ホスト側」と PID namespace を共有できる.実際に使う機会は少なそうだけど,ドキュメントに載っていた.そしてコンテナ同士での PID namespace 共有は Compose file version 2 reference のドキュメントには載っていたけど,Compose file version 3 reference では消えていた.
$ docker compose up $ docker compose exec ubuntu /bin/sh # ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 02:51 ? 00:00:00 sleep 300 root 7 0 0 02:52 pts/0 00:00:00 /bin/sh root 14 7 0 02:52 pts/0 00:00:00 ps -ef
まとめ
docker run
コマンドで使える --pid
オプションを試した.デフォルトでは PID namespace でコンテナ同士を隔離するけど,--pid
オプションで PID namespace を共有できるようになる.そして,書籍「分散システムデザインパターン」にも載っている通り,「サイドカー」のように活用することができる.
関連記事
書籍「分散システムデザインパターン」の書評記事は以下にある.合わせて読んでもらえると!
また docker run
コマンドには多くのオプションがある.今月公開した以下の記事では --security-opt
オプションを紹介している.