今更ansible+dockerを始めたら最初からつまづいたけど、何とか起動出来た話

## 概要
Excelの手順書通りに操作せよ！という現実を変えるのに、ansibleが使えそうだとどこかのサイトで見たので、dockerとの組み合わせで検証してみた。
そしてコンテナへの接続方法に**「Docker connection plugin for Ansible」**ってのを使えばssh不要と検証途中で知ったので、変更した上で接続出来るようになるまでのメモ。

## 環境
os: centos7
ansible: 2.9.13
docker: 19.03.13
docker-compose: 1.26.2

各ミドルのインストールは色んな方が公開されているので割愛。

## 失敗してた時の設定
### コンテナ側
* DockerFile

``` dockerfile
# OS
FROM centos:centos7

# pkg install
RUN yum install -y epel-release && \
    yum update -y  && \
    yum install -y openssh-server openssh-clients sshpass && \
    yum install -y net-tools vim

ENV LANG ja_JP.UTF-8

# root password
RUN echo password | passwd --stdin root

# # sshd_config edit
RUN sed -ri "s/#PermitRootLogin yes/PermitRootLogin yes/g" /etc/ssh/sshd_config
RUN systemctl enable sshd.service

CMD ["/sbin/init"]
```
ansibleで接続用のコンテナを準備する（最初はssh使おうとしてたので作った）

* docker-compose

``` yaml
version: '3.7'

services:
  srv1:
    build:
     context: .
     dockerfile: srv-dockerfile
    hostname: srv1
    container_name: srv1
    environment:
      - TZ=Asia/Tokyo
    restart: always
    tty: true
    networks:
      app_net:
        ipv4_address: 172.16.238.101

  srv2:
    build:
     context: .
     dockerfile: srv-dockerfile
    hostname: srv2
    container_name: srv2
    environment:
      - TZ=Asia/Tokyo
    restart: always
    tty: true
    networks:
      app_net:
        ipv4_address: 172.16.238.102

# 固定IP付与用のNW設定
networks:
  app_net:
    driver: bridge
    ipam:
     driver: default
     config:
       - subnet: 172.16.238.0/24
```
sshするのに便利そうだなと **固定IP** を付与した。

#### コンテナ起動
``` shell
# docker-compose up -d
Starting srv1 ... done
Starting srv2 ... done
```

### ansible側
* hosts

``` yaml
[testGrp]
172.16.238.101
172.16.238.102
```
* yaml

``` yaml
- name: start up a docker container
  hosts: localhost
  tasks:
    - name: start up a docker container by running bash
      command: docker-compose -f /srv/ansible/docker-compose.yml up -d
  tags:
    - never # docker-composeで「alwaus: restart」としているので、普段は動作しないようにした

- name: connection test
  hosts: testGrp
  connection: docker #connection plugin利用の指定
  tasks:
  - name: ping
    ping:
```
#### playbook実行結果
``` shell
# ansible-playbook -i hosts test-ansible.yml --check --diff

PLAY [start up a docker container] ***********************************************************************************************************************************

PLAY [connection test] ***********************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************
fatal: [172.16.238.101]: UNREACHABLE! => {"changed": false, "msg": "Failed to create temporary directory.In some cases, you may have been able to authenticate and did not have permissions on the target directory. Consider changing the remote tmp path in ansible.cfg to a path rooted in \"/tmp\", for more error information use -vvv. Failed command was: ( umask 77 && mkdir -p \"` echo ~/.ansible/tmp `\"&& mkdir \"` echo ~/.ansible/tmp/ansible-tmp-1602479114.98-3164-90901945313893 `\" && echo ansible-tmp-1602479114.98-3164-90901945313893=\"` echo ~/.ansible/tmp/ansible-tmp-1602479114.98-3164-90901945313893 `\" ), exited with result 1", "unreachable": true}
fatal: [172.16.238.102]: UNREACHABLE! => {"changed": false, "msg": "Failed to create temporary directory.In some cases, you may have been able to authenticate and did not have permissions on the target directory. Consider changing the remote tmp path in ansible.cfg to a path rooted in \"/tmp\", for more error information use -vvv. Failed command was: ( umask 77 && mkdir -p \"` echo ~/.ansible/tmp `\"&& mkdir \"` echo ~/.ansible/tmp/ansible-tmp-1602479115.05-3165-268763785818242 `\" && echo ansible-tmp-1602479115.05-3165-268763785818242=\"` echo ~/.ansible/tmp/ansible-tmp-1602479115.05-3165-268763785818242 `\" ), exited with result 1", "unreachable": true}

PLAY RECAP ***********************************************************************************************************************************************************
172.16.238.101             : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   
172.16.238.102             : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   

```
無事失敗した。
エラーメッセージにtmpフォルダの権限が無いかもってあったけど、pingで権限不足とかそんなことはあるまい、、、と放置。

``` shell
# docker-compose ps
Name    Command     State   Ports
---------------------------------
srv1   /sbin/init   Up           
srv2   /sbin/init   Up
# docker inspect srv1 | grep IPv4Address
                        "IPv4Address": "172.16.238.101"
# ping 172.16.238.101
PING 172.16.238.101 (172.16.238.101) 56(84) bytes of data.
64 bytes from 172.16.238.101: icmp_seq=1 ttl=64 time=0.133 ms
64 bytes from 172.16.238.101: icmp_seq=2 ttl=64 time=0.134 ms
```
念の為、ping単体で実行したが、こっちは成功したので、コンテナ自体は問題ないと判断。

## 成功時の設定
* hosts

``` yaml
[testGrp]
#172.16.238.101
#172.16.238.102
srv1
srv2
```
参考になる記事を色々見ていたら、どの記事もプラグインを利用するときは「ホスト名」で指定していることに今更ながらに気付く（この時点で半日経過）。
ので、ターゲットの指定方法を「IP」から**「コンテナ名」**に変更。
※他にもdockerfileからssh消したりしてますが、成功には関係ないので割愛



#### 実行結果
``` shell
# ansible-playbook -i hosts test-ansible.yml --check --diff

PLAY [start up a docker container] ***********************************************************************************************************************************

PLAY [connection test] ***********************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************
ok: [srv2]
ok: [srv1]

TASK [ping] **********************************************************************************************************************************************************
ok: [srv2]
ok: [srv1]

PLAY RECAP ***********************************************************************************************************************************************************
srv1                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
srv2                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
```
成功！

## まとめ
* 「Docker connection plugin for Ansible」を利用するとコンテナ内にsshdが要らない
* pluginを利用して接続する場合は、playbookで「connection: docker」を指定する
* ホストの指定方法は必ず**「コンテナ名」**で指定する

よくよく見なくてもと公式も含め「コンテナ名」とか「ホスト名」って書いてあるんですよね。
ssh接続の検証から入って、ひとまずIP固定化したしIP指定接続出来るなって思い込みで進めてた結果の失敗でした。。。


## 残課題
* ansibleのコンテナ化

ホントはansibleも含めて全部コンテナで起動させたかったんですが、コンテナ化すると該当のプラグインを経由して他のコンテナにアクセスできず、ひとまずホストに直接インストールしているため。
DooD使えば出来るって記事があったんですが、なぜかコンテナに認識されず、dockerコマンドが利用できなかったんですよね。。。
まあメインはそこじゃないので、後々ですが。

## 参考
* [AnsibleでDockerコンテナを操作してみよう](https://hiyoko-infratech.hateblo.jp/entry/2017/12/31/191043)
* [dockerのコンテナに固定IPを振る(compose file version 3の注意点)](https://qiita.com/ken992/items/e8fb65238112850ba186)
* [コンテナからコンテナを操作する](https://blog.nijohando.jp/post/docker-in-docker-docker-outside-of-docker/)