読者です 読者をやめる 読者になる 読者になる

will and way

ただの自分用メモを人に伝える形式で書くことでわかりやすくまとめてるはずのブログ

Vagrant上でDockerコンテナプロビジョニングとDockerコンテナプロビジョニング環境のプロビジョニングにAnsibleを使う

タイトルが長い笑

この記事はQiita Advent Calendar 2015 23日目の記事です。 前日はunchemistさんのここがヘンだよAnsible (ハマりどころと対策について)でした。

qiita.com

Ansibleのカレンダーが空いてたので投稿いたしましたが、もしかしたらPackerとかDockerの割合が多いかもしれませんが、ご容赦くだされば幸いです!!

今回は、

  1. Vagrant上でPackerでDockerコンテナのプロビジョニング環境整備をプロビジョニングする際にAnsibleを使う
  2. 1で作った環境上で、さらにPackerでDockerコンテナをプロビジョニングするさいにAnsibleを使う

という2点を行ったメモを紹介します。

記事の対象者

  • Ansible, Docker, Packerを触りはじめたばかり

全体像

f:id:matsuokah:20151223130449p:plain

環境

Apps Version
Mac OSX 10.11
VirtualBox 5.0.10 r104061
Vagrant 1.8.0
Docker 1.7.1
Ansible 1.7.1
Packer 0.8.6

まず、MacOSX上では狭義の意味ではDockerは動かないですが Installation on Macの通りにすれば、ハイパーバイザー上にDockerをホスティング&フックするラッパーツールを使うことができます

しかし、自分の環境では、Packerでプロビジョニング中に進まないという現象に陥いったことや、Vagrant完結にしてホストを汚さないようにしたかったためVagrant上で構築しました。
また、Centos6系ではkernelが2.6ですが、Dockerを起動するには3系である必要があります。

Vagrant起動時にDockerコンテナプロビジョニング環境を整える

DockerコンテナプロビジョニングにはPackerを使うので、具体的にはCentosにDockerとPackerをインストールします。

AnsibleによるVagrantBoxのプロビジョニングポイント

VagrantfileにAnsibleでプロビジョニングする旨とplaybook.ymlを指定すればOK

あとは、playbookとrolesを拡充していくのみです。

サンプル

github.com

git clone git@github.com:matsuokah/vagrant-docker-provisioner.gitしてディレクトリでvagrant upすればpackerが使えるイメージが立ち上がります。冪等性は担保してないのでご注意ください。

ファイルツリー

├── README.md
├── Vagrantfile
└── provisioning
    ├── playbook.yml
    └── roles
        ├── common
        │   └── tasks
        │       └── main.yml
        ├── docker
        │   ├── handlers
        │   │   └── main.yml
        │   └── tasks
        │       └── main.yml
        └── packer
            ├── files
            │   └── packer_0.8.6_linux_amd64.zip
            └── tasks
                └── main.yml

VagrantfileがあるディレクトリにAnsibleの設定を置いただけですね。

Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  config.vm.box = "centos7"
  config.vm.box_url = "https://github.com/holms/vagrant-centos7-box/releases/download/7.1.1503.001/CentOS-7.1.1503-x86_64-netboot.box"

  # provisioning
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "provisioning/playbook.yml"
    ansible.sudo = true
  end
end

Ansibleのモジュール実行の前提をしらずにハマる

Ansibleではモジュールを実行するためには、そのモジュールで使われるコマンドがインストールされているという前提を満たす必要があります。 例えばUnarcive moduleでは

Note
requires tar/unzip command on target host

のように、ホスト上でtar及び、unzipコマンドが使える必要があると言及しています。

TASK: [packer | Unarchive packer to installation directory] *******************  
failed: [default] => {"failed": true}  
msg: Failed to find handler to unarchive. Make sure the required command to extract the file is installed.

上記のようなエラーが出た場合、commonにはそれらの前提を整えるプロビジョニングを書くなどするといいかもです。これを知らないと、ただモジュールを実行しているだけなのに・・・とすこしハマリます。

PackerでDockerコンテナのプロビジョニングを行う

サンプル

github.com

後は、先程作ったpackerが実行可能なbox上で↑をcloneしてpacker build template.jsonとするだけです。

template.json

{
  "_comment": "Docker provisioner",
  "builders": [
    {
      "type": "docker",
      "image": "centos:7",
      "export_path": "/vagrant/image.tar"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "inline": [
        "yum localinstall -y http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm",
        "yum install -y python-pip python-devel libstdc++ gcc gcc-c++ kernel-devel",
        "pip install ansible"
      ],
    },
    {
      "type": "ansible-local",
      "playbook_file": "ansible/playbook.yml",
      "role_paths": ["ansible/roles/common", "ansible/roles/nginx"],
      "staging_directory": "/tmp/docker-packer-provisioner"
    }
  ]
}

やっていることは、

  1. centosコンテナをpull
  2. Ansibleをインストール
  3. Ansible実行

例ではnginxをインストールしてみました。

/vagrant/image.tarとしてexportしたので

$ cat /vagrant/image.tar | docker import - centos_nginx:latest
$ docker run -d -i -t --name my_nginx centos_nginx:lagest "/bin/bash"

とでもすればnginxが起動できるかと思います。

動作確認するためにはVagrantfileでdockerへのポート転送のすればできるでしょう。

以上、「Vagrant上でDockerコンテナプロビジョニングとDockerコンテナプロビジョニング環境のプロビジョニングにAnsibleを使う」でした!!

リファレンス