Packer の provisioners に Ansible を指定して Docker イメージを作成する

[Packerを使ってChef/Puppet/AnsibleでDockerのイメージをつくる  | SOTA](http://deeeet.com/writing/2014/03/02/build-docker-image-by-packer/) を参考にして、Dockerfile を使用せずに、Ansible を使用して Docker イメージを作成してみました

## 仮想環境の準備

Vagrant を使用して環境を準備します

Vagrantfile の内容は下記の通りです

box は事前に [shiguredo/packer-templates](https://github.com/shiguredo/packer-templates) を使用して作成しました

```ruby:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu-13.10"
  config.vm.box_url = "ubuntu-13-10-x64-virtualbox.box"
  config.vm.hostname = "ubuntu-13.10"

  config.vm.network "private_network", ip: "192.168.50.4"

  config.vm.provision :docker do |d|
    d.pull_images "ubuntu:13.10"
  end

  config.vm.provision :ansible do |ansible|
    ansible.playbook = "playbook.yml"
  end
end
```

```yaml:playbook.yml
---
- hosts: all
  sudo: True
  user: vagrant
  tasks:
    - shell: apt-get -y update
    - shell: apt-get -y install unzip curl
    - file:  path={{ workspace }}/packer
             state=directory
    - get_url: url=https://dl.bintray.com/mitchellh/packer/0.5.2_linux_amd64.zip
               dest={{ workspace }}/packer/0.5.2_linux_amd64.zip
    - shell: unzip 0.5.2_linux_amd64.zip
             chdir={{ workspace }}/packer
    - shell: echo "export PATH={{ ansible_env.PATH }}:{{ workspace }}/packer" > /home/vagrant/.bashrc
  vars:
    workspace: /home/{{ ansible_ssh_user }}/work
```

仮想環境を起ち上げて、ssh でログインします

```bash:
$ vagrant up
$ vagrant ssh
```

## Docker イメージの作成

### Ansible の playbook の作成

まず Ansible の playbook を作成します

今回は ansible ディレクトリ以下に下記の構成で作成しています

```bash:
.
├── playbook.yml
└── roles
    ├── python
    │   ├── tasks
    │   │   └── main.yml
    │   └── vars
    │       └── main.yml
    └── ruby
        ├── tasks
        │   └── main.yml
        └── vars
            └── main.yml
```

実行する playbook.yml は下記の通りです

```yaml:playbook.yml
- hosts: 127.0.0.1
  sudo: True
  roles:
    - python
    - ruby
  vars:
    workspace: /home/vagrant/work
```

Python 2.7.6 と Ruby 2.1.1 をそれぞれ /opt/python, /opt/ruby 以下にインストールします


### Packer のテンプレート の作成

次に、Packer のテンプレートを作成します

`playbook_file` に実行する playbook を指定しますが、これだけでは Ansible の roles 以下のディレクトリはアップロードされません

roles 以下のディレクトリをアップロードするために、`role_paths` に roles 以下のディレクトリを指定します

```json:template.json
  {
      "builders":[{
          "type": "docker",
          "image": "ubuntu:13.10",
          "export_path": "image.tar"
      }],
      "provisioners":[
          {
              "type": "shell",
              "inline": [
                  "apt-get -y update",
                  "apt-get install -y python-pip python-dev",
                  "pip install ansible"
              ]
          },
          {
              "type": "ansible-local",
              "playbook_file": "ansible/playbook.yml",
              "role_paths": ["ansible/roles/python", "ansible/roles/ruby"],
              "staging_directory": "/tmp/packer-provisioner-ansible-local"
          }
      ],
      "post-processors": [
          {
              "type": "docker-import",
              "repository": "hexa/ubuntu/base",
              "tag": "0.1"
          }
      ]
  }
```

### Docker イメージのビルド

次のコマンドでイメージを作成します

```bash:
$ packer build template.json
```

### 確認

Docker イメージの一覧

```bash:
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hexa/ubuntu/base    0.1                 c4fe59e2ddb0        39 seconds ago      1.071 GB
ubuntu              13.10               9f676bd305a4        8 weeks ago         178 MB
```

Ansible に設定した python と ruby がインストールされていることの確認

```bash:
$ docker run -i -t hexa/ubuntu/base:0.1 /opt/python/2.7.6/bin/python -V
Python 2.7.6
$ docker run -i -t hexa/ubuntu/base:0.1 /opt/ruby/2.1.1/bin/ruby -v
ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-linux]
```

## 参考

- [Packerを使ってChef/Puppet/AnsibleでDockerのイメージをつくる  | SOTA](http://deeeet.com/writing/2014/03/02/build-docker-image-by-packer/)
- [Ansible (Local) Provisioner - Packer](http://www.packer.io/docs/provisioners/ansible-local.html)