Dockerコンテナのクリーンアップの実務経験

このチュートリアルでは、**Alibaba Cloud**上の**Dockerコンテナ**のクリーンアップを実践的に体験できます。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/docker-container-cleanup-tutorial_594334)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

#準備
このチュートリアルに従うには、Dockerが既にインストールされているAlibaba Cloud [Elastic Compute Service](https://www.alibabacloud.com/ja/product/ecs) (ECS)サーバーが必要です。方法がわからない場合は、[このチュートリアル](https://www.alibabacloud.com/blog/how-to-install-and-use-docker-on-ubuntu-16-04_470612?spm=a2c65.11461447.0.0.7fc4481fXXLcBc)を参考にしてください。

コンテナのクリーンアップについて学ぶために、クリーンアップするコンテナがいくつか必要です。

まず、[https://hub.docker.com/](https://hub.docker.com/?spm=a2c65.11461447.0.0.7fc4481fXXLcBc) からいくつかのイメージが必要です。

このチュートリアルでは、画像の中に何が入っているかは全く問題ではありません。このチュートリアルを完全に理解するためには、Nginx、Redis、Alpineの経験は必要ありません。

Redisはオープンソースのインメモリデータ構造ストアで、データベースやデータキャッシュとして使用されています。ほとんどのプログラミング言語は、メモリ内のデータにほぼ瞬時にアクセスすることで、プログラムを高速化するために使用することができます。

NGINXは無料でオープンソースの高性能HTTPサーバーです。

Alpine Linuxは5MBのLinuxディストリビューションで、dockerユーザーに非常に人気があります。

Alpine Linuxは、dockerアプリケーションのベースイメージとして使用されています。これは、アプリを実行するための小さなLinux環境を提供します。

シェルプロンプトで次のように入力して、これらの4つのイメージをコンピュータにダウンロードしてください。

```
docker pull hello-world:latest
docker pull nginx:mainline-alpine
docker pull redis:alpine
docker pull alpine:3.8
```

**docker pul**コマンドはレジストリからDockerイメージをダウンロードします。docker レジストリには Docker イメージのコレクションが含まれています。

デフォルトでは、docker pull コマンドは Docker Hub: [https://hub.docker.com/](https://hub.docker.com/?spm=a2c65.11461447.0.0.7fc4481fXXLcBc) から docker イメージをプル/ダウンロードします。

Dockerイメージは、実行中のコンテナを作成するために使用されます。Docker イメージには、特定のアプリケーションを実行するために必要なすべてのソフトウェアが含まれています。例えば、ダウンロードしたnginx:mainline-alpineイメージには、コンテナ内でNginxを実行するために必要なすべてのソフトウェアが含まれています。

**docker pull nginx:mainline-alpine**では、nginx:mainline-alpineはプル/ダウンロードしたいイメージの名前です。画像名はnginxです。

mainline-alpineはタグです。タグは同じイメージの異なるバージョンを区別するために使われます。例えば、Docker Hubのリポジトリにはnginx:centos、nginx:ubuntu、nginx:debian8、nginx:debian9のイメージがあります。どのイメージをダウンロードするかを正確に指定するためにタグを使用しています。

**docker pull alpine:3.8**の場合、3.8タグはバージョン番号を表しています。

実行します。

```
docker ps -a
```

期待される出力。

```
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```

新鮮なdockerインストールサーバーでこれを実行している場合は、実行中のコンテナがありません。

混乱させて、いくつかのコンテナを作成して片付けてみましょう。以下のコマンドを入力します。

```

docker run --name nginx -d  nginx:mainline-alpine
docker run --name redis -d  redis:alpine
docker run -d hello-world
docker run -d hello-world
docker run -d hello-world
```

docker runは、以前にダウンロードした静的イメージを実行コンテナに変えてくれます。

コンテナとは、dockerイメージのランタイム版のことです。コンテナには、実行中のプロセスを含む完全な実行環境だけでなく、Dockerイメージのすべてのソフトウェアが含まれています。

このチュートリアルではnginxやredisの機能は必要ありません。必要なのは、多様なコンテナの興味深いリストだけです。そうすれば、コンテナを選択的に停止したり削除したりする方法をよりよく学ぶことができます。

nginx と redis を停止してみましょう。hello-world コンテナはメッセージを表示して終了するだけです。すでに停止しているので、停止させる必要はありません。

```
docker stop nginx
```

```
docker stop redis
```

このコマンドを入力して、すべてのコンテナを一覧表示します。

```
docker ps -a
```

期待される出力

```
CONTAINER ID        IMAGE                   COMMAND                  CREATED              STATUS                          PORTS               NAMES

97f95b11260e        hello-world             "/hello"                 57 seconds ago       Exited (0) 44 seconds ago                           determined_payne
91f69bd08bf8        hello-world             "/hello"                 About a minute ago   Exited (0) About a minute ago                       xenodochial_wiles
6f7b53de6ad7        hello-world             "/hello"                 About a minute ago   Exited (0) About a minute ago                       pedantic_bartik
62919b9e6d84        redis:alpine            "docker-entrypoint.s?   About a minute ago   Exited (0) 3 seconds ago                            redis
49ca281f8a0c        nginx:mainline-alpine   "nginx -g 'daemon of?   2 minutes ago        Exited (0) 14 seconds ago                           nginx
```

```
The CONTAINER IDs you get when you run these commands on your computer will be different.
```

現在、5つのコンテナが停止しています。

使用できません。

```
docker container prune
```

このコマンドは停止している全てのコンテナをプルーニング/削除します。ここでは、まだ nginx と redis のログを見たいと仮定します。そのため、hello-world コンテナだけを慎重にプルーニングしなければなりません。

hello-world コンテナだけのリストを作成してみましょう。実行します。

```
docker ps -a | grep "hello-world"
```

grep は、hello-world というテキストを含む出力行のみを選択します。

grep はほとんどの Linux ディストリビューションに搭載されている Linux シェルユーティリティです。40年前に書かれました。

```
grep is used to search plain-text input for lines that match its search expression.

The __ docker ps -a __ lists all containers, the pipe symbol | sends this list to grep.   __  grep "hello-world" __ searches for the text __ hello-word __. grep only outputs the list of containers __ containing hello-word. __

Grep stands for: g/re/p (__g__lobally search a __re__gular expression and __p__rint)

In __ docker ps -a | grep "hello-world" __ grep searched the list of containers output by docker ps, and prints only the lines containing hello-world.

grep searches the input files for lines containing a match to a given pattern list. When it finds a match in a line, it copies the line to standard output (by default), or whatever other sort of output you have requested with options.
```

期待される出力

```
CONTAINER ID        IMAGE                   COMMAND                  CREATED              STATUS                          PORTS               NAMES

97f95b11260e        hello-world             "/hello"                 About a minute ago   Exited (0) About a minute ago                       determined_payne
91f69bd08bf8        hello-world             "/hello"                 2 minutes ago        Exited (0) About a minute ago                       xenodochial_wiles
6f7b53de6ad7        hello-world             "/hello"                 2 minutes ago        Exited (0) 2 minutes ago                            pedantic_bartik
```

完璧です。プルーニングしたいコンテナのリストが必要です。

代わりに実行することもできます。

```
docker ps -a | egrep --invert-match "redis|nginx"
```

-invert-matchはマッチングを反転させ、マッチングしていない行のみを選択します。-v は --invert-match のショートカットです。

"redis|nginx "は、redisまたはnginxを含むテキストのみを選択する正規表現です。ここで、パイプ記号の｜は、「または」を意味します。

ここで、egrepは、redisとnginxを含むテキストを除いた出力行のみを選択します。

ここではegrepを使用しています: このgrepは拡張正規表現をサポートしています。この場合、"redis|nginx "は拡張正規表現をサポートしています。

```
docker container __ rm __ = docker container __ remove __ / delete / prune
```

docker container rmのフォーマットは以下の通りです。

```
docker container rm [OPTIONS] CONTAINER [CONTAINER...]
```

docker コンテナ rm に渡すコンテナ ID のリストが必要です。

コンテナIDは出力の最初のフィールド番号です。 awk '{print $1}' は、渡された最初のフィールドだけを出力します。

AWKはテキスト処理のために設計されたプログラミング言語です。テキストデータを抽出したりフィルタリングしたりするのに使われます。ほとんどのLinuxディストリビューションにインストールされています。

AWKは1970年に作成されました。AWKの名前は作者のAlfred Aho, Peter Weinberger, Brian Kernighanの名字に由来しています。

awkとgrepはどちらもテキストをフィルタリングします。grepは入力された列を選択的に印刷することができません。これは awk だけが持っている機能です。そのため、grepとawkを使う必要があります。

**awk '{print $1}'**  は、渡された最初のフィールドだけを表示します。 awk のデフォルトでは、フィールドは空白文字で区切られていると仮定しています。awk '{print $1}' __を使用すると、ここではコンテナのIDを表示しますが、これはdocker ps -aの出力の最初のフィールド/列です。

実行します。

```
docker ps -a | grep "hello-world" | awk '{print $1}'
```

期待される出力

```


97f95b11260e
91f69bd08bf8
6f7b53de6ad7
```

3つのhello-worldコンテナをすべて削除してみましょう。以下のコマンドのいずれかを選択して実行します。

```
docker ps -a | grep "hello-world" | awk '{print $1}' | __ xargs docker container rm __
```

或いは

```
docker ps -a | egrep -v "redis|nginx"  | awk '{print $1}' | __ xargs docker container rm __
```

**xargs docker container rm**はコンテナIDを一つずつ受信して削除します。

期待される出力

```


97f95b11260e
91f69bd08bf8
6f7b53de6ad7
```

完璧です。 **docker container rm**には削除したコンテナIDが表示されています。

実行します。

```
docker ps -a
```

```
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS                     PORTS               NAMES

62919b9e6d84        redis:alpine            "docker-entrypoint.s?   4 minutes ago       Exited (0) 2 minutes ago                       redis
49ca281f8a0c        nginx:mainline-alpine   "nginx -g 'daemon of?   4 minutes ago       Exited (0) 2 minutes ago                       nginx
```

redis と nginx はまだ存在しています。

redis と nginx のログを調べて、それらのコンテナも削除できるようにしておきましょう。
dockerのログはコンテナのログを表示します。

```
docker logs redis
```

```


1:C 03 Oct 06:40:25.554 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 03 Oct 06:40:25.559 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 03 Oct 06:40:25.559 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
1:M 03 Oct 06:40:25.613 * Running mode=standalone, port=6379.
1:M 03 Oct 06:40:25.614 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 03 Oct 06:40:25.614 # Server initialized
1:M 03 Oct 06:40:25.614 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
1:M 03 Oct 06:40:25.615 * Ready to accept connections
1:signal-handler (1538548914) Received SIGTERM scheduling shutdown...
1:M 03 Oct 06:41:54.159 # User requested shutdown...
1:M 03 Oct 06:41:54.195 * Saving the final RDB snapshot before exiting.
1:M 03 Oct 06:41:54.233 * DB saved on disk
1:M 03 Oct 06:41:54.233 # Redis is now ready to exit, bye bye...
```

実行します。

```
docker logs nginx
```

何も表示されません。nginxコンテナも何も使っていませんでした。

ログの調査完了しました。これで全てのコンテナを削除することができます。

実行します。

```
docker container prune -f
```

```
Deleted Containers:
62919b9e6d844d6720301dd8be7d0dfb58defb593fe8e9fa1ea0984b7aa92baa
49ca281f8a0cdc3adaddd222a654c4e61b17861f3a20dd9b584d0073466c722d
Total reclaimed space: 0B
```

2つのコンテナIDが表示されています。これらのコンテナも削除されました。

実行します。

```
docker ps -a
```

期待される出力

```
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS                     PORTS               NAMES
```

予想通り、コンテナの稼働も停止もありません。

**概要**

まず、コンテナを削除するには、必要なテキストだけを grepping してから awk でコンテナ ID だけを選択する方法を学びました。

次にコンテナIDをxargs docker container rmに渡すと、渡されたコンテナが削除されます。

```
docker ps -a | grep "hello-world" | awk '{print $1}' | xargs docker container rm
```

代用します：

```
docker ps -a | egrep -v "redis|nginx"  | awk '{print $1}' | xargs docker container rm
```

#Docker Container Pruneを使用してコンテナーを削除

```
docker run -d hello-world
```

さらに2回実行して、3つのコンテナをクリーンアップするようにします。

```
docker run hello-world ; docker run hello-world
```

実行します。

```
docker container ls
```

実行中のコンテナしか表示されないので、何も表示されません。

実行します。

```
docker container ls -a
```


**-a**は全てのコンテナを表示します。

期待される出力

```
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                          PORTS               NAMES

60cc61444c0b        hello-world         "/hello"            45 seconds ago       Exited (0) 37 seconds ago                           pensive_albattani
e820b8032706        hello-world         "/hello"            About a minute ago   Exited (0) 51 seconds ago                           silly_lovelace
7e959fd100d0        hello-world         "/hello"            About a minute ago   Exited (0) About a minute ago                       fervent_kilby
```

`docker container prune` コマンドは停止しているコンテナをすべて削除します。

コマンド `docker container prune --force` は停止しているコンテナをすべて削除しますが、確認のためのプロンプトは表示されません。

実行します。

```
docker container prune -f
```

期待される出力

```
 Deleted Containers:
60cc61444c0b90c7f2b0ada1546c3913a93676bbb0ba0dfb1c9329268222df6d
e820b803270681be048b511d676af56e28778e92ef783a536a4272f7d9648bd6
7e959fd100d0a72311f25987a0d0b6d1960283f2b164e56c538baddad83e8446
```

総埋立面積：0B

3つのコンテナを削除しました。prune オプションの -f は --force のショートカットです。

#ラベルを使ったコンテナのプルーニング
ラベルは、関連するコンテナをグループ化するためにdockerで使用されます。そして、ラベルの値に基づいてそれを選択することで、コンテナを選択的に処理することができます。

コマンド docker container prune は、ラベルをフィルターとして使用したコンテナの削除をサポートしています。

現在サポートされているフィルタは以下の通りです。

until () - 指定されたタイムスタンプより前に作成されたコンテナのみを削除します。

label - 指定したラベルが付いている（label!=...の場合は付いていない）コンテナのみを削除します。

今回はラベルを使って3つのコンテナを作成してみましょう。

以下の3つのコマンドを実行します。

```
docker run -d --label hello-1 hello-world
docker run -d --label hello-2 hello-world
docker run -d --label hello-3 hello-world
```

docker ps -a コマンドはラベルを表示しません。ラベルを表示するには --format オプションを使う必要があります。

完全な --format のリファレンスは

[https://docs.docker.com/engine/reference/commandline/ps/#formatting]()

実行します。

```
docker ps -a --format 'table {{.Image}}\t{{.Labels}}\t{{.Command}}\t{{.Status}}'
```

期待される出力

```
IMAGE               LABELS              COMMAND             STATUS
hello-world         hello-3=            "/hello"            Exited (0) 1 minutes ago
hello-world         hello-2=            "/hello"            Exited (0) 1 minutes ago
hello-world         hello-1=            "/hello"            Exited (0) 1 minutes ago
```

実行してhello-1コンテナだけを選択的にpruneしてみましょう。

```
docker container prune --force --filter "label=hello-1”
```

期待される出力

```


Deleted Containers:
1aa4c41c7a5b164edb4bb08cec4ec8c9769fb3e7dc311c825321fc7f87989ea9
Total reclaimed space: 0B
```

コマンドを再実行します。

```
docker ps -a --format 'table {{.Image}}\t{{.Labels}}\t{{.Command}}\t{{.Status}}'
```

```

IMAGE               LABELS              COMMAND             STATUS
hello-world         hello-3=            "/hello"            Exited (0) 4 minutes ago
hello-world         hello-2=            "/hello"            Exited (0) 4 minutes ago
```

これで残りのコンテナは2つになりました。

この2つのコンテナを実行してプルーニングしてみましょう。

```
docker container prune -f
```

実行します。

```
docker ps -a
```

期待される出力

```

IMAGE               LABELS              COMMAND             STATUS
```

すべてのコンテナをプルーニングしました。ラベルは、特定のラベルで1つのコンテナを選択的にプルーニングするのに便利です。

複数のコンテナが同じラベルを共有している場合には、複数のコンテナをプルーニング
するのと同じように便利です。

#Docker ps フィルタリングのリファレンス
[https://docs.docker.com/engine/reference/commandline/ps/#filtering](https://docs.docker.com/engine/reference/commandline/ps/?spm=a2c65.11461447.0.0.7fc4481fXXLcBc#filtering) より

name:::コンテナ名

label::: キーまたはキーと値のペアを表す任意の文字列。または = のように表現される。

ancestor:::: 指定された画像を共有するコンテナをancestorとしてフィルタリングします。

volume:::指定されたボリュームまたはバインドマウントをマウントした実行中のコンテナをフィルタリングします。

network:::指定されたネットワークに接続されているコンテナをフィルタリングします。

publish or expose::: を実行しているコンテナをフィルタリングします。指定されたポートを公開または公開するコンテナをフィルタリングします。port[/protocol]で表現されます。



これら3つのコンテナは同じ祖先イメージを共有しています。hello-word:latest__は、このコマンド一つで簡単にプルーニングすることができました。

```
docker container prune --force --filter __ "ancestor=hello-word:latest" __
```

これら3つのコンテナが同じネットワークを使用している場合、例えば mytestnetwork__ のように、このコマンド一つで簡単にプルーニングできました。

```
docker container prune --force --filter __ "network=mytestnetwork" __
```

#終了ステータスを使用したコンテナのプルーニング
終了ステータスは、終了したコンテナ内のプロセスの成功ステータスを表します。

終了ステータスが0の場合、通常は成功を意味します（オペレーティングシステムやプログラミング言語では、終了ステータス0=成功）。

終了ステータスの特定の数値は、特定のプログラミング言語やプログラムで定義された値を持っています。例えば、404はNginxとApacheのウェブサーバでウェブページが見つからないことを意味します。

以下の123と9の終了ステータスは、単に乱数であり、異なる終了ステータスを持つコンテナをクリーンアップする方法を示すために使用されています。

以下のコマンドを実行して、4つの異なる終了ステータスコードを持つ5つのコンテナを作成します。

```
docker run -d alpine:3.8 /bin/sh -c 'exit 123'
docker run -d alpine:3.8 /bin/sh -c 'exit 9'
docker run -d alpine:3.8
docker run --name nginx -d  nginx:mainline-alpine
docker run --name redis -d  redis:alpine
```

以下を実行して、コンテナの一覧とステータスの終了コードを表示します。

```
docker ps -a
```

期待される出力

```
CONTAINER ID        IMAGE                   COMMAND                  CREATED              STATUS                            PORTS               NAMES

9d4163879e17        redis:alpine            "docker-entrypoint.s?   13 seconds ago       Up 3 seconds                      6379/tcp            redis
2754c6805252        nginx:mainline-alpine   "nginx -g 'daemon of?   26 seconds ago       Up 15 seconds                     80/tcp              nginx
ef02229f40da        alpine:3.8              "/bin/sh"                42 seconds ago       Exited (0) 30 seconds ago                             epic_nobel
857cf388b70c        alpine:3.8              "/bin/sh -c 'exit 9'"    59 seconds ago       Exited (9) 46 seconds ago                             peaceful_torvalds
8b084d95a2fb        alpine:3.8              "/bin/sh -c 'exit 12?   About a minute ago   Exited (123) About a minute ago                       pedantic_mirzakhani
```

nginxとredisが実行されていますが、まだ終了コードはありません。

では実行してみましょう。

```
docker ps -a --filter status=exited
```

期待される出力

```
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                            PORTS               NAMES

ef02229f40da        alpine:3.8          "/bin/sh"                About a minute ago   Exited (0) About a minute ago                         epic_nobel
857cf388b70c        alpine:3.8          "/bin/sh -c 'exit 9'"    About a minute ago   Exited (9) About a minute ago                         peaceful_torvalds
8b084d95a2fb        alpine:3.8          "/bin/sh -c 'exit 12?   2 minutes ago        Exited (123) About a minute ago                       pedantic_mirzakhani
```

**--filter status=exited**を指定してから、3つの終了したコンテナだけが表示されました。

```
docker ps -a --filter 'exited=0’
```

期待される出力

```
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                          PORTS               NAMES

ef02229f40da        alpine:3.8          "/bin/sh"           About a minute ago   Exited (0) About a minute ago                       epic_nobel
```

終了したコンテナは1つだけ表示されます。

実行します。

```
docker ps -a --filter 'exited=123’
```

期待される出力

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS               NAMES

8b084d95a2fb        alpine:3.8          "/bin/sh -c 'exit 12?   2 minutes ago       Exited (123) 2 minutes ago                       pedantic_mirzakhani
```

終了したコンテナが1つだけ表示されています:**exited status = 123**

終了ステータス=0のコンテナを削除してみましょう。

```
docker ps -a --filter 'exited=0' | awk '{print $1}' | xargs docker container rm
```

実行します。

```
ef02229f40da
Error: No such container: CONTAINER
```

実行します。

```
docker ps -a
```

期待される出力

```
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS                       PORTS               NAMES

9d4163879e17        redis:alpine            "docker-entrypoint.s?   4 minutes ago       Up 3 minutes                 6379/tcp            redis
2754c6805252        nginx:mainline-alpine   "nginx -g 'daemon of?   4 minutes ago       Up 4 minutes                 80/tcp              nginx
857cf388b70c        alpine:3.8              "/bin/sh -c 'exit 9'"    4 minutes ago       Exited (9) 4 minutes ago                         peaceful_torvalds
8b084d95a2fb        alpine:3.8              "/bin/sh -c 'exit 12?   5 minutes ago       Exited (123) 4 minutes ago                       pedantic_mirzakhani
```

exited=0 コンテナの削除に成功しました。

なぜエラーが出るのか:
Error: そのようなコンテナはありません。: CONTAINER

実行してみてください。

```
docker ps -a --filter 'exited=9' | awk '{print $1}’
```

期待される出力


```
CONTAINER
857cf388b70c
```

そのCONTAINERヘッダーが問題です。xargs docker container rm にはコンテナ ID のリストだけを渡すべきです。

問題を修正するには、grep: grep -v CONTAINERを使ってCONTAINERヘッダの行を削除してください。

-v は --invert-match のショートカットです。

実行します。

```
docker ps -a --filter 'exited=9' | awk '{print $1}' | grep -v CONTAINER
```

期待される出力


```
857cf388b70c
```

Success: CONTAINER ヘッダー行が表示されていません。

この2行は同じ結果になっています。

```
docker ps -a --filter 'exited=9' | awk '{print $1}' | grep -v CONTAINER
```

ここでは、docker psは、9つのステータスコードコンテナを終了したフィルタリング、awkは最初のフィールドを表示し、grepは、CONTAINERの単語を除外して行を選択します。

代わりに:

```
docker ps -a --filter 'exited=9' | grep -v CONTAINER | awk '{print $1}'
```

ここでは、docker psは9つのステータスコードコンテナをフィルタリングし、grepはCONTAINERという単語を除いた行を選択し、awkは最初のフィールドを表示します。

一般的には、最初にgrepで選択を行い、最後のステップとしてawkで必要なカラムだけを表示します。論理的には、grepで選択し、最後にawkで結果を表示するという流れの方が良いでしょう。

ステータス9が終了したコンテナを、エラーメッセージを表示させずに削除してみましょう。

実行：

```
docker ps -a --filter 'exited=9' | awk '{print $1}' | grep -v CONTAINER | xargs docker container rm
```

期待される出力


```
857cf388b70c
```

Success: コンテナが削除され、エラーは表示されません。

ステータス123が終了したコンテナを、エラーメッセージが表示されないように削除してみましょう。

実行：

```
docker ps -a --filter 'exited=123' | awk '{print $1}' | grep -v CONTAINER | xargs docker container rm
```

期待される出力

```
8b084d95a2fb
```

Success: コンテナが削除され、エラーは表示されません。

実行します。

```
docker ps -a
```

期待される出力

```
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS               NAMES

9d4163879e17        redis:alpine            "docker-entrypoint.s?   10 minutes ago      Up 10 minutes       6379/tcp            redis
2754c6805252        nginx:mainline-alpine   "nginx -g 'daemon of?   10 minutes ago      Up 10 minutes       80/tcp              nginx
```

nginxとredisだけがまだ動いています。

#ステータスのコンテナを削除：作成済み
コンテナが作成された状態で終わってしまうことがあります。これは、コンテナが何かのエラーで実行中の状態に入れなくなったときに起こります。

ここでは、起動時のランフェーズで意図的にエラーを発生させて、作成状態のコンテナを作成してみましょう。

実行:

```
docker run -d alpine:3.8  <span class=error>  zxgarbagez  </span>
```

期待される出力

```
cc00b62dcb5078fed6d9e3fc48a9e5e7a9f3ef11d6722073781c3f5054696889
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \" <span class=error> zxgarbagez </span>\": executable file not found in $PATH": unknown.
```

実行：

```
docker ps -a
```

期待される出力

```
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS               NAMES

cc00b62dcb50        alpine:3.8              "zxgarbagez"             28 seconds ago      Created                                 zealous_colden
9d4163879e17        redis:alpine            "docker-entrypoint.s?   17 minutes ago      Up 17 minutes       6379/tcp            redis
2754c6805252        nginx:mainline-alpine   "nginx -g 'daemon of?   17 minutes ago      Up 17 minutes       80/tcp              nginx
```

zxgarbagezのエラーで作成された状態になってしまいます。

このように作成されたコンテナだけをリストアップしてみましょう。

```
docker ps --filter status=created
```

期待される出力

```
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS               NAMES

cc00b62dcb50        alpine:3.8              "zxgarbagez"             28 seconds ago      Created                                 zealous_colden
```

status=created にあるコンテナをすべて削除してみましょう。

実行：

```
docker ps --filter status=created | awk '{print $1}' | grep -v CONTAINER | xargs docker container rm
```

期待される出力

```
cc00b62dcb50
```

削除されたときに表示されるコンテナの名前。

実行します。

```
docker ps -a
```

期待される出力

```
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS               NAMES

9d4163879e17        redis:alpine            "docker-entrypoint.s?   17 minutes ago      Up 17 minutes       6379/tcp            redis
2754c6805252        nginx:mainline-alpine   "nginx -g 'daemon of?   17 minutes ago      Up 17 minutes       80/tcp              nginx
```

nginxとredisだけがまだ動いています。

#ステータスでコンテナを削除します:一時停止
このセクションでは、コンテナを一時停止してから削除を試みます。

Dockerはコンテナ内の全てのプロセスを凍結/一時停止するためにcgroupsフリーザー機能を使用します。

cgroups フリーザー機能を使うと、コンテナ内のプロセスは気づかず、フリーズコマンドを防ぐことも無視することもできません。

実行:

```
docker run -d --name testme alpine:3.8 /bin/sh -c 'sleep 10m'
```

小さな alpine Linux ディストリビューションを使ってコンテナを起動します。/bin/sh コマンド ( /bin/bash の小型版) を使用しています。sleep コマンド (何もしない) を 10 分間実行します。これで、一時停止できるコンテナが起動しました。

実行:

```
docker pause testme
```

期待される出力

```
testme
```

```
docker pause showed the name of the container it just paused: testme
```

実行:

```
docker ps -a
```

期待される出力

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS               NAMES

637489e9b88d        alpine:3.8          "/bin/sh -c 'sleep 1?   14 seconds ago      Up 6 seconds (Paused)                            testme
```

一時停止状態になっていることに注意してください。

以下のコマンドを実行すると、同じ出力リストが得られます。

```
docker ps --filter status=paused
```

このコンテナを削除してみましょう。実行してみます。

```
docker ps --filter status=paused | awk '{print $1}' | grep -v CONTAINER | xargs docker container rm
```

期待される出力

```
Error response from daemon: You cannot remove a paused container 637489e9b88d5704b9e677ff26199a9fec41644d4310732943cab0a2c8b0d4a6. Unpause and then stop the container before attempting removal or force remove
```

出力を読んでみてください。実行してコンテナを停止してみましょう。

```
docker stop testme
```

期待される出力

```
testme
```

ttme が停止したことを示します。

一時停止したいコンテナが複数ある場合は、以下のようにして一気に停止させることができます。

```
docker ps --filter status=paused | awk '{print $1}' | grep -v CONTAINER | xargs docker container stop
```

これで一時停止状態のすべてのコンテナが停止します。

これでうまくいったかどうか調べてみましょう。
実行:

```
docker ps --filter status=stopped
```

期待される出力

```
Error response from daemon: Invalid filter 'status=stopped’
```

明らかに停止状態はありません。コンテナを停止すると終了状態になります。

コンテナの有効な状態の一覧: created, restarting, running, removing, paused, exited, or dead

今度は正しい状態である exited を使って、それがうまくいったかどうかを調べてみましょう。実行してみましょう。

```
docker ps --filter status=exited
```

期待される出力

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                            PORTS               NAMES

3e8fb9e2c41d        alpine:3.8          "/bin/sh -c 'sleep 1?   3 minutes ago       Exited (137) About a minute ago                       testme
```

成功しました。これが現在終了しているコンテナのリストです。このコンテナIDのリストをdocker container rmに渡して、これらのコンテナを削除してみましょう。実行します。

```
docker ps --filter status=exited | awk '{print $1}' | grep -v CONTAINER | xargs docker container rm
```

期待される出力

```
3e8fb9e2c41d
```

成功しました これで、1つだけ終了したコンテナが削除されました。自分で docker ps -a を実行すると、このコンテナがリストに表示されなくなりました。

一時停止していたコンテナは、一時停止した場所で再開できるようになりました。停止しているコンテナは、停止した場所で再起動することはできません。コンテナを再起動すると、最初から始まります。

まとめ: 一時停止したコンテナのプルーニング/削除はできない - 一時停止を解除してからコンテナを停止する必要がある。

#終了時にコンテナを削除する
すでに、hello world のコンテナは手動で削除・プルーニングしなければならないことがわかりました。

コンテナを --rm オプションで実行すると、コンテナが終了したときに自動的に削除されます。

これで実践的な体験をしてみましょう。そうすると、便利な --rm オプションを必ず使うことになるでしょう。

以下の3つのコマンドを実行して、3つのhello worldコンテナを作成します。

```
docker run -d --rm hello-world
docker run -d --rm hello-world
docker run -d --rm hello-world
```

を使ってコンテナの一覧を確認してみましょう。

```
docker ps -a
```
期待される出力。

```
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
```

終了したhello worldコンテナが表示されていません。rmはこれら3つのコンテナが終了すると自動的に削除します。クリーンアップの必要はありません。

これらのbash aliasesを定義してください。2つ目のaliasを使ってクイックテストを行うことができ、後のクリーンアップの手間を省くことができます。

alias dr='docker run'

alias drrm='docker run --rm'

bash のエイリアスは長いシェルコマンドの短縮版です。その目的は、長いコマンドを入力しないようにすることです。

#チュートリアルのクリーンアップ
このチュートリアルはここまでです。

以下のコマンドを実行して、使用しなくなった画像をすべて削除してください。

```
docker image rm hello-world:latest
docker image rm nginx:mainline-alpine
docker image rm redis:alpine
docker image rm alpine:3.8
```

#Dockerの全体的なクリーンアップ
もしかしたら、あなたの開発用 docker サーバーは混乱しているかもしれません。

すべてのコンテナを停止すべきかもしれません。

そんなときは、以下のような方法ですぐに実行できます。

```
docker stop $(docker ps -a -q) #stop ALL containers
```

```
docker ps -a -q builds a list of all container IDs - running and exited.
```

これらのIDをdocker stopに渡します。

すべてのコンテナが停止します。既に終了したコンテナに対してはエラーは表示されません。

すべてのコンテナを削除するには、次のように実行します。

```
docker rm -f $(docker ps -a -q) # remove ALL containers
```

#概要
これで、あなたの仕事にコンテナクリーンアップコマンドを適用して実験することができるようになりました。

安全のためのヒント: 常にコマンドを実行して、選択されたコンテナのリストを表示するようにしてください。その後、docker container rm を実行して、実際にコンテナを削除してください。

grep, awk, xargs はこのチュートリアルで幅広く使われています。これらのツールに慣れていない場合は、チュートリアルを読む価値があることがわかります。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*