Ansible+DockerfileによるDockerイメージの作成

Dockerイメージの作成にAnsibleを使いたい場合、Packerを使う方法がよく知られています。

Packer の provisioners に Ansible を指定して Docker イメージを作成する - Qiita

ただ、Packerの売りは、Amazon EC2VirtualBox、Dockerなどの各種VM用イメージを単一のソースから作れる点だと理解しているので、Dockerイメージだけ作成できれば十分な場合は、もっとシンプルな方法で良いのではないかと思います。

また別の方法として、コンテナを立てる → 立てたコンテナに対してAnsibleを実行する → コンテナをイメージ化する、という方法もあります。これは導入の楽な方法だと思いますが、Ansible実行のためのSSHサーバが大抵必要になります。この記事にもある通り、SSHサーバには鍵の管理やセキュリティアップグレードに関する問題が付いて回るため、SSHサーバなしで済むなら、そうしたいところです。

このような場合、Ansible公式のDockerイメージを使うと、単純かつSSHサーバが不要な形で、AnsibleをつかったDockerイメージの作成ができます。ビルドするイメージ自身にAnsibleを実行させるという点では、Packerに近い方法です。このエントリでは、この公式イメージの使い方を紹介します。

Ansible公式のDockerイメージの使い方

1. 公式イメージを選ぶ

公式イメージには、Ansibleと、自分自身をAnsibleの設定対象ホストにする設定が入っています。

公式イメージはDockerHubにあり、ansible/ubuntu14.04-ansibleレポジトリansible/centos7-ansibleレポジトリが用意されています。

ansible/ubuntu14.04-ansibleレポジトリには次のタグが用意されています。ansible/centos7-ansibleレポジトリもほぼ同じです。

  • latest(develと同じ)
  • 1.7
  • 1.8
  • devel(Githubにある開発版のAnsible)
  • stable(最新のリリース版のAnsible)

1.7、1.8タグのイメージには、それぞれバージョン1.7、バージョン1.8のAnsibleが入っているはずですが、現状そうなっていないようです。pullしてみると、1.7の中にはバージョン1.8.2のAnsible、1.8の中には開発版のAnsibleが入っていました。修正されるまでは、1.7、1.8タグのイメージの使用はやめておいたほうが良いかもしれません。

使用したいレポジトリとタグを決めたら、docker pullします。

2. Ansibleを実行するDockerfileの作成

1で選んだイメージをベースイメージにして、Ansibleを実行するDockerfileを作成します。例えば次のような感じです。

ansible-docker-base/Dockerfile at master · ansible/ansible-docker-base · GitHub

FROM ansible/centos7-ansible:stable
# or, for example, FROM ansible/ubuntu14.04-ansible:stable

# Add playbooks to the Docker image
ADD ansible /srv/example/
WORKDIR /srv/example

# Run Ansible to configure the Docker image
RUN ansible-playbook site.yml -c local

# Other Dockerfile directives are still valid
EXPOSE 22 3000 80
ENTRYPOINT ["/usr/local/bin/apachectl", "-DFOREGROUND"]

ほぼ通常どおりの方法でAnsibleを実行できますが、以下の点が違っています。

  • inventoryを与える必要はありません。公式イメージの中で、localhostがAnsibleの設定対象ホストとして既に設定されているためです。あえてinventoryを与えたい場合は、いつもどおり-iオプションで与えれば、そちらが優先されます。

  • -c localオプションを付けます。AnsibleはデフォルトだとSSH(場合によってはparamiko)で設定対象ホストに接続しますが、今回は自分自身に対して設定するので、SSHは不要です。-c localオプションを付けると、Ansibleを実行したホスト上で直接モジュールの実行等をします。

  • Playbookのhostsの値には、localhostを設定します。これも、公式イメージの中でlocalhostが設定対象ホストとして設定されているためです。上記のDockerfile内で扱っているPlaybookは、次のURLから参照できます。

    ansible-docker-base/site.yml at master · ansible/ansible-docker-base · GitHub

作成したDockerfileをdocker buildすれば、イメージが作成できます。

使ってみた感想

この方法を使ってみて良いと感じた点は以下です。

  • 導入が簡単です。Packerを入れる必要もないし、Packerの設定ファイルの書き方を覚える必要もないです。

  • EXPOSE、VOLUMEなどの命令を使って、リッスンするポート、マウントポイントなどのメタ情報をDockerイメージ内に入れ込めます。Packerのドキュメントを見る限り、現状のPackerにはそのような機能はなさそうです。

  • DockerイメージにSSHサーバを入れる必要がなく、冒頭に書いたようなSSHサーバの管理問題を回避できます。

一方で、今一つと感じた点もあります。

  • Dockerイメージ内にAnsibleが入ってしまいます。Ansibleの良さとして、設定対象サーバに構成管理ツールを入れなくていいという点がありますが、この良さは失われてしまいます。

  • 上述の通り、Ansible公式のDockerイメージだと、バージョン指定が今のところできません。バージョン指定をしたい場合の次善策として、公式イメージを使わず、指定したバージョンのAnsibleをインストールするDockerfileを自分で書く、という手もあります。ごく単純ですが、例えば次のような感じです。

FROM ubuntu:14.04
MAINTAINER YOUR_NAME_AND_EMAIL

RUN apt-get -y update && \
    apt-get install -y python-yaml python-jinja2 python-paramiko python-pip
RUN mkdir /etc/ansible/ && \
    echo '[local]\nlocalhost\n' > /etc/ansible/hosts
RUN pip install ansible==1.8.2

Ansible公式イメージのDockerfileは次のURLにあるので、こちらを修正することもできます。

ansible/ansible-docker-base · GitHub

まとめ

AnsibleをつかったDockerイメージの作成方法として、Ansible公式のDockerイメージを使う方法を紹介しました。当たり前の方法のような気もしますが、DockerHubの公式イメージのダウンロード数を見ると、意外と使われていないようだったので、紹介してみました。