自分のコンテナが意図した通りに動いているかを正しく把握するために、コンテナがどのような状態遷移をするか理解しましょう。
コンテナが停止する理由を理解できていないと、「起動したはずのコンテナが見当たらない」とか「ターミナルが固まらないので起動に失敗したんだ」という勘違いに繋がってしまいます。
コンテナとプロセスについて
コンテナを起動する方法を学んだので、いくつかコンテナを起動して次はプロセスについて確認してみます。
例1: Ubuntu コンテナをデフォルト命令 ( bash ) で起動
Ubuntu コンテナを起動し、デフォルト命令の bash
を使っている状態で ps
コマンドでコンテナ内のプロセス一覧を確認すると、PID
の 1
は bash
になっています。
また ps
自身もプロセスとして存在します。
$ docker container run \
--name ubuntu1 \
--rm \
--interactive \
--tty \
ubuntu:20.04
# ps
PID TTY TIME CMD
1 pts/0 00:00:00 bash
10 pts/0 00:00:00 ps
例2: Nginx コンテナをデフォルト命令 ( nginx ) で起動
Nginx コンテナを起動しデフォルト命令の Web サーバが起動している状態では、PID
の 1
は nginx
の起動コマンドになっています。
ps
自身と ps
を実行するために container exec
で起動した bash
のプロセスも存在します。
( container exec
は【 2部: コンテナに接続する 】で説明します )
$ docker container run \
--name nginx1 \
--rm \
--detach \
nginx:1.21
$ docker container exec \
--interactive \
--tty \
nginx1 \
bash
# コンテナ内に ps コマンドがないためインストール
# apt update
# apt install -y procps
# ps x
PID TTY STAT TIME COMMAND
1 ? Ss 0:00 nginx: master process nginx -g daemon off;
36 pts/0 Ss 0:00 bash
387 pts/0 R+ 0:00 ps x
余談ですが、コンテナを起動するときに --tty
オプションを指定していないため、TTY
が ?
になっています。
例3: Nginx コンテナを指定命令 ( bash ) で起動
Nginx コンテナをデフォルト命令 ( nginx
) ではなく指定命令 ( bash
) で起動している状態では、PID
の 1
は bash
になっています。
また ps
のプロセスはありますが、nginx
のプロセスはありません。
$ docker container run \
--name nginx2 \
--rm \
--interactive \
--tty \
nginx:1.21 \
bash
# コンテナ内に ps コマンドがないためインストール
# apt update
# apt install -y procps
# ps
PID TTY TIME CMD
1 pts/0 00:00:00 bash
346 pts/0 00:00:00 ps
コンテナとプロセスの関係
コンテナは Namespace によって隔離されたプロセスであるということを【 2部: Docker を理解するためのポイント 】で学びました。
またコンテナにはイメージによって定められたデフォルトの命令があることと、container run
実行時に任意の命令を指定できることを【 2部: コンテナ起動時の基本の指定 】で学びました。
このページで確認したプロセスと前ページの学びを統合すると、次のように理解できます。
- コンテナは ある1つのコマンドを実行するため に起動している
- それはデフォルト命令か指定命令の どちらか で、
PID
が1
になる
- それはデフォルト命令か指定命令の どちらか で、
- 複数のコンテナの
PID = 1
は Linux の Namespace 機能により衝突しない
この本では便宜上 PID = 1
のプロセスを メインプロセス 、それを起動するコマンドを メインコマンド と呼びます。
コンテナはメインプロセスを実行するために起動する という点を押さえておくと、コンテナのことをよりスムーズに理解できるようになります。
たとえばコンテナが仮想サーバではなくただの1プロセスに見えてくると、「Ubuntu に PHP と MySQL と Apache を入れたコンテナを作ろう」ではなく「PHP と MySQL と Apache が必要だから3コンテナ作ろう」という発想に自然と変わります。
また、メインプロセスが終了したコンテナは自動で停止する という重要な点を理解できるようになります。
コンテナが停止するパターン
ここまでの前提知識を踏まえて、コンテナが停止する理由を大きく2つに分けて説明します。
- コンテナを停止する
- メインプロセスが終了する
コンテナ か メインプロセス のどちらかが先に終われば、もう片方も連動するということです。
どういうことが具体的に見ていきましょう。
1. コンテナを停止する
Nginx のコンテナをデフォルト命令 ( nginx
) で次の通りに起動します。
$ docker container run \
--name nginx3 \
--rm \
--detach \
nginx:1.21
起動した nginx
は Web サーバなので、 メインプロセスは止まれと言うまで止まりません。
メインプロセスは勝手に終了しないので、コンテナは停止か削除をするまで終了しません。
停止済コンテナの削除や起動中コンテナの強制削除については、【 2部: コンテナの基礎操作 】で説明した通りです。
2. メインプロセスが終了する
こちらはさらに2つに分類して確認します。
2-A. メインプロセスを自分で終了するパターン
同じ Nginx のコンテナを指定命令 ( bash
) で次の通りに起動します。
$ docker container run \
--name nginx4 \
--rm \
--interactive \
--tty \
nginx:1.21 \
bash
# do something
# do something
# exit
起動した bash
は exit
できるので、メインプロセスはいつか終了します。
メインプロセスが終了した場合、コンテナは連動して停止します。
当然 bash
の exit
より先にコンテナを停止することも可能です。
2-B. メインプロセスが自動で終了するパターン
最後に、また同じ Nginx のコンテナを指定命令 ( ls
) で次の通りに起動します。
$ docker container run \
--name nginx5 \
--rm \
nginx:1.21 \
ls /etc/nginx
$
起動した ls
は結果を表示するだけなので、メインプロセスは即時終了します。
メインプロセスが即終了するので、コンテナも連動して即時停止します。
コンテナが起動している瞬間は実質ないため、起動中のコンテナに強制削除を命じることはできません。
( 余談 ) 即時停止とバックグラウンド実行について
即時停止とバックグラウンド実行 ( --detach
オプション ) と混同しないようにしましょう。
コンテナの状態やコンテナ起動の成否は container run
の後にターミナルが固まったかどうかで判断してはいけません。
安易な覚え方をしないように注意しましょう。
メインコマンド | オプション | ターミナル | コンテナ | メインプロセス | 起動コマンドの実行結果 |
---|---|---|---|---|---|
nginx |
固まる | 起動中 | 起動中 | 正常 | |
nginx |
--detach |
固まらない | 起動中 | 起動中 | 正常 |
ls |
固まらない | 停止済 | 終了済 | 正常 ( 終了 ) |
まとめ
簡潔にまとめます。
- コンテナは メインプロセス (
PID = 1
) を実行するために起動する - コンテナが停止する理由は大きく分けて2つある
- コンテナを停止する
- メインプロセスが終了する
- 即時停止とバックグラウンド実行 (
--detach
オプション ) と混同しない
混乱してしまったときは立ち返ってみてください。
このページで作成したものの掃除
$ docker container rm --force \
ubuntu1 nginx1 nginx2 nginx3 nginx4 nginx5