Ansible 2.0 の Docker Connection Plugin で GCPに置いたDockerコンテナに繋ぐメモ


# はじめに
Ansible 2.0 でひっそり追加された ansible-docker-connection-plugin を試してみた。先人が参考になる前例を数多く残しているのであくまでも「自分がやってみたかったメモ」でござる。GCPを docker-machine にしているけど docker コマンドが通る状態であれば別に virtualbox でもなんでもよい。


ポイントは以下の3点。

- インベントリファイルにはコンテナ名を書く
- `eval $(docker-machine env hogehoge)` やってれば ansible から対象コンテナにそのまま繋がる
- 対象コンテナに python がインストールされている必要がある


# 下準備

## Docker Host を準備する

[GCP(Google Compute Engine) に Docker Machine を置く](http://qiita.com/ma2saka/items/74db9393072ff9e779c7) あたりを参照しつつ、作る。newtonはうちの猫の名前である。

```sh
$ gcloug auth login
$ docker-machine create -d google \
                        --google-project ${GCLOUG_PROJECT_NAME} \
                        --google-preemptible \
                        --google-tags 'http-server,https-server' \
                        --google-zone asia-east1-a \
                        --google-machine-type "g1-small" \
                        newton
$ eval $(docker-machine env newton)
```

余談だけど作った docker host には、以下のコマンドで ssh できる。

```
$ docker-machine ssh newton
$ ssh docker-user@$(docker-machine ip newton) -i ~/.docker/machine/machines/newton/id_rsa
```

ここまではよい。

## pipでansible 2.0を入れる

ローカル側で `pip install ansible` すると 2.0.0.1 が入る。

```
$ mkdir hoge
$ cd hoge
$ virtualenv .
$ . ./bin/activate
$ pip install ansible
Collecting ansible
  Using cached ansible-2.0.0.1.tar.gz
Collecting paramiko (from ansible)
  Using cached paramiko-1.16.0-py2.py3-none-any.whl
Collecting jinja2 (from ansible)
  Using cached Jinja2-2.8-py2.py3-none-any.whl
Collecting PyYAML (from ansible)
Requirement already satisfied (use --upgrade to upgrade): setuptools in ./lib/python2.7/site-packages (from ansible)
Collecting pycrypto>=2.6 (from ansible)
Collecting ecdsa>=0.11 (from paramiko->ansible)
  Using cached ecdsa-0.13-py2.py3-none-any.whl
Collecting MarkupSafe (from jinja2->ansible)
Building wheels for collected packages: ansible
  Running setup.py bdist_wheel for ansible
  Stored in directory: /Users/ma2saka/Library/Caches/pip/wheels/7a/e1/81/d35ca9bdfb4da7f44d31db8af498e731795fe2cbe086dd1285
Successfully built ansible
Installing collected packages: ecdsa, pycrypto, paramiko, MarkupSafe, jinja2, PyYAML, ansible
Successfully installed MarkupSafe-0.23 PyYAML-3.11 ansible-2.0.0.1 ecdsa-0.13 jinja2-2.8 paramiko-1.16.0 pycrypto-2.6.1
```




## Nginx コンテナを取得して起動する

`docker pull nginx`する。コンテナ名は nginx01 とする。

```
$ docker pull nginx
$ docker run -d -p 80:80 --name nginx01 nginx
874e6894f85e81368d30ac7b56003bf8cc2b5f38ccc74790d3cfcda536936c2c
```

ちゃんと起動したことが確認できる。

```
$ curl $(docker-machine ip newton)
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
```

## (おまじない) Nginxコンテナに python をインストールする

```
$ docker exec -t nginx apt-get update
$ docker exec -t nginx apt-get install -y python
```

残念ながら、ansible docker connection で対象コンテナにあれこれするには、対象コンテナに python がインストールされている必要があるのです。*これはとても悔しい点です。*

# Ansible x Docker Connection

やってみよう。

## コンテナ名を書いたインベントリファイルを作成する

インベントリファイルを以下のように作成する。

```hosts
[containers]
nginx01
```

nginx01はさっき作ったコンテナ名。つまり、コンテナ名指定で接続できるのだ。dockerホストの情報は docker コマンドと共用なので、dockerコマンドが機能する状態なら気にしなくてもよい。

## nginx のファイルを ansible で置き換える

Nginxのデフォルトページのファイルは `/usr/share/nginx/html/index.html` だ。

こいつを書き換えてやろう。

以下のような playbook.yml を用意した。

```playbook.yml
- hosts: all
  connection: docker
  tasks:
  - name: "Nginxの標準ページの書き換え"
    replace: >-
      dest='/usr/share/nginx/html/index.html'
      regexp='nginx'
      replace='Nyanginx'
```


### 実行する

```
[ma2saka@localhost:hoge]$ ansible-playbook -i hosts playbook.yml

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [nginx01]

TASK [Nginxの標準ページの書き換え] ********************************************************
changed: [nginx01]

PLAY RECAP *********************************************************************
nginx01                    : ok=2    changed=1    unreachable=0    failed=0

```

### 動作確認

エンジンエックスがニャンジンエックスに書き換わってることを確認する。

```
[ma2saka@localhost:hoge]$ curl $(docker-machine ip newton)
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Nyanginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to Nyanginx!</h1>
<p>If you see this page, the Nyanginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://Nyanginx.org/">Nyanginx.org</a>.<br/>
Commercial support is available at
<a href="http://Nyanginx.com/">Nyanginx.com</a>.</p>

Nyanginx
</body>
</html>
```

でけた。

# まとめ

dockerコマンドと接続情報を共用することで、コンテナ名によって接続先を抽象化できるのはかっこいい。ただ、コンテナ側にpythonインストールが必要ってのは困りもの。これはなんとかならないかな・・・?

コンテナ名で解決できるってのが面白そうだから試してみたが、使い所は、うーん、Dockerコンテナのベースビルドに Dockerfile 使って、オンプレその他の既存資産と共通のAnsibleでアプリケーションレイヤーのコンフィギュレーションを行うくらいなのかなぁ。まあ、こんな風に動くんだなぁってことで1つ。