コンテナの働き - Docker User Guide

Working with Containers - Docker Documentation
http://docs.docker.com/userguide/usingdocker/

# コンテナの働き

Docker User Guide の最後のセクションで、私たちは初めてのコンテナを起動しました。２つのコンテナを `docker run` コマンドで起動しました。

* フォアグラウンドで双方向的に実行するコンテナ
* バックグラウンドでデーモン化されたコンテナ

これまで、私たちはいくつかの Docker コマンドについて学びました。

* `docker ps` - コンテナの一覧
* `docker logs` - コンテナの標準出力を表示
* `docker stop` - 稼働しているコンテナの停止

注：`docker` コマンドを学ぶ別の方法として、[interactive tutorial](https://www.docker.com/tryit/) があります。

`docker` クライアントは、きわめてシンプルです。Docker を使って行える個々のアクションはコマンドによるもので、各々のコマンドは、いくつかのフラグや引数を持つことができます。

```
# Usage:  [sudo] docker [flags] [command] [arguments] ..
# Example:
$ docker run -i -t ubuntu /bin/bash
```

この動作をみるために、`docker version` コマンドを使い、現在インストール済みの Docker クライアントとデーモンのバージョン情報を取得しましょう。

```
$ sudo docker version
```

このコマンドは、使用している Docker クライアントとデーモンのバージョンだけでなく、Go（Docker を動かしているプログラミング言語）のバージョンも表示します。

```
Client version: 0.8.0
Go version (client): go1.2

Git commit (client): cc3a8c8
Server version: 0.8.0

Git commit (server): cc3a8c8
Go version (server): go1.2

Last stable version: 0.8.0
```

### Docker クライアントは何が出来るのかを見る

`docker` バイナリに何も付けずに実行すると、Docker クライアントを使って利用可能な全てのコマンドを見る事ができます。

```
$ sudo docker
```

そうすると、利用可能なコマンドが表示されます。

```
Commands:
     attach    Attach to a running container
     build     Build an image from a Dockerfile
     commit    Create a new image from a container's changes
. . .
```

### Docker コマンドの使い方を見る

特定の Docker コマンドに関する使い方の詳細を見る事もできます。

典型的なものは、`[コマンド]`を使ったコマンドの表示です。

```
$ sudo docker attach
Help output . . .
```

`docker` バイナリに対しては `--help` を付ける事も出来ます。

```
$ sudo docker images --help
```

実行するとヘルプ説明と、全ての利用可能なフラグが表示されます:

```
Usage: docker attach [OPTIONS] CONTAINER

Attach to a running container

  --no-stdin=false: Do not attach stdin
  --sig-proxy=true: Proxify all received signal to the process (even in non-tty mode)
```

これまで実行してきたコンテナは、特に役立つ働きをしませんでした。そこで、Docker を使ってウェブアプリケーションを実行する例を通して、構築することを経験しましょう。

注： Docker の全コマンド一覧は、[ここ](http://docs.docker.com/reference/commandline/cli/)に書かれています


## Docker でウェブアプリケーションを動かす

それでは、これまで `docker` クライアントについて学んできましたが、より重要な事を学んでいきましょう。それは、より多くのコンテナを実行する事です。これまで私たちが実行したコンテナのほとんどは、どれも特に役に立つような何かを実行するものではありませんでした。それで、Docker を使ってウェブアプリケーションを実行する例を通して、構築を経験しましょう。

ウェブアプリケーションとしては、Python Flask アプリケーションを使います。`docker run` コマンドから始めましょう。

```
$ sudo docker run -d -P training/webapp python app.py
```

私たちがどのようなコマンドを実行したか精査しましょう。`-d` と `-P` の２つのフラグを実行しました。`-d` は既出のフラグで、Docker に対してコンテナをバックグラウンドで実行するように命令します。`-P` フラグは新しいもので、Docker に、コンテナが何かしら必要なポートを、ホストに対してマップ（割り当て）するよう命令します。ここではウェブアプリケーションを見ていきましょう。

ここで指定したイメージは `training/webapp` です。このイメージは私たちが予め作っておいたコンテナで、単純な Python Flask ウェブアプリケーションが含まれています。

最後で、私たちはコンテナに実行命令 `python app.py` を指定しました。これで私たちのウェブアプリケーションが起動します。

注: `docker run` コマンドについて、より多くの詳細を知りたい場合は、[command reference] (http://docs.docker.com/reference/commandline/cli/#run) と、[Docker Run Reference] (http://docs.docker.com/reference/run/) をお読みください。


## Viewing our Web Application Container

これで実行しているコンテナを `docker ps` コマンドによって見る事ができます。

```
$ sudo docker ps -l
CONTAINER ID  IMAGE                   COMMAND       CREATED        STATUS        PORTS                    NAMES
bc533791f3f5  training/webapp:latest  python app.py 5 seconds ago  Up 2 seconds  0.0.0.0:49155->5000/tcp  nostalgic_morse
```

ここでは `docker ps` コマンドに対して、新しいフラグ `-l` が指定されていることが見えます。これは、`docker ps` コマンドへ、最後に起動したコンテナの詳細を返すようにするものです。

注：`docker ps` コマンドは、起動中のコンテナ情報のみを表示します。停止したコンテナの情報も参照したい場合は、`-a` フラグを使います。

アプリケーションの Docker 化で見てきたような詳細情報に加え、重要な `PORTS` 列が追加されています。

```
PORTS
0.0.0.0:49155->5000/tcp
```

`-P` フラグを `docker run` コマンドに渡すと、Docker は、イメージからホストに対して公開されているポートを割り当てます。

中：どのようにポートの公開するかの詳細については、[we learn how to build images](http://docs.docker.com/userguide/dockerimages) で学びます。

この場合は、Docker はポート 5000 （デフォルトの Python Flask ポートです）をポート 49155 上に公開しました。

ネットワークのポート割り当ては、Docker では常に変更可能なものです。この例では `-P` フラグは、`-p 5000` へのショートカットであり、ローカルの Docker ホスト上の high port (範囲は 49000 ～ 49900) を、コンテナの中のポート 5000 に割り当てるものです。Docker コンテナに対して、`-p` フラグを使用して割り当てるポート番号を明示することも出来ます。

```
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
```

これは、ローカルホスト上のポート 5000 を、コンテナ内部の port 5000 にマップ（割り当て）します。もしかしたら、次のように訊ねようとしているかもしれません。どうして 1:1 のポートマップを Docker コンテナに使うのではなく、high port を常に使うのでしょうか？と。これは、1:1 のマッピングを行おうとすると、ローカルホスト上において、１つしか割り当てられないという制約が起こってしまいます。たとえば、2 つのアプリケーションをテストしたいとします。いずれもコンテナ内部ではポート 5000 を使用しています。Docker のポートマッピングがないと、一度に１つのコンテナしかアクセスできません。

では、ウェブブラウザからアプリケーションに対して、ポート 49155 で見てみましょう。

![](http://docs.docker.com/userguide/webapp1.png)

このように、私たちの Python アプリは動いています！

メモ：OS X 上で boot2docker を使うならば、ローカルホストを使う代わりに、仮想ホストの IP アドレスを取得する必要があります。

```
$ boot2docker ip
The VM's Host only interface IP address is: 192.168.59.103
```

この例では、http://192.168.59.103:49155 としてアクセスします。

## ネットワークポートのショートカット

'docker ps' コマンドを使って戻り値から割り当てられているポートを見つけるのは、少々扱いにくいです。そこで Docker には 'docker port' というショートカットがあります。'docker port' を使うと、コンテナ名や ID を指定して、対象のコンテナのポートが、公開ポートのどこに割り当てられているか知ることができます。

```
$ sudo docker port nostalgic_morse 5000
0.0.0.0:49155
```

この例では、コンテナ内のポート 5000 が、外部の何番ポートに割り当てられるか分かります。

## ウェブアプリケーションのログを表示

アプリケーションで何が起こっているかをみていきましょう。これまでに学んだ `docker logs` コマンドを使います。

```
$ sudo docker logs -f nostalgic_morse
* Running on http://0.0.0.0:5000/
10.0.2.2 - - [23/May/2014 20:16:31] "GET / HTTP/1.1" 200 -
10.0.2.2 - - [23/May/2014 20:16:31] "GET /favicon.ico HTTP/1.1" 404 -
```

今回は新しく `-f` というフラグを使いました。`docker logs` コマンドに対して `tail -f` コマンドを付けると、コンテナの標準出力を参照します。ここでは、ポート 5000 で動作しているアプリケーションである、Flask に対するアクセスを表示するログを見ることが出来ます。

## アプリケーションコンテナのプロセスを見る

コンテナのログに加え、内部で稼働しているプロセスを `docker top` コマンドによって動作状況を確認できます。

```
$ sudo docker top nostalgic_morse
PID                 USER                COMMAND
854                 root                python app.py
```

ここにあるように、`python app` コマンドのみがコンテナ内部で動作していることがわかります。

** Web アプリケーションコンテナの調査

最後に、Docker コンテナに低レベルでアクセスするには、`docker inspect` コマンドを使います。Docker コンテナの便利な構成情報やステータス情報を JSON ハッシュの戻り値で確認できます。

```
[{
    "ID": "bc533791f3f500b280a9626688bc79e342e3ea0d528efe3a86a51ecb28ea20",
    "Created": "2014-05-26T05:52:40.808952951Z",
    "Path": "python",
    "Args": [
       "app.py"
    ],
    "Config": {
       "Hostname": "bc533791f3f5",
       "Domainname": "",
       "User": "",
. . .
```

そうすることで、特定の欲しい要素に関する情報を返すことも出来ます。たとえば、コンテナが使用しうる IP アドレスの情報です。

```
$ sudo docker inspect -f '{{ .NetworkSettings.IPAddress }}' nostalgic_morse
172.17.0.5
```

## ウェブアプリケーションコンテナの停止

これまではウェブアプリケーションの動作を見て来ました。次は、`docker stop` コマンドを使って `nostalgic_morse` という名前のコンテナを停止します

```
$ sudo docker stop nostalgic_morse
nostalgic_morse
```

それから `docker ps` コマンドで確認すると、コンテナが停止していることが分かります。

```
$ sudo docker ps -l
```

## ウェブアプリケーションコンテナの再起動

さて、停止したコンテナは他の開発者が使うだろうと書いてきました。ここでは２つの選択肢があります。新しいコンテナを作成するか、古いコンテナを再起動するかです。それでは、以前のコンテナを差し戻す方法をみていきましょう。

```
$ sudo docker start nostalgic_morse
nostalgic_morse
```

ここで素早く `docker ps -l` を再び実行すると、バックアップしていたコンテナが稼働して、コンテナの URL で数秒程度で見えるようになります。

注意：`docker restart` コマンドを使うと、対象コンテナの停止と起動を行います。

## ウェブアプリケーションコンテナの削除

同僚から作業が終わったので、もうコンテナを使わなくなったと連絡がありました。次は、`docker rm` コマンドを使って削除しましょう。

```
$ sudo docker rm nostalgic_morse
Error: Impossible to remove a running container, please stop it first or use -f
2014/05/24 08:12:56 Error: failed to remove one or more containers
```

何が起こったでしょうか？ 実際にはコンテナを削除できません。間違って動いているコンテナを削除出来ないよう、プロテクトがかかっています。まずコンテナを停止してから再度試します。

```
$ sudo docker stop nostalgic_morse
nostalgic_morse
$ sudo docker rm nostalgic_morse
nostalgic_morse
```

これでコンテナは停止・削除されました。

注：削除したコンテナの情報は記憶されます。

## 次のステップ

これまでは [Docker Hub](https://hub.docker.com/) からイメージをダウンロードして使いましたが、次は自分自身でイメージを構築し、共有してみましょう。

Go to [Working with Docker Images](http://docs.docker.com/userguide/dockerimages).