Dockerfileを書かずにAnsibleでプロビジョニングする


2016年 07月 13日

Dockerコンテナでsshdを動かしてはいけない

この記事ではDockerコンテナにAnsibleで接続してプロビジョニングする方法を説明します。

その前に、Dockerコンテナでsshdを動かしてAnsibleで接続しているみなさん、Ansible 2.0からDocker Connection Pluginが導入されてsshは必要なくなったので今すぐsshdを停止してください。

Dockerコンテナでsshdを動かしてはいけない理由は以下を参照してください。

Dockerコンテナ内でsshdを実行してはいけない理由

今回のファイル一式をGitHubに置きました

https://github.com/eyasuyuki/docker-ansible

AnsibleとDockerのインストール

この記事は以下の環境で試しています。

  • OS X 10.11.5
  • Ansible 2.1
  • Docker 1.11.2
  • Docker Machine 0.7.0
  • Docker Compose 1.7.1
  • VirtualBox 5.1.0

これらがインストールされていない場合は以下を実行してインストールしてください。

brew install ansible docker docker-machine docker-compose
brew cask install virtualbox

Docker MachineでVMを作成する

Docker Machineを使って、VirtualBox上で動くLinux VMを作成しましょう。

docker-machine create -d virtualbox <em>VM名</em>

例えばVM名がdocker01だったら、

docker-machine create -d virtualbox docker01

となります。

VMが起動したかどうか確かめてみましょう。

docker-machine ls

VMが起動している場合は、現在稼働中のVM一覧に名前が表示されるはずです。

NAME       ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
docker01   -        virtualbox   Running   tcp://192.168.99.103:2376           v1.11.2

Dockerコマンドの動作に必要な環境変数を登録しましょう。

eval $(docker-machine env <em>VM名</em>)

例えばVM名がdocker01なら、

eval $(docker-machine env docker01)

となります。

たとえば以下の環境変数が登録されているはずです。

env | grep DOCKER
DOCKER_HOST=tcp://192.168.99.103:2376
DOCKER_MACHINE_NAME=docker01
DOCKER_TLS_VERIFY=1
DOCKER_CERT_PATH=/Users/yasuyuki/.docker/machine/machines/docker01

Docker Composeでコンテナを起動する

Docker Composeを使って、プロビジョニングの対象となるコンテナを起動しましょう。今回はCentOS 7を使用します。

install.yml

centos:
image: centos:latest
container_name: centos7
entrypoint: tail -f /dev/null

最後の行の tail -f /dev/null ですが、これがないとコンテナはすぐ終了してしまいます。

では起動してみましょう。

docker-compose -f install.yml up -d

コンテナが起動したかどうか確認してみましょう。

docker-compose -f install.yml ps

上記を実行すると、一覧にコンテナ名が表示されるはずです。

Name          Command        State   Ports
-------------------------------------------
centos7   tail -f /dev/null   Up

Ansibleの設定ファイルを書く

ansible.cfgファイルでInventoryファイルのファイル名を指定します。

ansible.cfg

[defaults]
inventory = ./hosts

Inventoryファイルに書くのはsshホスト名ではなくDockerのコンテナ名です。

hosts

[docker]

centos7

試しに接続してみましょう。

ansible -i hosts centos7 -m ping -c docker

デフォルトでAnsibleはsshを使って接続しますが、-cオプションにdockerを指定しているのでDocker Connection Pluginが使われます。

centos7 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

Ansible Playbookの記述

Ansible Playbookではconnection: dockerと記述することでsshではなくDocker Connection Pluginが使われます。

setup.yml

- hosts: all
  connection: docker
  roles:
    - common

あとはDockerfileの代わりにAnsible Playbookでプロビジョニングできます。

ansible-playbook setup.yml -vvvv

docker commit

Ansible Playbookの最後でdocker commitを行えばDockerイメージを保存できます。

- name: commit changes
  local_action: shell /usr/local/bin/docker commit {{ inventory_hostname }} <em>イメージ名</em>

付録: Dockerコンテナへの接続方法

sshを使わずにDockerコンテナのbashを起動するにはdocker execを使います。

docker exec -it centos7 bash

Dockerコンテナでsshdを動かす必要がないことがお分かりいただけたでしょうか。