プロセスID1の終了でコンテナ停止

コンテナはどのような状態になると停止するのか。

  1. プロセスID1終了でコンテナ停止
  2. バックグラウンドのプロセスだけだとコンテナ停止
  3. docker stopでコンテナ停止
  4. プロセスID1をホストでkillしてもコンテナ停止

プロセスID1終了でコンテナ停止

# 渡すのはpsコマンドだけ(プロセスID1になる)
# ps -Aで全てのプロセスを表示してすぐ終了する
docker run --rm -it --name test centos:7 \
  ps -A --format pid,etime,args
  PID     ELAPSED COMMAND
    1       00:03 ps -A --format pid,etime,args

# 停止確認
docker ps --filter=name=test

上記のように、プロセスID1のコマンド(ps)が終了すると、コンテナも自動停止する(--rmもあるのでコンテナ削除)。


バックグラウンドのプロセスだけだとコンテナ停止

# バックグラウンドのコマンド複数と、すぐに終了するpsコマンドを渡す
# 「コマンド &」でバックグラウンドになる
docker run --rm -it --name test centos:7 \
  bash -c " \
    sleep 5m & \
    sleep 10m & \
    ps -A --format pid,ppid,user,args,etime \
  " # ppidは親プロセスPID
  PID  PPID USER     COMMAND                         ELAPSED
    1     0 root     bash -c      sleep 5m &           00:00
    7     1 root     sleep 5m                          00:00
    8     1 root     sleep 10m                         00:00
    9     1 root     ps -A --format pid,ppid,use       00:00

# sleepがバックグラウンドで生きるはずが、すぐ停止している
docker ps --filter=name=test

上記のように、プロセスID1のシェル以外で残るプロセスがバックグラウンドのものだけだと、すぐにコンテナ停止となってしまう。

一つでもフォアグラウンドあればコンテナ継続

フォアグラウンドのコマンドがあれば、プロセスID1のシェルは継続するので、コンテナは継続できる。

# tail -fがフォアグラウンド
# コンテナはバックグラウンド・モード
docker run --rm -dit --name test centos:7 \
  bash -c " \
    sleep 5m & \
    tail -f /dev/null \
  "

# 確認
docker exec -it test \
  ps -A --format pid,ppid,user,args,etime
  PID  PPID USER     COMMAND                         ELAPSED
    1     0 root     bash -c      sleep 5m &           00:13
    7     1 root     sleep 5m                          00:12
    8     1 root     tail -f /dev/null                 00:12
    9     0 root     ps -A --format pid,ppid,use       00:01

# コンテナ停止
docker stop test

docker stopでコンテナ停止

コマンドが自然に停止する前に、途中でコンテナを停止するにはdocker stopを使う。


プロセスID1をホストでkillしてもコンテナ停止

次のように、コンテナにとってのプロセスID1をホストから強制終了(SIGKILL)してもコンテナ停止となる。普通は使わない。

docker run --rm -dit --name test centos:7 sleep 1111

# ホストから見るプロセスIDを調べる
ps -A --format pid,user,args | grep 'sleep 1111'
24889 root     sleep 1111

# root権限で、上のプロセスIDをkill
# SIGTERMでは効かない
target=$( ps -A --format pid,user,args | grep 'sleep 1111' | head -1 | awk '{print $1}' )
echo $target
kill -s SIGKILL $target

# 停止確認
docker ps --filter=name=test

コンテナからプロセスID1をSIGKILLでもkillできないものがある

次のように、シグナルをキャッチしていないコマンドがプロセスID1の場合は、SIGKILLでさえもkillができない模様。(ドキュメント未確認)

# バックグラウンドのコンテナ起動
docker run --rm -dit --name test centos:7 sleep 1111

# さらにBashプロセス追加
docker exec -dit test bash

# プロセス確認
docker exec -it test \
  ps -A --format pid,ppid,user,args,etime
  PID  PPID USER     COMMAND                         ELAPSED
    1     0 root     sleep 1111                        00:14
    7     0 root     bash                              00:08
   21     0 root     ps -A --format pid,ppid,use       00:00

# kill(SIGKILL)
# プロセスID1にkillを試す
docker exec -it test kill -s SIGKILL 1

# bashのpid(この例では7)
target=$( docker exec -it test ps -A --format pid,ppid,user,args,etime | grep bash | awk '{print $1}' )
echo $target
# bashをkill
docker exec -it test kill -s SIGKILL $target

# プロセス確認
docker exec -it test \
  ps -A --format pid,ppid,user,args,etime
  PID  PPID USER     COMMAND                         ELAPSED
    1     0 root     sleep 1111                        05:03
   45     0 root     ps -A --format pid,ppid,use       00:01
# プロセスID1のsleepは生きたまま

# コンテナ停止
docker stop test