「docker container run」コマンドの、「--pid」というオプションを知らなかったので。
$ docker container run --help | grep 'pid ' --pid string PID namespace to use
こちらを使うと、指定したコンテナ(ホストも可)とPID名前空間を共有できるようです。
docker run | Docker Documentation
docker container run | Docker Documentation
ちょっと試してみましょう。
例えば、nginxのコンテナを起動してみます。コンテナ名は、「nginx」としました。
$ docker container run -it --rm --name nginx nginx:1.17.0
ここでもうひとつ、Dockerコンテナを起動してみましょう。Ubuntu Linux 18.04 LTSのイメージを使います。
$ docker container run -it --rm --name ubuntu --pid=container:nginx ubuntu:18.04 bash
この時、「--pid:container:[コンテナ名]」を指定して起動します。
すると、Ubuntu Linuxのコンテナ側から「--pid」で指定したコンテナのプロセスを見ることができます。
# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 13:11 pts/0 00:00:00 nginx: master process nginx -g daemon off; 101 6 1 0 13:11 pts/0 00:00:00 nginx: worker process root 7 0 1 13:13 pts/0 00:00:00 bash root 17 7 0 13:13 pts/0 00:00:00 ps -ef
1度抜けて、「--pid」オプションの指定を外してみましょう。
$ docker container run -it --rm --name ubuntu ubuntu:18.04 bash
nginxのプロセスが見えなくなります。そりゃあそうですよね。
# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 13 13:13 pts/0 00:00:00 bash root 10 1 0 13:13 pts/0 00:00:00 ps -ef
「--pid:container:」の後に指定するのはコンテナのIDでも、もちろんOKです。
$ docker container run -it --rm --name ubuntu --pid=container:653933fbb169 ubuntu:18.04 bash # ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 13:11 pts/0 00:00:00 nginx: master process nginx -g daemon off; 101 6 1 0 13:11 pts/0 00:00:00 nginx: worker process root 33 0 6 13:17 pts/0 00:00:00 bash root 42 33 0 13:17 pts/0 00:00:00 ps -ef
ちなみに、この状態で共有しているのはPIDの名前空間であり、他のコンテナのファイルなどが見えたりするわけではありません。
# ls -l /etc/nginx ls: cannot access '/etc/nginx': No such file or directory
確認のため、nginxコンテナ側へ「docker container exec」。
$ docker exec -it nginx ls -l /etc/nginx total 40 drwxr-xr-x 2 root root 4096 Jun 11 00:03 conf.d -rw-r--r-- 1 root root 1007 May 21 14:23 fastcgi_params -rw-r--r-- 1 root root 2837 May 21 14:23 koi-utf -rw-r--r-- 1 root root 2223 May 21 14:23 koi-win -rw-r--r-- 1 root root 5231 May 21 14:23 mime.types lrwxrwxrwx 1 root root 22 May 21 14:45 modules -> /usr/lib/nginx/modules -rw-r--r-- 1 root root 643 May 21 14:45 nginx.conf -rw-r--r-- 1 root root 636 May 21 14:23 scgi_params -rw-r--r-- 1 root root 664 May 21 14:23 uwsgi_params -rw-r--r-- 1 root root 3610 May 21 14:23 win-utf
で、これでなにが嬉しいかというと、たとえばlsofなどのコマンドを使ってプロセスの情報を確認したりできるわけですね。
# apt update -y && apt install lsof -y # lsof -p 1 | head -n 10 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nginx 1 root cwd DIR 0,103 4096 15350471 / nginx 1 root rtd DIR 0,103 4096 15350471 / nginx 1 root txt REG 0,103 1322024 15220792 /usr/sbin/nginx nginx 1 root mem REG 8,8 15220792 /usr/sbin/nginx (stat: No such file or directory) nginx 1 root mem REG 8,8 14824535 /lib/x86_64-linux-gnu/libnss_files-2.24.so (stat: No such file or directory) nginx 1 root mem REG 8,8 14824539 /lib/x86_64-linux-gnu/libnss_nis-2.24.so (stat: No such file or directory) nginx 1 root mem REG 8,8 14824511 /lib/x86_64-linux-gnu/libnsl-2.24.so (stat: No such file or directory) nginx 1 root mem REG 8,8 14824520 /lib/x86_64-linux-gnu/libnss_compat-2.24.so (stat: No such file or directory) nginx 1 root mem REG 8,8 14818351 /lib/x86_64-linux-gnu/libc-2.24.so (stat: No such file or directory)
sysstatなどを使っても良いでしょう。
# apt install sysstat -y # mpstat -P ALL 1
こういう各種ツールなどを入れたコンテナを、別コンテナのデバッグに使ったりするのとかも、ありなのかなーと。
プロセスにアタッチするようなstraceとかを使いたかったら、「--cap-add sys_ptrace」でSYS_PTRACE Capabilityを与えておく
必要があります。
$ docker container run -it --rm --name ubuntu --pid=container:nginx --cap-add sys_ptrace ubuntu:18.04 bash
Javaでjcmdやjstackで他のコンテナのJavaプロセスにアクセスしたい場合も、「--cap-add sys_ptrace」を付けておく必要が
ありそうです。
事前に、やりたいことができるかどうかは確認しておいた方が良さそうですね。それでも、知っておくと便利かなと。
また、「--pid」で指定する値を「host」にすると、ホスト側のPID名前空間を共有することができます。
$ docker container run -it --rm --name ubuntu --pid=host ubuntu:18.04 bash
このオプションを知ったのは、こちらの本を見ていて「サイドカー」の紹介で使われていて、こういうオプションがあるんだなぁ
と思って試してみたくなったのがきっかけです。
分散システムデザインパターン ―コンテナを使ったスケーラブルなサービスの設計
- 作者: Brendan Burns,松浦隼人
- 出版社/メーカー: オライリージャパン
- 発売日: 2019/04/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
こちらでは、あるコンテナに対して、別のコンテナを使って能力を付け加えるような形で紹介されていました。
なお、tcpdumpのようなネットワーク系の場合は、対象のコンテナと同じネットワークに参加する必要があるみたいです。
いろいろ調べておくと、デバッグ時に便利そうですね。