AnsibleをDockerコンテナで動かす

# Ansibleコンテナ

オフライン環境でAnsibleを構築する必要があったのですが、必要なパッケージやらを全部かき集めて作るのは大変ですね。
全部Dockerに放り込んでしまえばいいのでは？ということで、PythonのDockerコンテナをベースにAnsibleをコンテナ化しました。

ちなみに、Offcialで`ansible/ansible`というコンテナイメージがありますが、これはAnsible自体のテスト環境として用意されているものであり、Ansibleが入っているわけではありません。
> **ansible/ansible**
> Images for automated testing of Ansible. They do not include Ansible and are not for end users. 


## レポジトリ

以下のレポジトリに登録してあります。
[satken2/ansible - Docker Hub](https://hub.docker.com/r/satken2/ansible)

## Dockerfile

内容はとても単純です。
AnsibleでSSHのパスワード認証を使うためには`sshpass`が必要なのでインストールしています。
また、使うモジュールによっては追加でpipのパッケージが必要な場合がありますがそれは書いていたらきりがないので書いてません。

```dockerfile
FROM python:3.7.6-stretch

RUN pip install pip --upgrade
RUN pip install ansible

RUN apt-get update -y && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
    sshpass

WORKDIR /work
```

# Playbookの実行

Playbookを保存したディレクトリに移動してから以下のコマンドを実行すれば、Playbookを実行できます。

```
docker run -v "${PWD}":/work:ro -v ~/.ansible/roles:/root/.ansible/roles -v ~/.ssh:/root/.ssh:ro --rm satken2/ansible ansible-playbook <YAML_FILENAME>
```

通常のAnsibleでの、`ansible-playbook  <YAML_FILENAME>`と同じです。

## コマンド解説

### --rmオプション 

このコンテナは立ち上げっぱなしに使うわけではないので、環境を汚さないために実行が終わったら削除するようにしておきます。

### バインド

このコマンドでは以下のバインドを定義しています。

| ホストパス | コンテナパス | 目的 |
|----------------|--------------------|---------------------------------------------|
| `$pwd`         |     `/work`        | ホストマシンのPlaybookをコンテナ内から読めるようにします            |
| `~/.ansible/roles`| `/root/.ansible/roles` | Ansible GalaxyでインストールしたRoleを永続化するためです |
|  `~/.ssh`      |    `/root/.ssh`    | コンテナ内からターゲットマシンにSSH認証を通すため、ホストマシンの認証情報を共有します |

**$pwd <-> /work**
コンテナのファイルシステム内にPlaybookをいちいちコピーして使うのは面倒なので、バインドを使ってホストシステム内のPlaybookを直接読み込みます。
ホストの`${PWD}`をコンテナ内のワークディレクトリである`/work`にバインドすることで、コマンド実行時のディレクトリがコンテナ内から見えます。

**~/.ansible/roles <-> /root/.ansible/roles**
これは、Ansible GalaxyでインストールしたRoleを永続化するためのものです。Galaxyを使わない場合は不要です。
Ansibleの仕様上、GalaxyでRoleをインストールした場合は以下のディレクトリの中で利用可能なものにRoleが保存されます。

 - ~/.ansible/roles
 - /usr/share/ansible/roles
 - /etc/ansible/roles

今回は一番上の~/.ansible/rolesに入るようにしています。

**~/.ssh <-> /root/.ssh**
そのままコンテナを実行しても、コンテナ内のSSHクライアントはターゲットマシンの認証情報を持っていないので、接続できません。
ホストマシンの`.ssh`を共有して、コンテナ内からもターゲットマシンにアクセスできるようにしてあげます。


# GalaxyからのRoleインストール

任意のディレクトリで以下のコマンドを実行したら、Ansible Galaxyを使ってRoleをインストールできます。

```
docker run -v ~/.ansible/roles:/root/.ansible/roles --rm satken2/ansible ansible-galaxy install <ROLE_NAME>
```

通常のAnsibleでの、`ansible-galaxy install <ROLE_NAME>`と同じです。

## コマンド解説

### --rmオプション 

さきほどと同様、使い終わったら削除します。

### バインド

**~/.ansible/roles <-> /root/.ansible/roles**
さきほどのPlaybook実行時と合わせて~/.ansible/rolesにRoleが入るように設定しています。


# Bashエイリアス

上記で紹介したようなコマンドや他にもよく使うものをエイリアスとして登録しておけば、Docker上で動いていることをほとんど意識することなくAnsibleを使用できます。

## 登録

```bash
#!/bin/bash
alias ansible='docker run -v "${PWD}":/work:ro --rm satken2/ansible ansible'
alias ansible-playbook='docker run -v "${PWD}":/work:ro -v ~/.ansible/roles:/root/.ansible/roles -v ~/.ssh:/root/.ssh:ro --rm satken2/ansible ansible-playbook'
alias ansible-galaxy='docker run -v ~/.ansible/roles:/root/.ansible/roles --rm satken2/ansible ansible-galaxy'
alias ansible-vault='docker run -v "${PWD}":/work:ro --rm satken2/ansible ansible-vault'
```

## 使う時

通常のAnsibleと同じように使えます。
ただし、`ansible-playbook`を使う時はPlaybookのディレクトリに確実に`cd`してからでないと正常に動作しませんので注意。

```bash
$ ansible -m ping
$ ansible-playbook site.yml
```