Docker を理解する - Docker User Guide



# Docker を理解する

Understanding Docker - Docker Documentation
http://docs.docker.com/introduction/understanding-docker/

なぜ Docker なのでしょうか？

Docker は開発、移動、アプリケーションの実行を行うオープンなプラットフォームです。Docker はアプリケーションを速く届けるよう設計されています。Docker を使う事で、インフラ基盤からアプリケーションを切り離すことができるのと、インフラ基盤をアプリケーションを管理するように扱えます。Docker は、コードをより速く送り出し、速くテストし、速くデプロイし、コードを書いてコードを実行するサイクルを短くするのに役立ちます。

Docker は、これらを、作業手順（ワークフロー）とツールの組みあわせにより、軽量なコンテナ仮想化プラットフォームを提供し、アプリケーションの管理やデプロイに役立つものです。

Docker はその中核機能で、コンテナの中であれば、ほとんどのアプリケーションがセキュリティ的に分離されて実行する環境を提供します。分離とセキュリティの機能があるので、自分のホスト上に多くのコンテナを同時に動かすことができます。軽量な性質なので、ハイパーバイザによる余分な負荷をかけることなく、ハードウェアからより多くを得られます。

コンテナ仮想化を囲むツールとプラットフォームが、いくつかの手助けになります：

* Docker コンテナに、アプリケーション（そしてサポート・コンポーネント）を入れる
* チームでの更なる開発とテストのために、コンテナの配付と発送をする
* これらのアプリケーションを本番環境、ローカルのデータセンタやクラウドに配備（デプロイ）します。

## どのように Docker を使う事ができますか？

アプリケーションの迅速な移動

Docker は開発のライフサイクルを促進するのに申し分ありません。Docker は、アプリケーションとサービスを含むローカルなコンテナで、開発者が開発を行うことができるようになります。それにより、継続的な統合(? Contenious integration)と開発ワークフローとを統合することができるようになります。

たとえば、開発者はローカルでコードを書き込んで、それら開発スタックを Docker のコンテナを通して共有します。それらの準備ができると、それらのコードを push し、テスト環境に開発したものを積み上げて、必要なあらゆるテストを実施します。テスト環境から、Docker イメージを化プロダクションの所で展開することができます。

展開をより簡単に

Docker のコンテナを基盤としたプラットフォームによって、高く持ち運び可能な作業負担(workload)となります。Docker コンテナは、開発者のローカルホストで開発することができますし、データセンタの物理あるいは仮想マシンでも構いませんし、クラウド上でも走らせることができます。

Docker の移植性(portability)と軽量な性質によって、動的に作業負担をの管理を簡単にもします。Docker を使う事で、アプリケーションやサービスの迅速なスケールアップや引き下ろし(tear down)ができるようになります。Docker のスピードというのは、リアルタイムに近くスケールすることができうるという意味があります。

多くの作業負荷=workload(*)を高密度に実行する事を達成

Docker は軽量で高速です。現実的であり、費用対効果が良い選択肢を、ハイパーバイザー経由の仮想マシンに提供します。とりわけ、高密度環境で役に立ちます。たとえば、自分自身で構築したクラウドであったり、PaaS（サービスとしてのプラットフォーム）です。しかし、自分自身が持っているリースを有効活用しようとする、小中規模の開発環境にとっても役立つでしょう。

Docker の主要コンポーネントとは何か？

Docker は２つの主要コンポーネントがあります。

* Docker: オープンソースのコンテナ仮想化プラットフォーム
* Docker Hub: Docker コンテナを共有・管理するための SaaS プラットフォーム

メモ：Docker はオープンソースの Apache 2.0 ライセンスで提供されています。

## Docker の設計（アーキテクチャ）とは？

Docker はクライアント・サーバ型の設計です。Docker クライアントは Docker デーモンに対して話し、構築・実行・Docker コンテナの配付といった重荷を処理を行います。Docker クライアントとデーモンは、同じシステムで動作することができますし、Docker クライアントをってリモートの Docker デーモンに接続する事もできます。Docker クライアントとサービスは、ソケットや RESTful API を経由して通信できます。

画像リンク
http://docs.docker.com/article-img/architecture.svg


### Docker デーモン

上図で示すように、Docker デーモンはホストマシン上で動作します。利用者が直接デーモンとやりとりしないかわりに、Docker クライアントを用います。

### Docker クライアント

Docker クライアントは 'docker' バイナリの形であり、Docker へつなぐ第一のインターフェースです。ユーザが実行したコマンドに応じて、Docker デーモンとの通信を行ったり来たりします。

### Docker 内部

Docker の中身を理解するために、まず３つのコンポーネントを知っておく必要があります。

* Docker イメージ(images)
* Docker レジストリ(registries)
* Docker コンテナ(containers)

#### Docker イメージ

Docker イメージは、リードオンリー（読み込み専門）のテンプレートです。たとえば、あるクラウドのイメージに含まれるのは、Apache とウェブアプリケーションがインストールされた Ubuntu オペレーティングシステムです。イメージは Docker コンテナを作成するのに使います。Docker は新規イメージの更新、既存イメージのアップデートなど、他の人が既に作成している Docker イメージのダウンロードを行う、簡単な方法を提供します。Docker イメージは、Docker の構築コンポーネントです。

#### Docker レジストリ

Docker レジストリは、イメージを保持します。そこで、パブリックまたはプライベートなストア（保存場所）に、自分のイメージをアップロードしたり、ダウンロードすることができます。パブリック DOcker レジストリは Docker Hub という名前です。利用可能な既存のイメージの膨大なコレクションを提供します。自分自身でイメージを作成することもできますし、既に誰かが作成済みのイメージを利用することもできます。Docker レジストリは、Docker の配付コンポーネントです。

#### Docker コンテナ

Docker コンテナはディレクトリと似ています。Docker コンテナには、アプリケーションの実行に必要なすべてを保持します。各々のコンテナは Docker イメージから作成します。Dockr コンテナは、実行、開始、停止、移動、削除ができます。各々のコンテナは分離されて安全なアプリケーションのプラットフォームです。Docker コンテナは、Docker の実行コンポーネントです。


## では、Docker は何をするのでしょうか？

これまで、私たちは以下の事を学んできました；

1. アプリケーションを保持する Docker イメージを構築できます
2. アプリケーションを実行するために、Docker イメージから Docker コンテナを作成できます
3. Docker Hub や自分自身のレジストリを通して Docker イメージを共有できます

それでは、これらの要素が Docker の動作においてどのように結びついているかを見ていきます。

### Docker イメージの働きとは？

私たちは Docker イメージが、Docker コンテナを立ち上げるときの、リードオンリーのテンプレートであることを既に見て来ています。各々のイメージは、数層から構成されます。Docker は、単一のイメージにこれらの層を組みあわせるため、[union file system](http://en.wikipedia.org/wiki/UnionFS) を利用します。ユニオンファイルシステムは、ファイルとディレクトリをファイルシステムから分離するので（branches ＝分岐？として知られている）、透過的にオーバーレイ（上に覆う）する、単一の一貫性のあるファイルシステムを作ります。

Docker がとても軽量な理由の１つは、これらの層があるためとも考えられます。Docker イメージの変更を行うとき、例えば、アプリケーションを新しいバージョンにバージョンアップするときは、あたら意志レイヤを取得し、ビルドします。すなわち、マシンイメージの全てを（ゼロから）作り直すよりも、全体的な再建( entirely rebuilding ) であり、それらは仮想マシンだけで実行されるかもしれませんが、対象となる層だけが追加または更新されます。これで、新しい Docker イメージを作っても更新するだけで、Docker イメージを速く簡単に配付できるようになるので、どうやってその新しいイメージを配付するかを心配する必要はありません。

全てのイメージは基本イメージ(base image)から使い始めます。たとえば、`ubuntu` は、基本の(base) Ubuntu イメージであり、`Fedora` では、基本イメージは base Fedora イメージです。
新しいイメージ作成のための基礎として、自分自身のイメージを使うことができます。たとえば、基本の Apache イメージを持っているならば、あなたの全てのウェブアプリケーションイメージの base として、これを使う事もできます。

メモ；Docker は通常 Docker Hub から、これらの基本イメージを取得します。Docker イメージは、これらの base イメージ（基本イメージ）を用いて、簡単に、インストラクション（命令）と呼ぶステップをセットした記述によって構築できます。多くの instruction(命令) によって、私たちオンイメージの上に新しい層を作ります。命令には以下の様なアクションを含みます。

* コマンドを実行する
* ファイルやディレクトリの追加
* 環境変数の追加
* コンテナ起動時、対象イメージの中の何のプロセスを起動するか

これらの指示は、'Dockerfile' と呼ばれるファイルに保存されます。Docker は、イメージ構築時に、この 'Dockerfile' を読み込むことで、指示を実行し、最終的なイメージを戻します。

### Docker レジストリは、どう働きますか？

Docker レジストリは、自分の Docker イメージの保管場所です。一旦 Docker イメージを作ってしまえば、イメージをパブリックな Docker Hub レジストリに置くことができますし、自分自身のファイアウォール配下に置くこともできます。

Docker クライアントを使う事で、既に公開されているイメージを探し、そっらを手許の Docker ホストに持ってきて、これらのコンテナをビルドすることができます。

Docker Hub は、パブリックとプライベート両方のイメージ保管場所を提供します。パブリックなストレージは、誰でも検索やダウンロードができるものです。プライベートストレージの場合は、自分自身や自分ののユーザに対してのみ検索の結果、コンテナを構築することができます。ストレージの料金プランはについては、ここでサインアップしてください。

### コンテナの働きとは？

コンテナにはオペレーティングシステム、ユーザが追加下ファイル、そしてメタデータが含まれます。これまで見て来たように、各々のコンテナはイメージから構築されます。そのイメージが Docker に伝えるのは、どんなコンテナを保持するか、どんなプロセスを実行するか、いつコンテナを起動するか、そして様々な種類の設定データです。Docker イメージはリードオンリーです。Docker がイメージからコンテナを起動するときは、イメージの上に読み書き可能な層を追加し（これまで見て来た union file system を使います）、アプリケーションが実行可能になります。

### コンテナを実行する時、何が起こっているのか？

`docker` バイナリを使うか、API 経由どちらでも、Docker クライアントは Docker デーモンに対して、コンテナを実行する事を伝えます。

```
$ docker run -i -t ubuntu /bin/bash
```

このコマンドをブレイクダウン（分析）してみましょう。
Docker クラアントが起動されるのは、`docker` バイナリの `run` オプションにより、新しいコンテナを起動するときです。Docker クライアントがコンテナを実行するために Docker デーモンに伝える最小限のことは、以下の通りです。

* コンテナの構築を、どの Docker イメージから行うか。ここでの `ubuntu` は、base ubnutu image を使います。
* コンテナ起動時に内部で実行したいと思うコマンド。ここでは `/bin/bash` が、新しいコンテナの中で Bash シェルを起動することを意味します。

では、このコマンドを実行すると何が起こるでしょうか。

Docker は順番に次の通り実行します。

* 1ubuntu1 イメージの取得: Docker は `ubuntu1 イメージの存在を調べ、もしもローカルホストや存在しないのであれば、Docker は Docker Hub からダウンロードします。もしイメージが既に存在しているなら、Docker はそれを新しいコンテナ向けに使います。
* 新しいコンテナの作成: Docker が一度イメージを作成しておくと、そこから新しくコンテナを作成できます。
* ファイルシステムを割り当て、読み書き層をマウント: コンテナはファイルシステム上で生成され、イメージに読み書き層を追加します。
* ネットワークやブリッジインターフェースの追加: ネットワークインターフェースを作成し、Docker コンテナがローカルホストと通信できるようにします。
* IP アドレスのセット: プール上で利用可能な IP アドレスを探し、取り付けます
* 指定したプロセスを実行: アプリケーションを実行し、それから
* アプリケーションの出力を取得・提供:稼働しているアプリケーションに接続し、ログの標準入出力やエラーを見えるようにします。

これでコンテナが動きました！ここからは、コンテナを管理し、アプリケーションとやりとりを行い、終わったらコンテナを停止し、削除します。

## 基礎技術

Docker は Go で書かれており、これまで見て来た機能性を提供するために、いくつかの Linux kernel 技術を利用します。

### 名前空間(Namespaces)

我々がコンテナと呼ぶ絶縁した(isolated; 隔離は違う、分離が近い、寧ろ絶縁か)ワークスペースを提供するのに、`namespaces` (名前空間)と呼ばれる技術を Docker は使います。コンテナを実行させるとき、Docker は対象コンテナのための一組の名前空間を作成します。

これにより、層の分離（絶縁）ができるようになります：コンテナの各々の外観は、自分自身の名前空間ですが、外からアクセスできるものではありません。

Docker が使う名前空間は、以下の通りです

- `pid` ネームスペース: プロセスの分離 (PID: プロセス ID).
- `net` ネームスペース: ネットワークインターフェースの管理 (NET: ネットワーク).
- `ipc` ネームスペース: IPC リソースの管理(IPC: 内部プロセスにおける通信).
- `mnt` ネームスペース: マウントポイントのマッピング (MNT: マウント).
- `uts` ネームスペース: カーネルとバージョン識別の分離 (UTS: Unix タイムシェアリングシステム).

### コントロールグループ(Control groups)

Docker は `cgroups` や control groups と呼ばれる別の技術も用います。アプリケーションを分離して実行する為の鍵になるのは、必要とするリソースのみを割り当てることです。これにより、ホスト上において、望ましいマルチテナント利用者であることを保証します。コントロールグループは、Docker がコンテナが共有可能なハードウェアリソースを許可し、必要があれば、上限設定や制約を設けられます。たとえば、特定のコンテナに対して利用可能なメモリの上限を設定します。

### ユニオンファイルシステム(Union file systems)

ユニオンファイルシステムや UnionFS は、コンテナ層の操作が非常に軽量で速いファイルシステムです。コンテナがファイルシステムのブロックを使えるように、Docker はユニオンファイルシステムを使います。Docker は、以下を含むいくつかのユニオンファイルシステム系列が利用できます：AUFS, birtfs, vfs, DeviceMapper.

### コンテナ規格(format)

Docker はコンテナ規格(container format)と私たちが呼ぶラッパーと、これらのコンポーネントを組みあわせます。標準のコンテナ規格は `libcontainer` です。Docker は、LXC という伝統的な Linux コンテナもサポートします。将来的には、Docker は他のコンテナ規格をサポートするかもしれません。例えば、BSD Jails や Solaris ゾーンとの統合です。