Docker イメージの働き - Docker User Guide


# Docker イメージの働き

Working with Docker Images - Docker Documentation
http://docs.docker.com/userguide/dockerimages/

[introduction](http://docs.docker.com/introduction/) では、Docker イメージの基本コンテナについて学びました。[前のセクション](http://docs.docker.com/userguide/dockerizing/)では、既に使っている Docker イメージを使いました。例として使ったのは、`ubuntu` イメージと `training/webapp` イメージです。

これまでは Docker のイメージを Docker ホストにダウンロードする方法をみてきました。もし対象となるイメージがホストに存在していなければ、レジストリからダウンロードします。デフォルトのレジストリは、[Docker Hub](https://hub.docker.com/) の公開レポジトリです。

このセクションでは、Docker イメージのより詳細について学びます。

* 自分の Docker ホスト上でローカルなイメージの管理と起動
* 基本イメージの作成
* イメージを [Docker Hub](https://hub.docker.com/) にアップロードする

## ホスト上のイメージの一覧

ローカルのホスト上で持っているイメージの一覧を作成しましょう。そのためには `docker images` コマンドを次のように実行します。

```
$ sudo docker images
REPOSITORY       TAG      IMAGE ID      CREATED      VIRTUAL SIZE
training/webapp  latest   fc77f57ad303  3 weeks ago  280.5 MB
ubuntu           13.10    5e019ab7bf6d  4 weeks ago  180 MB
ubuntu           saucy    5e019ab7bf6d  4 weeks ago  180 MB
ubuntu           12.04    74fe38d11401  4 weeks ago  209.6 MB
ubuntu           precise  74fe38d11401  4 weeks ago  209.6 MB
ubuntu           12.10    a7cf8ae4e998  4 weeks ago  171.3 MB
ubuntu           quantal  a7cf8ae4e998  4 weeks ago  171.3 MB
ubuntu           14.04    99ec81b80c55  4 weeks ago  266 MB
ubuntu           latest   99ec81b80c55  4 weeks ago  266 MB
ubuntu           trusty   99ec81b80c55  4 weeks ago  266 MB
ubuntu           13.04    316b678ddf48  4 weeks ago  169.4 MB
ubuntu           raring   316b678ddf48  4 weeks ago  169.4 MB
ubuntu           10.04    3db9c44f4520  4 weeks ago  183 MB
ubuntu           lucid    3db9c44f4520  4 weeks ago  183 MB
```

ここで表示されるのは、これまでの [user guide](http://docs.docker.com/userguide/) で作成したものです。
それぞれ、対象となるイメージを起動しようとした時、[Docker Hub](https://hub.docker.com/) からダウンロードしてきたものです。

この一覧では、３つの重要なイメージの情報が表示されています。

* どのレポジトリからのものか。例えば `ubuntu`
* 各々のイメージのタグ。例えば `14.04`
* イメージのイメージ ID

レポジトリは複数の種類のイメージを持っている可能性があります。私たちの `ubuntu` イメージの場合は、Ubuntu 10.04, 12.03, 12.10, 13.04, 13.10, 14.04 のように、私たちは複数のバージョンを扱っていることが分かります。各々のイメージはタグで識別することができ、次のように表示されます。

```
ubuntu:14.04
```

コンテナを実行しようとするとき、タグ付けされたイメージを指定するには、次のようにします：

```
$ sudo docker run -t -i ubuntu:14.04 /bin/bash
```

替わりに 12.04 のイメージを使って構築したい場合は、次のようにします：

```
$ sudo docker run -t -i ubuntu:12.04 /bin/bash
```

バージョンを明示して指定しない場合、例えば `ubuntu` とだけ指定した場合は、デフォルトで `ubuntu:latest` イメージを使用します。

注：私たちは常に特定のタグを付けたイメージの使用を推奨します。例えば `ubuntu:12.04` のようにです。これによって、イメージのどのようなバージョンが使われているか、常に厳密に分かるからです。

## 新しいイメージの取得

それでは、新しいイメージを取得するときはどうしたら良いでしょうか。Docker は、Docker ホスト上に存在しないあらゆるイメージを、自動的にダウンロードします。しかしながら、場合によってはコンテナを起動するのに少々の時間がかかってしまう場合があります。もし、予めイメージの事前読み込みをしたければ、`docker pull` コマンドを使って事前ダウンロードをすることが出来ます。それでは、`centos` イメージをダウンロードしてみましょう。

```
$ sudo docker pull centos
Pulling repository centos
b7de3133ff98: Pulling dependent layers
5cc9e91966f7: Pulling fs layer
511136ea3c5a: Download complete
ef52fb1fe610: Download complete
. . .
```

各々のレイヤのイメージがプルダウンされ、このイメージからコンテナを実行できるようになりましたので、イメージをダウンロードするために待つ必要はありません。

```
$ sudo docker run -t -i centos /bin/bash
bash-4.1#
```

## イメージの検索

Docker の特長の１つに、沢山の人が作成した様々な Docker イメージがあります。大部分は [Docker Hub](https://hub.docker.com/) にアップロードされています。これらのイメージは [Docker Hub](https://hub.docker.com/) のウェブサイトから検索する事が出来ます。

画像 http://docs.docker.com/userguide/search.png

または、`docker search` コマンドを使って、コマンドラインからイメージを検索することもできます。例えば、私たちが欲しいイメージは、ウェブアプリケーション開発のために Ruby と Sinatra がインストールされているものとします。私たちはイメージを `docker search` コマンドを使って `sinatra` という言葉を含むイメージを探すことができます。

```
$ sudo docker search sinatra
NAME                                   DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
training/sinatra                       Sinatra training image                          0                    [OK]
marceldegraaf/sinatra                  Sinatra test app                                0
mattwarren/docker-sinatra-demo                                                         0                    [OK]
luisbebop/docker-sinatra-hello-world                                                   0                    [OK]
bmorearty/handson-sinatra              handson-ruby + Sinatra for Hands on with D...   0
subwiz/sinatra                                                                         0
bmorearty/sinatra                                                                      0
. . .
```

実行すると `sinatra` という言葉を含む沢山のイメージの情報が表示されます。表示されるのは、NAME(イメージ名)、DESCRIPTION(説明)、STAR(スター数)（イメージがソーシャル上で有名である指標 - 利用者がイメージが好きなら "star" することができます）、そして、OFFICIAL (公式かどうか)、AUTOMATED(自動ビルド)の状態です。
公式レポジトリとは、[Stackbrew](https://github.com/dotcloud/stackbrew) プロジェクトによって構築と監視されたもので、[自動ビルド](http://docs.docker.com/userguide/dockerrepos/#automated-builds)された自動化されたレポジトリにあり、これによって、出所(source)とイメージの中身の安全性を確認します。

さて、利用可能なイメージの中から `training/sinatra` イメージを使う事を決めました。次に私たちは `ubuntu` のようなイメージ（base イメージまたは root イメージと呼んでいます）を使うため、２種類のイメージリポジトリを参照します。ベースイメージは Docker 社が構築し、提供しているものであり、有効性が保証されています。これによって、単語名から（イメージを）識別することができます。

私たちが選んだ `training/sinatra` イメージのように、ユーザイメージの探し方を見て来ました。ユーザイメージは、Docker コミュニティのメンバーに所属するもので、ユーザ自身によって管理されているものです。ユーザイメージを、ユーザ名のプレフィックス、ここでは `training` というユーザ名がイメージを作成したのかという情報を識別することができます。

## 私たちのイメージをもってくる(pull)

私たちは適切なイメージ `training/sinatra` を確認し、これで `docker pull` コマンドを使ってダウンロードすることができます。

```
$ sudo docker pull training/sinatra
```

これで、チームはこのイメージを使って、それぞれのコンテナを実行できるようになります。

```
$ sudo docker run -t -i training/sinatra /bin/bash
root@a8cb6ce02d85:/#
```

## 私たちのイメージの作成

チームでは `training/sinatra` イメージが有用であるとわかりましたが、イメージを私たちの欲しいものにするためには、いくつかの変更を加える必要があることがわかりました。

1. 私たちはイメージからコンテナの更新を行う事が出来、変更点をイメージにコミット出来ます。
2. 私たちはイメージの作成にあたり 'Dockerfile' を用いて細かな指示を行えます。

### コミットしたイメージの更新

イメージを更新するには、まず、更新したいイメージからコンテナを作成する必要があります。

```
$ sudo docker run -t -i training/sinatra /bin/bash
root@0b2616b0e5a8:/#
```

注：作成された `0b2616b0e5a8` というコンテナ ID を記録しておきます。この後すぐに使います。

実行しているコンテナの中で `json` gem をインストールしましょう。

```
root@0b2616b0e5a8:/# gem install json
```

作業が終わったら、`exit` コマンドを実行してコンテナから抜けます。

これで、私たちが欲しい変更を加えたコンテナが手に入りました。`docker commit` コマンドを対象のイメージに使う事で、このコンテナのコピーにコミットすることができます。

```
$ sudo docker commit -m="Added json gem" -a="Kate Smith" \
0b2616b0e5a8 ouruser/sinatra:v2
4f177bd27a9ff0f6dc2a830403925b5360bfe0b93d476f7fc3231110e7f71b1c
```

ここで `docker commit` コマンドを使いました。`-m` と `-a`、２つのフラグを指定しています。`-m` フラグは、バージョンコントロールシステムにコミットするような、コミットメッセージを明示できます。`-a` フラグは、更新に当たっての作者を指定するものです。

そしてまた、私たちが新しいコンテナの作る元も  `0b2616b0e5a8` のように指定します（コンテナ ID は先に記録したものです）。そして、イメージに次のように指定します。

```
ouruser/sinatra;v2
```

それでは詳細を見ていきましょう。`ouruser` は新しいユーザ名の指定で、このイメージを書いた人です。また、イメージに特定の名前も指定します。ここではオリジナルのイメージ名は `sinatra` です。最後にイメージに対するタグを `v2` と指定します。

それから、`docker images` コマンドを使うと、新しく `ouruser/sinatra` イメージが作成されます。

````
$ sudo docker images
REPOSITORY          TAG     IMAGE ID       CREATED       VIRTUAL SIZE
training/sinatra    latest  5bc342fa0b91   10 hours ago  446.7 MB
ouruser/sinatra     v2      3c59e02ddd1a   10 hours ago  446.7 MB
ouruser/sinatra     latest  5db5f8471261   10 hours ago  446.7 MB
```

新しく作成したイメージを元にコンテナを使うには、次のようにします。

```
$ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash
root@78e82f680994:/#
```

### `Dockerfile` からイメージを作成する。

`docker commit` コマンドを使うことは、イメージを拡張するための簡単な方法ですが、少々煩わしく、チーム間でイメージを開発プロセスにおいて共有するのは簡単ではありません。スクラッチで（ゼロから）新しいイメージを作る代わりに、私たちは `docker build` という新しいコマンドを使うことができます。

実行する為には `Dockerfile` を作成し、Docker に対してどのようにイメージを構築するかの命令セットを記述しています。

それでは、まずディレクトリを作成し、`Dockerfile` を置きましょう。

```
$ mkdir sinatra
$ cd sinatra
$ touch Dockerfile
```

それぞれの命令を含む新しいイメージの層を作成します。私たちの開発チームが、自分たち自身の Sinatra イメージを新しく作る場合の例を考えて見ましょう。

```
# This is a comment
FROM ubuntu:14.04
MAINTAINER Kate Smith <ksmith@example.com>
RUN apt-get -qq update
RUN apt-get -qqy install ruby ruby-dev
RUN gem install sinatra
```

それでは、'Dockerfile' は何をしているか見ていきましょう。各々の指示のプリフィクスは、命令文であり、大文字で書きます。

```
INSTRUCTION statement
命令        命令文
```

注：`#` をコメントとして表示する事ができます

最初の命令 `FROM` は、Docker に対してソースとなるイメージは何かを伝え、この場合は私たちは Ubuntu 14.04 イメージの上の新規イメージを基盤とする事を伝えます。

次に `MAINTAINER` 命令を使って、誰が新しいイメージを管理するのか明示します。

最後に、3つの `RUN` 命令を記述します。`RUN` 命令は、イメージの中で実行するコマンドを書きます。例えばパッケージをインストールするなど。ここでは APT キャッシュの更新を行い、Ruby と RubyGems をインストールした後、Sinatra gem をインストールします。

注：Dockerfile で[利用可能な命令は、もっと沢山あります](http://docs.docker.com/reference/builder)。

それでは、`Dockerfile` を使って、`docker build` コマンドによってイメージを構築してみましょう。

```
$ sudo docker build -t="ouruser/sinatra:v2" .
Uploading context  2.56 kB
Uploading context
Step 0 : FROM ubuntu:14.04
 ---> 99ec81b80c55
Step 1 : MAINTAINER Kate Smith <ksmith@example.com>
 ---> Running in 7c5664a8a0c1
 ---> 2fa8ca4e2a13
Removing intermediate container 7c5664a8a0c1
Step 2 : RUN apt-get -qq update
 ---> Running in b07cc3fb4256
 ---> 50d21070ec0c
Removing intermediate container b07cc3fb4256
Step 3 : RUN apt-get -qqy install ruby ruby-dev
 ---> Running in a5b038dd127e
Selecting previously unselected package libasan0:amd64.
(Reading database ... 11518 files and directories currently installed.)
Preparing to unpack .../libasan0_4.8.2-19ubuntu1_amd64.deb ...
. . .
Setting up ruby (1:1.9.3.4) ...
Setting up ruby1.9.1 (1.9.3.484-2ubuntu1) ...
Processing triggers for libc-bin (2.19-0ubuntu6) ...
 ---> 2acb20f17878
Removing intermediate container a5b038dd127e
Step 4 : RUN gem install sinatra
 ---> Running in 5e9d0065c1f7
. . .
Successfully installed rack-protection-1.5.3
Successfully installed sinatra-1.4.5
4 gems installed
 ---> 324104cde6ad
Removing intermediate container 5e9d0065c1f7
Successfully built 324104cde6ad
```

`docker build` コマンドを使う事によって、`-t` フラグで新しく `ouruser` に所属するイメージを作成し、`sinatra` という名前のレポジトリで、`v2` というタグを使用します。

また、私たちは `Dockerfile` を `.` で指示しており、これは現在のディレクトリにある `Dockerfile` を使うようにしています。

注：`Dockerfile` のパスを明示することもできます。

これで動作時の構築プロセスを見る事ができました。まず Docker が行っているのは、構築のコンテキスト（環境）をアップロードすることです。基本的に構築しようとしているディレクトリの中にコンテンツを置きます。これは Docker デーモンが実際にイメージを構築し、ローカルなコンテキストをそこに入れるために必要となるからです。

次に、`Dockerfile` の指示は、段階的に実行するのを見る事が出来ます。
新しいコンテナを構築する各々のステップに於いて、
コンテナの中に対して命令を出し、
そして、これまでみてきたような `docker commit` ワークフローのようにコンテナに対する変更をコミットします。
全ての命令が `324104cde6ad` というイメージに対して実行され（あるいは、タグ付けされて分かりやすい `ouruser/sinatra:v2`）、中間コンテナは削除されます。

これで、私たちは私たちの新規イメージからコンテナを起動できます。

```
$ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash
root@8196968dac35:/#
```

注：これは最短でイメージを作るための導入です。私たちは、利用可能な命令の全てを使っているわけではありません。更に多くの命令はガイドの後半でお見せしますし、あるいは、`Dockerfile` リファレンスを参照して、全ての命令に関する説明や例を読む事ができます。

## イメージにタグを付ける

コミットやビルド後でも、既存イメージに対するタグを追加することができます。そのためには `docker tag` コマンドを使います。それでは `ouruser/sinatra` イメージに対して新しいタグを付けます。

```
$ sudo docker tag 5db5f8471261 ouruser/sinatra:devel
```

`docker tag` コマンドにはイメージの ID を渡します、ここでは `5db5f8471261` であり、そこに私たちのユーザ名と、レポジトリ名（ここでは devel)という新しいタグを追加します。

`docker images` コマンドで新しいタグの情報を見てみましょう。

```
$ sudo docker images ouruser/sinatra
REPOSITORY          TAG     IMAGE ID      CREATED        VIRTUAL SIZE
ouruser/sinatra     latest  5db5f8471261  11 hours ago   446.7 MB
ouruser/sinatra     devel   5db5f8471261  11 hours ago   446.7 MB
ouruser/sinatra     v2      5db5f8471261  11 hours ago   446.7 MB
```

## Docker Hub にイメージを送る(push)

構築した新しいイメージは、`docker push` コマンドを使う事で、[Docker Hub](https://hub.docker.com/) に push することができます。これは、他人と共有したり、公開したりできますし、あるいは[プライベートなレポジトリ](https://registry.hub.docker.com/plans/)に送ることもできます。

## ホストからイメージを削除する

Docker ホストから `docker rmi` コマンドで、コンテナの使っているイメージを削除することもできます。

`training/sinatra` イメージがもう必要なければ、削除してみましょう。

```
$ docker rmi training/sinatra
Untagged: training/sinatra:latest
Deleted: 5bc342fa0b91cabf65246837015197eecfa24b2213ed6a51a8974ae250fedd8d
Deleted: ed0fffdcdae5eb2c3a55549857a8be7fc8bc4241fb19ad714364cbfd7a56b22f
Deleted: 5c58979d73ae448df5af1d8142436d81116187a7633082650549c52c3a2418f0
```

注：イメージをホストから削除するためには、ベースとして使っているコンテナが存在していない必要があります。

## 次のステップ

これまで、どのように個々のアプリケーションを Docker コンテナの中に構築するかを見て来ました。次は、どのように複数の Docker コンテナがスタックされているアプリケーションで、Docker を構築するかを学びます。

Go to [Linking Containers Together](http://docs.docker.com/userguide/dockerlinks).