Chapter 07

2部: コンテナの状態遷移

ほげさん
ほげさん
2022.03.21に更新

自分のコンテナが意図した通りに動いているかを正しく把握するために、コンテナがどのような状態遷移をするか理解しましょう。

コンテナが停止する理由を理解できていないと、「起動したはずのコンテナが見当たらない」とか「ターミナルが固まらないので起動に失敗したんだ」という勘違いに繋がってしまいます。

コンテナとプロセスについて

コンテナを起動する方法を学んだので、いくつかコンテナを起動して次はプロセスについて確認してみます。

例1: Ubuntu コンテナをデフォルト命令 ( bash ) で起動

Ubuntu コンテナを起動し、デフォルト命令の bash を使っている状態で ps コマンドでコンテナ内のプロセス一覧を確認すると、PID1bash になっています。

また ps 自身もプロセスとして存在します。

Host Machine
$ 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 サーバが起動している状態では、PID1nginx の起動コマンドになっています。

ps 自身と ps を実行するために container exec で起動した bash のプロセスも存在します。
( container exec は【 2部: コンテナに接続する 】で説明します )

Host Machine
$ 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 ) で起動している状態では、PID1bash になっています。

また ps のプロセスはありますが、nginx のプロセスはありません。

Host Machine
$ 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つのコマンドを実行するため に起動している
    • それはデフォルト命令か指定命令の どちらか で、PID1 になる
  • 複数のコンテナの PID = 1Linux の Namespace 機能により衝突しない

この本では便宜上 PID = 1 のプロセスを メインプロセス 、それを起動するコマンドを メインコマンド と呼びます。

コンテナはメインプロセスを実行するために起動する という点を押さえておくと、コンテナのことをよりスムーズに理解できるようになります。

たとえばコンテナが仮想サーバではなくただの1プロセスに見えてくると、「Ubuntu に PHP と MySQL と Apache を入れたコンテナを作ろう」ではなく「PHP と MySQL と Apache が必要だから3コンテナ作ろう」という発想に自然と変わります。

また、メインプロセスが終了したコンテナは自動で停止する という重要な点を理解できるようになります。

コンテナが停止するパターン

ここまでの前提知識を踏まえて、コンテナが停止する理由を大きく2つに分けて説明します。

  1. コンテナを停止する
  2. メインプロセスが終了する

コンテナメインプロセス のどちらかが先に終われば、もう片方も連動するということです。

どういうことが具体的に見ていきましょう。

1. コンテナを停止する

Nginx のコンテナをデフォルト命令 ( nginx ) で次の通りに起動します。

Host Machine
$ docker container run \
    --name nginx3      \
    --rm               \
    --detach           \
    nginx:1.21

起動した nginx は Web サーバなので、 メインプロセスは止まれと言うまで止まりません
メインプロセスは勝手に終了しないので、コンテナは停止か削除をするまで終了しません

image

停止済コンテナの削除や起動中コンテナの強制削除については、【 2部: コンテナの基礎操作 】で説明した通りです。

2. メインプロセスが終了する

こちらはさらに2つに分類して確認します。

2-A. メインプロセスを自分で終了するパターン

同じ Nginx のコンテナを指定命令 ( bash ) で次の通りに起動します。

Host Machine
$ docker container run \
    --name nginx4      \
    --rm               \
    --interactive      \
    --tty              \
    nginx:1.21         \
    bash

# do something

# do something

# exit

起動した bashexit できるので、メインプロセスはいつか終了します
メインプロセスが終了した場合、コンテナは連動して停止します

image

当然 bashexit より先にコンテナを停止することも可能です。

image

2-B. メインプロセスが自動で終了するパターン

最後に、また同じ Nginx のコンテナを指定命令 ( ls ) で次の通りに起動します。

Host Machine
$ docker container run \
    --name nginx5      \
    --rm               \
    nginx:1.21         \
    ls /etc/nginx

$

起動した ls は結果を表示するだけなので、メインプロセスは即時終了します
メインプロセスが即終了するので、コンテナも連動して即時停止します

image

コンテナが起動している瞬間は実質ないため、起動中のコンテナに強制削除を命じることはできません。

( 余談 ) 即時停止とバックグラウンド実行について

即時停止とバックグラウンド実行 ( --detach オプション ) と混同しないようにしましょう。

コンテナの状態やコンテナ起動の成否は container run の後にターミナルが固まったかどうかで判断してはいけません

安易な覚え方をしないように注意しましょう。

メインコマンド オプション ターミナル コンテナ メインプロセス 起動コマンドの実行結果
nginx 固まる 起動中 起動中 正常
nginx --detach 固まらない 起動中 起動中 正常
ls 固まらない 停止済 終了済 正常 ( 終了 )

まとめ

簡潔にまとめます。

  • コンテナは メインプロセス ( PID = 1 ) を実行するために起動する
  • コンテナが停止する理由は大きく分けて2つある
    • コンテナを停止する
    • メインプロセスが終了する
  • 即時停止とバックグラウンド実行 ( --detach オプション ) と混同しない

混乱してしまったときは立ち返ってみてください。

このページで作成したものの掃除

Host Machine
$ docker container rm --force \
    ubuntu1 nginx1 nginx2 nginx3 nginx4 nginx5