Dockerfileを試す

Dockerの勉強用のメモです。
Dockerに関しては、先達のみなさんのblog、Qiita上の情報を参考に勉強していますが、今回はスポットで下記についての実行結果をアップします。

# やりたいこと
* CentOSのイメージを使って、簡単なコマンドを実行する
* docker run…ではなくて、Dockerfileを使ってdocker buildしてみる。
  * うまくいったら、少しずつRUNさせることを増やしていく。
* Dockerのイメージのリポジトリから、好きなもの使ってみたい。

### ここまでの前提
* 仮想環境にはVirtualBox + Vagrantを使う。
* Vagrantを使って、Docker入りのUbuntuをインストールした。
 * https://github.com/dotcloud/docker.git を利用 -> Vagrant upでUbuntuの環境を作成した。
* 上記のUbuntuをベースにし、sshログイン。この中でdockerコマンドが実行できることを確認した。
* Dockerのチュートリアルで、簡単に学習をした。
 * http://www.docker.io/gettingstarted/# (オンラインで学習できます！）
* dockerコマンドで、最初にイメージをダウンロードし、コンテナ（Dockerで言う所の仮想環境）を起動できた。
 * yum installなどで内部に変更が加わると、イメージのIDが変更していくことが分かった。

# CentOSのイメージを選びます

### docker search centos で検索

前提条件をもとに、ベースに使うCentOSを選びます。(実行の起点はUbuntuですが、dockerで利用するイメージはいろいろ選べます）
すでにCentOS6.5が出ているので、新しいほうがいいな..と思い、docker search で検索しました。

"TRUSTED"がOKになっているものは、公式なイメージなんでしょうか？
(https://index.docker.io/search?q=centos でも一覧が取れます）

```souece:bash
vagrant@precise64:~$ docker search centos
NAME                                     DESCRIPTION                                     STARS     OFFICIAL   TRUSTED
dustin/centos                            Old CentOS is old.                              0                    
chentoo/centos                           centos 5.6 x86_64 image                         0                    
hnakamur/centos                          CentOS 6.5 x86_64 base image                    0                    
tutum/centos                             CentOS Docker image with SSH access             5                    
blalor/centos                            Bare-bones base CentOS 6.5 image                0                    [OK]
tianon/centos                            CentOS 5 and 6, created using rinse instea...   2                    
backjlack/centos                         This repository contains the following ima...   0  

# --- 以下略                 
```
OfficalのものはCentOS6.4 なようなので、6.5は無いかなと思ったところ、[hnakamurさんのエントリ](http://qiita.com/hnakamur/items/8e3136488fcfe763802c)で、CentOS 6.5のbase imageを作成＆登録したとの記述を発見!
こちらを利用させていただくことにしました。

* https://index.docker.io/u/hnakamur/centos/

# Dockerfileを作ります

イメージを決めたので、次はDockerfileを用意します。場所はどこでも良いみたいなので、~/work 以下に置きました。

最低限、FROM（どのイメージを使うか）があれば良いみたいです。

今回は、hnakamuraさんのイメージを利用したいので、検索して出て来たそのままの名前を入れてみました（この時点で、この指定でいいのか自信がありませんでした）。

```source:bash
vagrant@precise64:~/work$ pwd
/home/vagrant/work
vagrant@precise64:~/work$ ls
Dockerfile
vagrant@precise64:~/work$ cat Dockerfile 
#FROM centos
FROM hnakamur/centos 
RUN /bin/echo hi
RUN /bin/cat /etc/redhat-release
```
Dockerfileの内容は、こんな感じです。

 1. 指定のimageを取ってくる
 2. 起動して"hi" をecho する
 3. OSのバージョンを表示する (redhat-releaseの記載を確認し、CentOS6.5になってるかどうか確認)

### Build前の確認
実施前の確認です。imageは空っぽの状態。（Ubuntu向けにbaseというイメージもありましたが、いったんクリアしました）

```source:bash
vagrant@precise64:~$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE

```

# Buildしてみます

Dockerfileのあるディレクトリで、docker build . としてみます。

まずはdocker.ioからイメージをダウンロードするところから始まります。

親切なことに、Step1, Step2 と言った具合に、進行状況（過程）も表示してくれるんですね！

```source:bash
vagrant@precise64:~/work$ docker build .
Uploading context 10.24 kB
Step 1 : FROM hnakamur/centos
Pulling repository hnakamur/centos
a9f02140a1ee: Download complete 
dfb97af77c51: Download complete 
50d4926c934d: Download complete 
 ---> dfb97af77c51
Step 2 : RUN /bin/echo hi
 ---> Running in d08b5b48f486
hi
 ---> 22d0bb5e5683
Step 3 : RUN /bin/cat /etc/redhat-release
 ---> Running in f832f6d77c12
CentOS release 6.5 (Final)
 ---> 9bd6f163b65a
Successfully built 9bd6f163b65a
```
結果を見ると、"hi" と "CentOS release 6.5 (Final)" という表示が出ているので、予想通りの結果となりました。

また、 **built 9bd6f163b65a** という結果になりました。
これが現在のIMAGE IDのようです。

https://index.docker.io/u/hnakamur/centos/ のダウンロード数もカウントアップされたようです。

### 2回目以降は？

Stepは表示されますが、イメージのダウンロードは行われない分、処理が早くなります。

```source:bash
vagrant@precise64:~/work$ time docker build .
Uploading context 10.24 kB
Step 1 : FROM hnakamur/centos
 ---> dfb97af77c51
Step 2 : RUN /bin/echo hi
 ---> Using cache
 ---> 22d0bb5e5683
Step 3 : RUN /bin/cat /etc/redhat-release
 ---> Using cache
 ---> 9bd6f163b65a
Successfully built 9bd6f163b65a

real	0m0.020s
user	0m0.008s
sys	0m0.000s
```
さて、echo, cat の内容はどうなったかと言うと、 *Using cache* という文字列が表示されているだけ。
どうなっちゃったんでしょう？

cacheということで、IMAGE IDは **built 9bd6f163b65a** という結果で、これは初回と同じ値です。

### no cacheをつけてみる

まだよく分かっていないのですが、オプションにno cacheを付けてみます。こんどは、echo / cat の結果が返ってきました。

```source:bash
vagrant@precise64:~/work$ docker build -no-cache .
Uploading context 10.24 kB
Step 1 : FROM hnakamur/centos
 ---> dfb97af77c51
Step 2 : RUN /bin/echo hi
 ---> Running in 26955e584363
hi
 ---> fb53f74b6767
Step 3 : RUN /bin/cat /etc/redhat-release
 ---> Running in 95aba47597d6
CentOS release 6.5 (Final)
 ---> 45cdab64b614
Successfully built 45cdab64b614
```
イメージを確認すると **built 45cdab64b614** が追加されてます。

```source:bash
vagrant@precise64:~/work$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
<none>              <none>              45cdab64b614        2 minutes ago       309.9 MB
<none>              <none>              9bd6f163b65a        14 minutes ago      309.9 MB
hnakamur/centos     6.5                 a9f02140a1ee        2 weeks ago         309.9 MB
hnakamur/centos     latest              dfb97af77c51        2 weeks ago         309.9 MB
```
# ファイルに何か書き込んでみます

echoするだけ、catするだけだと、書き込み（変更）が無いので、さらに ~/test.txt に書き込むテストをしてみます。

```
#FROM centos
FROM hnakamur/centos
RUN /bin/echo hi
RUN /bin/cat /etc/redhat-release
RUN /bin/echo "hoge" > ~/test.txt
RUN /bin/cat  ~/test.txt
```
実行。~/test.txt の中身のcatもできたようです。

```
vagrant@precise64:~/work$ docker build .
Uploading context 10.24 kB
Step 1 : FROM hnakamur/centos
 ---> dfb97af77c51
Step 2 : RUN /bin/echo hi
 ---> Using cache
 ---> 22d0bb5e5683
Step 3 : RUN /bin/cat /etc/redhat-release
 ---> Using cache
 ---> 9bd6f163b65a
Step 4 : RUN /bin/echo "hoge" > ~/test.txt
 ---> Using cache
 ---> 699db1b2f739
Step 5 : RUN /bin/cat  ~/test.txt
 ---> Running in c7eee58c120d
hoge
 ---> f20c50e138e4
Successfully built f20c50e138e4
```
### 状態をコミット
```
vagrant@precise64:~/work$ docker ps -a
CONTAINER ID        IMAGE                    COMMAND                CREATED             STATUS              PORTS               NAMES
c7eee58c120d        699db1b2f739             /bin/sh -c /bin/cat    2 minutes ago       Exit 0                                  boring_pike         
07e7be6ba1af        9bd6f163b65a             /bin/sh -c /bin/echo   2 minutes ago       Exit 0                                  boring_darwin       
95aba47597d6        fb53f74b6767             /bin/sh -c /bin/cat    4 hours ago         Exit 0                                  determined_turing   
26955e584363        hnakamur/centos:latest   /bin/sh -c /bin/echo   4 hours ago         Exit 0                                  tender_euclide      
f832f6d77c12        22d0bb5e5683             /bin/sh -c /bin/cat    4 hours ago         Exit 0                                  prickly_ritchie     
d08b5b48f486        hnakamur/centos:latest   /bin/sh -c /bin/echo   4 hours ago         Exit 0                                  romantic_turing  
```
コミットには、CONTAINER IDが必要らしいので、一番最後に実行したものを引数にしてみます。

```   
vagrant@precise64:~/work$ docker commit c7eee58c120d
9608087e8eb76cc16c40a842599f125861aadf7fd4afe78b6cf54ffbf64a89be
vagrant@precise64:~/work$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
<none>              <none>              9608087e8eb7        3 seconds ago       309.9 MB
<none>              <none>              f20c50e138e4        2 minutes ago       309.9 MB
hnakamur/centos     6.5                 a9f02140a1ee        2 weeks ago         309.9 MB
hnakamur/centos     latest              dfb97af77c51        2 weeks ago         309.9 MB
```
### イメージ毎のテスト

test.txt を書き込む前の、ダウンロードした直後のイメージに対して、test.txt の中身をcatさせてみます。

結果、そんなのは無いよ、と言われます。

```source:bash
vagrant@precise64:~/work$ docker run a9f02140a1ee /bin/cat /test.txt
/bin/cat: /test.txt: No such file or directory
```
つぎに、コミットしたイメージに対して、test.txt の中身をcatさせてみます。(Image ID : f20c50e138e4)

```source:bash
vagrant@precise64:~/work$ docker run f20c50e138e4 /bin/cat /test.txt          
hoge
```
こんどはちゃんと出力できたようです！

# ファイルに書き込みテスト（２）をためします

同じ文字列"hoge" だけを書き込むと、キャッシュされるようなので、今度はdateコマンドの結果もくっつけて、Dockerfileを実行してみます。

### Dockerfile

```
FROM hnakamur/centos
RUN /bin/echo hi
RUN /bin/cat /etc/redhat-release
RUN /bin/echo "hoge `date`" > ~/test.txt
RUN /bin/cat  ~/test.txt
```

 ### 2回続けて実行

1回目。
"hoge Sun Jan  5 20:47:17 EST 2014" と出力されます。

```
vagrant@precise64:~/work$ docker build .
Uploading context 10.24 kB
Step 1 : FROM hnakamur/centos
 ---> dfb97af77c51
Step 2 : RUN /bin/echo hi
 ---> Using cache
 ---> 22d0bb5e5683
Step 3 : RUN /bin/cat /etc/redhat-release
 ---> Using cache
 ---> 9bd6f163b65a
Step 4 : RUN /bin/echo "hoge `date`" > ~/test.txt
 ---> Running in c5d97135393c
 ---> 6c44ddd7b236
Step 5 : RUN /bin/cat  ~/test.txt
 ---> Running in 6126db4144b6
hoge Sun Jan  5 20:47:17 EST 2014
 ---> cf8c4153782b
Successfully built cf8c4153782b
```
2回目。
"hoge Sun Jan  5 20:47:29 EST 2014" と出力されます。

```
vagrant@precise64:~/work$ docker build .
Uploading context 10.24 kB
Step 1 : FROM hnakamur/centos
 ---> dfb97af77c51
Step 2 : RUN /bin/echo hi
 ---> Using cache
 ---> b8ecb1c6f4ca
Step 3 : RUN /bin/cat /etc/redhat-release
 ---> Using cache
 ---> 2cd2b4ee1d84
Step 4 : RUN /bin/echo "hoge `date`" > ~/test.txt
 ---> Running in a7d8417b6e95
 ---> b5aa2308d56a
Step 5 : RUN /bin/cat  ~/test.txt
 ---> Running in aea88825dd7c
hoge Sun Jan  5 20:47:29 EST 2014
 ---> cce9c7c2d7cd
Successfully built cce9c7c2d7cd
```

### imageを指定してテスト

ちゃんと異なるタイムスタンプ（時間）でcatされました！

```souce:bash
# 1回目のimagewお指定
vagrant@precise64:~/work$ docker run cf8c4153782b /bin/cat /test.txt
hoge Sun Jan  5 20:47:17 EST 2014

# 2回目のimageを指定
vagrant@precise64:~/work$ docker run cce9c7c2d7cd /bin/cat /test.txt
hoge Sun Jan  5 20:47:29 EST 2014
```
# ある時点のイメージに潜り込んでみます

Dockerで記録されるイメージは、IDを指定して呼び出すことができるのが分かりました。
では、今度は、その時点のOSの中に入って確認してみます。

```source:bash
# 上記1回目のimageを指定して、バックグラウンドで起動
vagrant@precise64:~/work$ docker run -i -t -d cf8c4153782b /bin/bash
0a0392a384d5a5a40e1ec87e88e2a2680eeec2603604ccd61bc200aae7bbf1c2

# アタッチします
vagrant@precise64:~/work$ docker attach 0a0392a384d5a5a40e1ec87e88e2a2680eeec2603604ccd61bc200aae7bbf1c2

# 中の世界に潜り込みました！
bash-4.1# cat /test.txt 
hoge Sun Jan  5 20:47:17 EST 2014
bash-4.1# 
```
ちゃんと、過去のある時点の世界に潜り込めました。（すごい！
exitすると、バックグラウンドで動いていたプロセスも停止します。

どうでもいいんですが、bashでなく、shにしたら、attachするとshでアクセスになりました。

```
vagrant@precise64:~/work$ docker run -i -t -d cf8c4153782b /bin/sh
152ad6c546c160cb3ab218d46f06907ecb9a8e41685739a435e444c8dcdbc0ed
vagrant@precise64:~/work$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
152ad6c546c1        cf8c4153782b        /bin/sh             3 seconds ago       Up 2 seconds                            cranky_morse        
vagrant@precise64:~/work$ docker attach 152ad6c546c1                                                    

sh-4.1# 
```

# こんな気づきがありました！

実現方法に関しては、まだ良くわかっていないのですが、VirtualBox & Vagrant という組み合わせと違うな、というのが、とにかく任意の状態への遷移がしやすいことでした。

* 状態の管理がしやすい
* VirtualBoxのSnapshotでも、状態は記録できるけれど、復元するのに時間がかかる。（停止 -> スナップショットIDを指定して再起動）
* Dockerの場合は一瞬！（起動とか停止が気にならないくらい）
* Dockerfileだけ用意してチェックアウトしてJenkinsでビルドっていうのがホントに出来そう！
* ある時点、違う内容の『xxxxの世界』に、ほんの少しで移動出来る！（なんかディケイドっぽい！）

### OSイメージに対する更新の歴史を垣間みる

また、docker.ioにもイメージがたくさん登録されているのですが、多分それをベースにすると、gitのリポジトリをcloneして来たときと同じように、そのイメージの歴史も一緒に見えるんじゃないかと思いました。

実際に、ruby2.1入りのCentOSのイメージをdocker.ioから取得して、historyを見てみると…。

```
vagrant@precise64:~/work$ docker history tmtk75/ruby-2.1.0p0 
IMAGE               CREATED             CREATED BY                                      SIZE
583b10f73f37        7 days ago          /bin/sh -c gem install bundler --no-ri --no-r   8.675 MB
1b1fd68b6011        7 days ago          /bin/sh -c cd /usr/local/ruby-2.1.0; ./config   345 MB
ebd5e5c243eb        7 days ago          /bin/sh -c cd /usr/local; tar xfz ruby-2.1.0.   69.76 MB
bad9ee09833f        7 days ago          /bin/sh -c cd /usr/local; curl -OL http://cac   15.08 MB
d6291e86618f        7 days ago          /bin/sh -c yum install -y zlib-devel openssl-   27.27 MB
3ffa09187685        7 days ago          /bin/sh -c yum install -y gcc                   203.4 MB
539c0211cd76        9 months ago                                                        300.6 MB
```

うーん、面白い。
しかも、先達のステップもきちんと見えてくるので、環境構築の手順に大変参考になります。

以上、全くプログラミングしてないので恐縮ですが、Dockerの1回目の覚え書きでした。