Docker初めての人向け説明メモ

初めてDockerを使う人に説明するためにまとめたメモ。

# Dockerを使った開発の全体像

Dockerのドキュメントを読んでいると様々な用語が出てきて最初は戸惑うものの、Dockerを理解するには、

* Dockerコンテナ
* Dockerイメージ

この2つの用語だけ覚えられれば良い。（たぶん）

Dockerではホストマシン上にコンテナという単位の実行環境が作られてアプリケーションが実行される。（仮想マシン(Virtual Machine)との違いは後述するので、一旦はVMと似たようなものと理解するのがわかりやすい）

![Docker](https://qiita-image-store.s3.amazonaws.com/0/82022/a9a90de6-dc76-f2b9-03ae-a3c4d482189e.png)


(https://blog.docker.com/2016/09/4-biggest-questions-docker-vmworld-2016/ より)

DockerコンテナはDockerイメージを`run`することで作成される。

![docker2 (2).png](https://qiita-image-store.s3.amazonaws.com/0/82022/fbfbfd85-e120-6736-06dc-628192ad5744.png)

Dockerイメージは、基となるイメージをビルドして作成する。dockerコマンドを使って手動作成やDockerfileを書いてビルドする。

![docker3.png](https://qiita-image-store.s3.amazonaws.com/0/82022/2d83ae5c-6d85-1c6c-7090-e9eb18f00daa.png)

ベースとなるDockerイメージは、Docker Registryと呼ばれる場所にある。

Docker Registryは有名なものでDocker Hubがあり、Docker公式のDockerイメージはここにある。また、Dockerイメージを使いプライベートな領域に構築することも可能。それ以外にもAWS上のEC2 Container Registryなど様々なサービスがある。

Docker Registryから`pull`することでイメージを取得できる。

![docker4.png](https://qiita-image-store.s3.amazonaws.com/0/82022/25aad66a-512d-8668-3c3b-0db41b992eda.png)

ここで実際の運用を考えると、サーバで毎回ビルドするとデプロイに時間がかかってしまうため、ローカルマシンやCIサーバでビルドを行い、Docker RegistryにPushしておいたイメージを利用する。

![docker5.png](https://qiita-image-store.s3.amazonaws.com/0/82022/d582434f-87b4-f015-36cd-765a91c8b9c2.png)

ビルドマシンでPullしているイメージは通常はその会社の標準となるイメージをインフラチームなどがビルドして用意しておく。

以上、ざっくりとした全体概要。

ここで、Dockerfileはどのようなものか紹介する。

```Dockerfile
FROM ruby:2.3
COPY . /usr/src/app
RUN bundle install
EXPOSE 3000
ENTRYPOINT ["./bin/rails", "server", "-b", "0.0.0.0"]
```

内容は適当なので注意。`FROM`でベースとなるイメージを指定している。上記では、[DockerHub上のrubyイメージ](https://hub.docker.com/r/library/ruby/)を選択。

`build`を行うと、COPYやRUNなどのコマンドが順に実行され、Dockerイメージが作成される。`run`すると、ENTRYPOINTに書かれたコマンドがコンテナ上で実行される。

# コンテナとVMの違い

![Docker Containers vs VMs](https://i0.wp.com/blog.docker.com/wp-content/uploads/1-1.png?w=975&ssl=1)

VMはOSを含めて動作するのに対し、DockerコンテナではホストOSとカーネルを共有し、必要なライブラリやアプリのみがDockerコンテナに含まれる。そのため、VMと比較してオーバーヘッドが少なくなる。

[こちらの公式資料](https://goto.docker.com/docker-for-the-virtualization-admin.html)で数ページを使って説明しているのがわかりやすい。

# Dockerは何が良いのか

* VMと比べて軽量
    * OSを立ち上げる必要が無いため起動時間が非常に短く、不要なプロセスが立ち上がることもない
* 移植性が高い
    * ミドルウェア群まで含んでいるため、デプロイする環境によってアプリケーションが動かない可能性が少ない
* ~~イミュータブルである~~
    * ~~コンテナは常にDockerイメージから作られるため、状態を保持することができず、自然とイミュータブルになる~~
    * **→ [コメント欄](http://qiita.com/miyasakura_/items/87ccb6d4a52d4a00a999#comment-160ad7faceceafbaef53)で指摘がありました。イミュータブルインフラストラクチャと相性が良い、という表現が正しそうです**

# Docker関連の用語

Dockerを触っていると出てくる用語を簡単に。

## Docker デーモン

dockerコマンドは、コマンド自体（client）とそれを受け取るDockerデーモン(server)という構成になっていて、`run`や`build`というコマンドを受け取ったDockerデーモンが実際の処理を行っている。そのため各マシン上ではDockerデーモンが動作している。

## Docker Machine

Docker Machineは、Dockerの実行環境を構築、管理をするツール。EC2やVirtualBoxなどの対象を指定して、そこにDockerが動作する環境を作ることができる。

以前DockerはLinuxでしか動作しなかったため、MacやWindowsではDocker MachineでVirtualBox上に環境を作り、その上でDockerデーモンやDockerエンジンを動かしていました。

現在は各プラットフォームにネイティブ対応しているため、ローカル実行の際にはDocker Machineは使われない。ただし、古いOSを利用している場合にはDocker Machineを使うことになる。

## Swarm mode

Docker Engineのクラスタはswarmと呼ばれ、それを管理するのが[Swarm mode](https://docs.docker.com/engine/swarm/)である。

以前はDocker Swarmという独立のツールを利用していたが、v1.12からDocker Engineに組み込まれたSwarmkitのSwarm modeを使うことが推奨されている。

また、Swarm以外にもクラスタリングを行う方法として、Google Kubernetes, Amazon EC2 Container Service(ECS)などでクラスタリングを行うこともできる。

## Docker Compose

Dockerコンテナは通常1プロセスを立ち上げて利用するため、複数の機能を提供する場合、いくつかのコンテナが協調して動作する必要がある。

それを簡単にするのがDocker Composeである。`Dockerfile`に加えて、 docker-compose.ymlを書くことで複数のコンテナを組み合わせることが簡単になる。

＃少し前にドキュメントを読んだときはDevelopment向けに作っていてでProductionは今のところ目的にしてない、と書かれていたが、今見るとその記述は無くなっていた

# 更にDockerを学ぶ

今回の記事は本当に概要だけで、実際に運用するには足りていない。

* [公式ドキュメント](https://docs.docker.com/)を読みつつ実際に触る
* 書籍を読む

など勉強する必要がある。この１年でも大きく技術が進化しているため、常にキャッチアップし続ける必要がある。読んだ書籍の中では、[プログラマのためのDocker教科書](http://www.shoeisha.co.jp/book/detail/9784798141022)が一番詳しくかつわかりやすかった。