Dockerコンテナーで実行されているいくつかのプロセスがあり、それらのPIDはコンテナーの名前空間で分離されていますが、Dockerホスト上のPIDを把握する方法はありますか?
たとえば、Dockerコンテナー内で実行されているApache Webサーバー( Docker Hub のApache + PHPイメージを使用)があり、Apacheは起動時にコンテナー内にさらにワーカープロセスを作成します。これらのワーカープロセスは、実際に着信要求を処理しています。これらのプロセスを表示するには、Dockerコンテナー内でpstree
を実行します。
# pstree -p 1
Apache2(1)-+-Apache2(8)
|-Apache2(9)
|-Apache2(10)
|-Apache2(11)
|-Apache2(12)
`-Apache2(20)
親Apacheプロセスは、コンテナプロセス名前空間内のPID 1で実行されます。ただし、ホストの観点からもアクセスできますが、ホスト上のそのPIDは異なり、docker compose
コマンド:
$ docker inspect --format '{{.State.Pid}}' container
17985
これから、コンテナプロセス名前空間内のPID 1がホスト上のPID 17985にマップされることがわかります。ホストでpstree
を実行して、Apacheプロセスの子をリストできます。
$ pstree -p 17985
Apache2(17985)─┬─Apache2(18010)
├─Apache2(18011)
├─Apache2(18012)
├─Apache2(18013)
├─Apache2(18014)
└─Apache2(18164)
これから、コンテナ内のPID 1がホスト上のPID 17985にマップする方法と同じ方法で、それもマップすると仮定します。
(これにより、straceのように、ホストでのみ使用でき、コンテナでは使用できないツールを使用して、Dockerコンテナからプロセスをデバッグできます)
問題は、pstreeがコンテナーとホストの両方で同じ順序でプロセスをリストすると想定するのがどれほど安全かわからないことです。
Dockerコンテナ内で実行されている特定のプロセスのホスト上のPIDを検出するより信頼性の高い方法を誰かが提案できたら、すばらしいでしょう。
/proc/<pid>/status
ファイルを見て、名前空間PIDとグローバルPID間のマッピングを決定できます。たとえば、Dockerコンテナで次のようにいくつかのsleep 900
プロセスを開始する場合:
# docker run --rm -it Alpine sh
/ # sleep 900 &
/ # sleep 900 &
/ # sleep 900 &
私はそれらがコンテナで実行されているのを見ることができます:
/ # ps -fe
PID USER TIME COMMAND
1 root 0:00 sh
7 root 0:00 sleep 900
8 root 0:00 sleep 900
9 root 0:00 sleep 900
10 root 0:00 ps -fe
ホストでこれらを見ることができます:
# ps -fe | grep sleep
root 10394 10366 0 09:11 pts/10 00:00:00 sleep 900
root 10397 10366 0 09:12 pts/10 00:00:00 sleep 900
root 10398 10366 0 09:12 pts/10 00:00:00 sleep 900
そして、それらのいずれについても、status
ファイルを見て名前空間pidを確認できます。
# grep -i pid /proc/10394/status
Pid: 10394
PPid: 10366
TracerPid: 0
NSpid: 10394 7
NSpid
行を見ると、PID名前空間内でこのプロセスはpid 7を持っていることがわかります。実際、ホスト上のプロセス10394
を強制終了すると:
# kill 10394
次に、コンテナ内でPID 7が実行されていないことがわかります。
/ # ps -fe
PID USER TIME COMMAND
1 root 0:00 sh
8 root 0:00 sleep 900
9 root 0:00 sleep 900
11 root 0:00 ps -fe