Docker コンテナのライフサイクル : 「終了」と「破棄」は違う

以前の記事で、Docker コンテナについて、次のように書いた。

実は、この表現は正しくない。$$ exit による終了 = 即全てのデータが破棄される、というワケではなく、コレはただ「コンテナを終了させただけ」なのだ。

「でもその後 $ docker run コマンドをもう一回叩くと、データ残ってないんだけど…?」と思うかもしれない。

今回は、コンテナの「生成」→「起動」→「終了」→「破棄」 というライフサイクルを確認してみよう。

目次

実際にやってみる

実際にコマンドを叩いて順を追って確認してみよう。

# まずはコンテナを生成・起動する
$ docker run -it centos:7 bash

# ホスト名を確認する。Docker が生成したランダムなホスト名が見える
[root@038be9cb96b3 /]# hostname
038be9cb96b3

# exit で抜ける
[root@038be9cb96b3 /]# exit

# 同じコマンドでコンテナを生成・起動する → 別の環境が立ち上がる
$ docker run -it centos:7 bash

# その証拠に、ホスト名が異なる
[root@ded8c658767b /]# hostname
ded8c658767b

# exit で抜ける
[root@ded8c658767b /]# exit

ココまでで何が起こっているかというと、「1つの Docker イメージ」を基に「2つの Docker コンテナ」を生成して、別々に保持している状態なのだ。物理的な比喩で言うと、「1つの CentOS のインストールディスク」を用いて「2つの CentOS サーバを立てて、両方の電源を切った」状態、といえる。

「Create (新規生成)」と「Start (起動)」がセットになっているのが docker run コマンドである。

終了したコンテナはどこにあるの?

ココで疑問なのは、一度 exit で抜けて終了させたコンテナはどこにあって、どうやったらまたアクセスできるの? ということだ。多分最初はコレが一番分かりにくいのだと思う。

一つのターミナルで Docker コンテナにアクセスしている間に、別のターミナルを開いて $ docker ps と叩くと、起動中のコンテナが確認できる。

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
ede6d077be0c        centos:7            "bash"              22 minutes ago      Up 1 second                             silly_hamilton

一方、exit で抜けて終了した Docker コンテナは、$ docker ps --all コマンドで確認できる。

# `--all` は `-a` と省略できる
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
ded8c658767b        centos:7            "bash"              23 minutes ago      Up About a minute                               silly_hamilton
038be9cb96b3        centos:7            "bash"              25 minutes ago      Exited (0) 24 minutes ago                       hardcore_poitras

終了させたコンテナはココにいた。

終了させたコンテナにもう一度アクセスしたい (アタッチ)

じゃあ、これらのコンテナにアクセスするにはどうしたらいいの? という話。

まずは、この状態ではコンテナが終了しているので、再度起動させる。$ docker start コマンドを使い、先程のコマンドで確認できた CONTAINER ID を指定すれば、そのコンテナがまた起動できる。

$ docker start 038be9cb96b3
038be9cb96b3

で、起動したコンテナにアクセスすることを「アタッチ」と表現するのだが、$ docker attach コマンドで、またシェルにログインできる。

$ docker attach 038be9cb96b3
[root@038be9cb96b3 /]# hostname
038be9cb96b3

このとおり。

コンテナを起動させたまま抜ける (デタッチ)

起動中のコンテナに入るのを「アタッチ」と呼ぶが、反対に、入っているコンテナから抜け出すことは「デタッチ」という。デタッチはコンテナ内部で行うので、docker コマンドではなく、Ctrl + PCtrl + Q と入力する。

# アタッチ
$ docker attach 038be9cb96b3
[root@038be9cb96b3 /]# hostname
038be9cb96b3

# デタッチ : Ctrl + P → Ctrl + Q と入力する
[root@038be9cb96b3 /]# read escape sequence

# デタッチしただけだとコンテナは終了していないので、`docker ps` で見える
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
038be9cb96b3        centos:7            "bash"              29 minutes ago      Up About a minute                       hardcore_poitras

終了したコンテナが溜まっていく…「破棄」はどうするの?

こうした挙動を認識しておらず、バンバン $ docker run しまくっていると、裏側には「終了したまま放置されているコンテナ」がゴミとして残ることになる。

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                        PORTS               NAMES
e02b7b30296f        centos:7            "/bin/bash"         23 seconds ago      Exited (0) 22 seconds ago                         sad_pasteur
0552478e9e44        centos:7            "/bin/bash"         35 seconds ago      Exited (0) 34 seconds ago                         practical_rosalind
ded8c658767b        centos:7            "bash"              34 minutes ago      Exited (137) 11 minutes ago                       silly_hamilton
038be9cb96b3        centos:7            "bash"              36 minutes ago      Up 8 minutes                                      hardcore_poitras

このままだと、それぞれのコンテナは前述の方法で再起動できるワケだが、これらを完全に削除して、本当にデータを破棄するには、$ docker rm コマンドを使う。

$ docker rm e02b7b30296f
e02b7b30296f

こんな風にすると、破棄 = 削除できる。

試行錯誤している最中はいいとして、一段落したら、このようにゴミコンテナが残っていないか確認するといいだろう。

以上

コンテナをバンバンとっかえひっかえできるのはサーバ運用としてはメリットかもしれないが、どうも個人がコマンドラインから使っている範囲だと、分かりづらいように感じる。

自分の用途に応じて、コンテナのライフサイクルを意識して適宜エイリアスを作ったりすると良いかと思う。