DockerをMacに入れた。Docker設定メモ

## はじめに
現在`Docker`に対して造詣を深めようとしているところで、まだまだわかってない状況です。
その中で少しわかってきたのが、`Vagrant`とは違い`Docker`はイメージベースでやり取りをするためにある気がしました。

すなわち`Docker`は誰かが作ったスナップショットをもらって、その環境を使って仕事を行う事を目的をして使われる事が多いのではないかと思い始めました。

`Vagrant`+`Chef`の構成を容易にやり取りできる感じでしょうか？
`Chef`のレシピで細かいところまで設定すると仰々しくなり、汎用的に使えなくなります。
一方で`Docker`は元のイメージを複製して、イメージ内を変更して適した形にしたところでスナップショットを取って配布していくので汎用的に使えなくても問題がないという思想なのかなと思いました。

なので、今回は人が作ったイメージをMacで再現（再生？w）してみようと思います。

目標は[Dockerで即実行できる、社内・自宅向けオープンソースWebアプリ](http://qiita.com/y_hokkey/items/406b5a8c4bc15354d069)を起動する事です。

## 前回まで行った事
[前回](http://qiita.com/syou007/items/c497d1effc2fbb1464cb)行った事で重要なところだけピックアップします。
（前回の記事はメモ書きだったので、見てもわけがわからないと思うので・・・）

### 必要なモノをインストール
以下の二つを事前に入れておいてください。
もし`docker-machine`の設定済みだった場合飛ばしてください。

* VirtualBox
* HomeBrew

その状態で以下を入れます。

```sh
$ brew install docker docker-machine
```

これで`Docker`のVMを管理する`docker-machine`とコマンドを管理する`docker`が入りました。
念のため確認します。

```sh
$ docker -v
Docker version 1.8.1, build d12ea79h
$ docker-machine -v
docker-machine version 0.4.1 (HEAD)
```

次はVMを入れます。
`dev`はVMの名前なので、なんでも良さそうです。

```sh
$ docker-machine create --driver virtualbox dev
```

### 起動
入れたVMを起動します。
もし`docker-machine`の設定済みだった場合飛ばしてください。

```sh
$ docker-machine env dev
```

設定を追加します。

```sh
$ vi ~/.bash_profile 
# 一番最後に設定
eval "$(docker-machine env dev)"
# 反映
$ soruce ~/.bash_profile 
```

## docker-machineの各種コマンド

### IPアドレスの確認
```sh
$ docker-machine ip dev
192.168.99.100
```

### VMの確認
```sh
$ docker-machine ls
NAME   ACTIVE   DRIVER       STATE     URL                         SWARM
dev    *        virtualbox   Running   tcp://192.168.99.100:2376   
```

### VMへログイン
```sh
$ docker-machine ssh dev
```

### VMの起動/終了コマンド
```sh
# 起動
$ docker-machine start dev
# IPアドレスが変わるので、必要に応じて起動後に一度実行する。
$ docker-machine env dev
$ source ./bash_profile
# 終了
$ docker-machine stop dev
```

## Dockerの各種コマンド

### イメージ取得
```sh
$ docker pull ubuntu:latest
```

### イメージ起動
```sh
$ docker run centos:latest echo "Hello World"
```

`echo "Hello World"`はインストール後に行う命令。
イメージが無い場合は、ダウンロードして実行される。

```sh
$ docker run -it --name ubuntu1 ubuntu /bin/bash
```

取得したイメージを起動することができる。


#### 主な[オプション]

* -d：バックグラウンドで実行する（後述）。既定では、コンテナーをフォアグラウンドで実行するため、Webサーバーやアプリケーションサーバーなど常時実行するコンテナーで指定
* -i：コンテナーの標準入力を開く。/bin/bashなどでコンテナーを操作する際に指定
* -t：tty（端末デバイス）を確保する。/bin/bashなどでコンテナーを操作する際に指定
* -p ｛ホストのポート番号｝:｛コンテナーのポート番号｝：Dockerサーバーのホストとポートマッピングを構成

[ついに1.0がリリース！ Dockerのインストールと主なコマンドの使い方 (2/3)](http://www.atmarkit.co.jp/ait/articles/1406/10/news031_2.html)より引用。

### イメージ確認
```sh
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              latest              e9fa5d3a0d0e        7 weeks ago         172.3 MB
```

### コンテナ確認
```sh
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS                     PORTS               NAMES
93d9d73dff28        ubuntu              "/bin/bash"           3 minutes ago       Exited (0) 5 seconds ago                       ubuntu1
38f47d2577f6        centos:latest       "echo 'Hello World'"  3 hours ago         Exited (0) 3 hours ago                         mad_poitras
```

`NAMES`は指定しないと勝手につけられる。
今回の例では`mad_poitras`となってるので、以下の`mad_poitras`の部分については適時読み替えてください。

`-a`をつけない場合は起動しているコンテナだけを確認できる。

### コンテナに入る。
```sh
$ docker attach mad_poitras
```

初めのコマンドは見えないので、その場合は以下のコマンドで入れば見れる。
(@hidekuroさんに教えてもらいました。)

```sh
$ docker logs CONTAINER_NAME && docker attach CONTAINER_NAME
```

一度入り込んで抜けるとコンテナは止まってる。

### イメージの保存
Dockerを起動して中身を変更します。

```sh
$ docker start ubuntu1
$ docker attach ubuntu1
root@93d9d73dff28:/# apt-get install -y nginx
root@93d9d73dff28:/# dpkg -l nginx
root@93d9d73dff28:/# exit
```

変更内容をイメージに保存します。

```sh
$ docker commit ubuntu1 ubuntu/nginx
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu/nginx        latest              a3bbb2669586        7 seconds ago       206.1 MB
ubuntu              latest              e9ae3c220b23        3 weeks ago         187.9 MB
```

新しいイメージができてます。

#### 出来なかったことのメモ
上記のイメージを80番ポートフォワードでnginxコンテナを起動。

```sh
$ docker run -d -p 80:80 --name nginx1 ubuntu/nginx /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
$ curl localhost:80
# curl: (52) Empty reply from serverが出る場合はVMのポートフォワーディングを変更してください。
```

##### 注意
Macで上記を行う場合は[こちら](http://qiita.com/kochizufan/items/c6c1b12748a4e08fde3f)の設定が必要となる。


### コンテナの停止
```sh
$ docker stop mad_poitras
```

### コンテナ起動
```sh
$ docker start mad_poitras
```

### コンテナの削除
```sh
$ docker rm mad_poitras
```

### イメージの削除
イメージの削除はコンテナを全て削除しないと実施できない。

```sh
docker rmi e9fa5d3a0d0e
```

`e9fa5d3a0d0e`は`docker images`の`IMAGE ID`を指定する。

### イメージ検索
```sh
$ docker search ubuntu
```

## Dockerfileを使用
少し憂いがあるが、目標のために突き進む。

`Dockerfile`を使用するとあらかじめ設定した通りにイメージを作成してくれる。

```sh
$ mkdir nginx
$ cd nginx
$ vi Dokerfile
```

適当なディレクトリに`Dockerfile`を以下のように作成する。

```Dokerfile
FROM ubuntu
RUN apt-get install -y nginx
ADD index.html /usr/share/nginx/html/
```

上記の例ではあらかじめ`index.html`を`nginxディレクトリ`に作っておく必要がある。

### イメージを作成する

実際にここから`イメージ`を作成する。

```sh
$ docker build -t ubuntu/nginx:10 .
```

`ubuntu/nginx`という名前でTAGを`10`で作成する。
最後の`.`は現在のディレクトリを指している。

### コンテナを起動する
以下のコマンドで先ほど作成したイメージのコンテナを起動する。

```sh
docker run -d -p 80:80 --name nginx1 ubuntu/nginx:10 /usr/sbin/nginx -g
```

### ENTRYPOINTを使用する。
`Dokerfile`を以下のように記載すると起動コマンドを省略することができる。

```Dokerfile
FROM ubuntu
RUN apt-get install -y nginx
ADD index.html /usr/share/nginx/html/
ENTRYPOINT /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
```

コンテナ起動まで行う。

```sh
$ docker build -t ubuntu/nginx:1.1 .
$ docker run -d --name nginx2 -p 62733:80 ubuntu/nginx:1.1
```

## 一つ目の目的を達成する。
[Dockerで即実行できる、社内・自宅向けオープンソースWebアプリ](http://qiita.com/y_hokkey/items/406b5a8c4bc15354d069)に記載されている一番最後のイメージはDockerfileで定義されているので、上記の知識を使いイメージを作ってみる。

```sh
$ mkdir reichat
$ cd reichat/
$ vi Dockerfile
```

ページに書かれている事をそのまま実装する。

```Dockerfile
FROM node:0.12.2
RUN npm install -g reichat
EXPOSE 10133
CMD reichat
```

イメージの作成をして実行

```sh
$ docker build -t reichat .
# WARNがいっぱい出るけど・・・
$ docker run -d --name reichat -p 10133:10133 reichat
```

[この設定](http://qiita.com/kochizufan/items/c6c1b12748a4e08fde3f)も忘れずに行う。
ブラウザで`http://localhost:10133/`へアクセス！
やった！できた！！

```sh
$ curl localhost:10133
```

これでもデータの取得ができた！

## 感想
`nginx`の場合はうまくポートフォワードが出来なかったが、`reichat`はうまくできた。
・・・と言う事は`nginx`の設定が何か悪かったのだろう。
→解決しました。コンテナ起動時の`-p 62733:80`の設定は考えすぎで`-p 80:80`で起動させて、VMのポートフォワーディングで対応すればOKでした。

分かるとあっという間にイメージを作れてWebサイトが生成されるので驚きだった。
そして、ページが見れた時はちょっと感動したw

確かにこれでイメージを受け渡せば開発環境のスナップショットの受け渡しや、一つのサーバー内でいくつものサーバーを内部で立てれるのはすごい魅力だ。
（自分のローカルに本番環境を立てる事もできるだろう・・・。）