PackerでDocker Imageをビルドしてみました

#PackerでDockerのイメージをビルドする手順

##まずはビルド用の.jsonファイルを用意する。

```js
// redis_packer.json 
{
    "builders":[{
        "type": "docker",
        "image": "ubuntu",
        "export_path": "redis_packer_image.tar"
    }],
    "provisioners":[
        {
            "type": "shell",
            "inline": [
                "apt-get -y update",
                "apt-get install -y redis-server"
            ]
        }
    ],
    "post-processors": [
        [
            {
                "type": "docker-import",
                "repository": "liubin/redis",
                "tag": "packer"
            },
            "docker-push"
        ]
    ]
}

```

##`packer`コマンドでビルドする。

```
sudo packer build redis_packer.json
```
ビルド中の出力

```
docker output will be in this color.

==> docker: Creating a temporary directory for sharing data...
==> docker: Pulling Docker image: ubuntu
    docker: Pulling repository ubuntu
==> docker: Starting docker container...
    docker: Run command: docker run -d -i -t -v /tmp/packer-docker025602017:/packer-files ubuntu /bin/bash
    docker: Container ID: 9aa0984a820d7158c975a9d76cc560d0de0a59423bb82dcbc1a263051ac12adf
==> docker: Provisioning with shell script: /tmp/packer-shell448633696
    docker: Ign http://archive.ubuntu.com trusty InRelease

~~~~~　省略：apt-get XXX の出力 ~~~~

    docker: Processing triggers for ureadahead (0.100.0-16) ...
==> docker: Exporting the container
==> docker: Killing the container: 9aa0984a820d7158c975a9d76cc560d0de0a59423bb82dcbc1a263051ac12adf
==> docker: Running post-processor: docker-import
    docker (docker-import): Importing image: Container
    docker (docker-import): Repository: liubin/redis:packer
    docker (docker-import): Imported ID: 30e3f178a05b602aafb5991da161c5f280f56f301a956b1e942c5c4adc548277
==> docker: Running post-processor: docker-push
    docker (docker-push): Pushing: liubin/redis
    docker (docker-push): The push refers to a repository [liubin/redis] (len: 3)
    docker (docker-push): Sending image list
    docker (docker-push): Pushing repository liubin/redis (3 tags)
    docker (docker-push): Pushing tag for rev [2f21e9eb9e82] on {https://registry-1.docker.io/v1/repositories/liubin/redis/tags/dockerfile}
    docker (docker-push): Pushing tag for rev [744ce29b2fcf] on {https://registry-1.docker.io/v1/repositories/liubin/redis/tags/manually}

.......

Build 'docker' finished.

==> Builds finished. The artifacts of successful builds are:
--> docker: Imported Docker image: liubin/redis:packer
```

##内訳
上記のログからよくわかると思いますが、PackerはBASEとなるイメージをContainerとして起動させ、Containerの中にProvisioningをして、最後にContainerをExposeをした。手動でイメージをビルドと同じです。

`post-processors`の部分は生成した"redis_packer_image.tar"をローカルのリポジトリに導入し、さらにDocker Hubにアップロードしました。

詳細は[マニュアル](http://www.packer.io/docs/builders/docker.html)で確認ください。

#Dockerfileと異なる点（また問題点）

##履歴は残れない

Packerはかなり原始的なアプローチをとったのが原因だと思う。

```
# Packerで作ったイメージに履歴はない。

$ sudo docker history liubin/redis:packer
IMAGE               CREATED             CREATED BY          SIZE
30e3f178a05b        22 hours ago                            249.1 MB

# dockerfileで作ったイメージに履歴はちゃんと残っている
$ sudo docker history liubin/redis:dockerfile
IMAGE               CREATED             CREATED BY                                      SIZE
2f21e9eb9e82        24 hours ago        /bin/sh -c #(nop) ENTRYPOINT [/usr/bin/redis-   0 B
016287bed93b        24 hours ago        /bin/sh -c #(nop) EXPOSE map[6379/tcp:{}]       0 B
ba0681b90522        24 hours ago        /bin/sh -c apt-get -y install redis-server      2.388 MB
e7fbd2e3ce12        24 hours ago        /bin/sh -c apt-get update                       3.764 MB
c8ead3c65fde        24 hours ago        /bin/sh -c #(nop) MAINTAINER bin liu <liubin0   0 B
e54ca5efa2e9        6 days ago          /bin/sh -c apt-get update && apt-get install    178.4 kB
6c37f792ddac        6 days ago          /bin/sh -c apt-get update && apt-get install    83.61 MB
83ff768040a0        6 days ago          /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/   1.903 kB
2f4b4d6a4a06        6 days ago          /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic   194.5 kB
d7ac5e4f1812        6 days ago          /bin/sh -c #(nop) ADD file:adc47d03da6bb2418e   192.5 MB
511136ea3c5a        12 months ago                                                       0 B

```
##イメージのサイズは違う
下記の例にTAGがdockerfileとなるのはDockerfileで生成した、サイズはPackerで生成したイメージより大きかった（４０MBぐらい）。

＊2014/6/25 18:00　追記：詳しい情報は[＃コメント２](http://qiita.com/liubin0329/items/5cb5467a079a453e8f72#comment-83e0c0bbb761bac51d4e)をご参照ください。

※ 3つの`liubin/redis`イメージはすべて `apt-get -y update`と`apt-get install -y redis-server`でビルドした。

```
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
liubin/redis        packer              30e3f178a05b        22 hours ago        249.1 MB
liubin/redis        dockerfile          2f21e9eb9e82        24 hours ago        282.6 MB
liubin/redis        manually            744ce29b2fcf        26 hours ago        282.3 MB
```

##ENTRYPOINT・EXPOSEなどDockerfileにあるオプションを指定できない

指定できないため、イメージを使うとき（`docker run`）で詳しい情報提供しなければならない。別に大きい不便でも感じられなさそうだ。

[マニュアル](http://www.packer.io/docs/builders/docker.html)にもその原因が載せている。

#最後に感想
オフィシャルサイトを読めば、Cloudのために生まれたツールの感じがする。
なかなか面白いツールじゃないかと。ぜひお試してください。