ansible-playbookでdockerコンテナをプロビジョニングしてみた

## はじめに

通常dockerコンテナを構築する際、イメージのビルドの為にdockerfileの記述を行います。
しかしながら、イメージレイヤーを減らすためにRUNにAND演算子をひたすら繋げたコマンドを記述する必要があるため、
少々処理が追いにくくなることが難点です。
また、ansible用のロールをコンテナに適用する事を考えたときに、いちいち処理を書き直すのは面倒だなー…と
思っていた矢先にAnsibleの**Connection Plugin**の存在を知りました。

## Connection Plugin

簡単に言えば、Ansibleサーバーとリモートホストの接続方式を切り替えられるプラグインのことです。
デフォルトではAnsibleサーバーとリモートホストの接続はsshが用いられますが、
Ansible 2.0からはdockerコンテナと接続できる**Docker Connection Plugin**も用意されていました。
ので、今回はこちらのプラグインを使用してみたいと思います。
詳しくは以下の参考元などをご覧ください。
ちなみにdocker connection pluginを使用する際は、```connection: docker```を指定すれば良いとのことです。

## 実行例

例に倣ってとりあえず試してみました。

### 環境

|項目名|バージョン|
|:---:|:---:|
|CentOS|7.3.1611|
|ansible|2.3.1.0|
|pip|9.0.1|

### 手順

1. Ansible(=>2.0)をインストール

    ```
#　yum install openssl-devel python-devel
#　pip install ansible
``` 

2. docker-pyをインストール

     ```
# pip install docker-py
```

3. 以下のようにrole,playbookを記述
今回は単純にCentOS6のベースイメージから作成したコンテナ上に、某界隈で有名なslをインストールしてみます。

     ```:tree
.
|-- ansible.cfg
|-- playbook
|   `-- docker
|       `-- test.yml
`-- roles
    |-- docker
    |   `-- docker-run
    |       |-- defaults
    |       |   `-- main.yml
    |       `-- tasks
    |           |-- docker_run.yml
    |           `-- main.yml
    |-- remi
    |   `-- tasks
    |       |-- epel.yml
    |       `-- main.yml
    `-- sl
        `-- tasks
            |-- main.yml
            `-- sl.yml
```
     ```:ansible.cfg
[defaults]
roles_path    = roles
```
     
    ```yaml:playbook/docker/test.yml
    ---

    - hosts: localhost
      connection: local
      roles:
        - { role: docker/docker-run }

    - hosts: test
      connection: docker
      roles:
        - { role: epel }
        - { role: sl }
```

    ```yaml:roles/docker/docker-run/defaults/main.yml
docker_image: centos:6.9
docker_hostname: test
```

    ```yaml:roles/docker/docker-run/tasks/docker_run.yml
    ---

    - name: Dockerコンテナ起動
      docker_container: image={{ docker_image }} name={{ docker_hostname }} detach=yes tty=yes command=/bin/bash 
    - name: Dockerコンテナをホストとして追加
      add_host: name={{ docker_hostname }}
```

    ```yaml:roles/remi/tasks/epel.yml
    ---
    
    - name: "epel install"
      yum: name=epel-release
```

    ```yaml:roles/sl/tasks/sl.yml
    ---
    
    - name: "sl install"
      yum: name=sl state=latest enablerepo=epel
```

4. ansible-playbook

     ```
# ansible-playbook playbook/docker/test.yml
```

5. コンテナ内で確認

    ```
# docker exec -ti test /bin/bash
[root@b3a5b2f0ebe1 /]# sl



                              (@@) (  ) (@)  ( )  @@    ()    @     O     @     O      @
                         (   )
                     (@@@@)
                  (    )

                (@@@)
              ====        ________                ___________
          _D _|  |_______/        \__I_I_____===__|_________|
           |(_)---  |   H\________/ |   |        =|___ ___|      _________________
           /     |  |   H  |  |     |   |         ||_| |_||     _|                \_____A
          |      |  |   H  |__--------------------| [___] |   =|                        |
          | ________|___H__/__|_____/[][]~\_______|       |   -|                        |
          |/ |   |-----------I_____I [][] []  D   |=======|____|________________________|_
        __/ =| o |=-~~\  /~~\  /~~\  /~~\ ____Y___________|__|__________________________|_
         |/-=|___|=O=====O=====O=====O   |_____/~\___/          |_D__D__D_|  |_D__D__D_|
          \_/      \__/  \__/  \__/  \__/      \_/               \_/   \_/    \_/   \_/
```

上記のようにslが走り出したら、成功です！

## 参考元

[Ansible公式：Developing Plugins](http://docs.ansible.com/ansible/dev_guide/developing_plugins.html)
[Ansible Docker Connection Pluginを使う](http://tdoc.info/blog/2015/12/03/docker_connection_plugin.html)