orenoblog

エンジニアになりたいExcel方眼紙erの物語

Dockerfile + chef-solo

既存のChefレシピをDockerfileに流用してみます。

Dockerコンテナそのものは状態を持たない(ステートレス)ように動かすのが良さそうなので

mysqld等のRDBMSを始めとした状態を持つ(ステートフル)なイメージは作成しません。

またserviceコマンドで利用される/etc/init.d配下のスクリプトはDockerコンテナ内では利用できないのが注意です。

↑使えました

docker run実行時に起動スクリプトを用いずプロセスを起動する必要があります。

そのためchefのserviceリソースは流用できませんが(意味ない)

package, template, attribute等のパラメータを設定するためのリソースは流用できるのでDockerイメージの作成に十分役立つと考えています。

さて作成順序は以下のとおりです。

  1. Berkshelfで利用するCookbookを取得して一つのディレクトリ内に集約する
  2. Dockerfileを作成する
  3. docker buildでDockerイメージを作成する

環境: OS X@boot2docker(docker v0.8.1)

  • 作業ディレクトリの構成

こんなかんじです。使わないcookbookが転がってるけどきにsない

orenomac$ tree -L 2
.
├── Berksfile★
├── Dockerfile★
├── Gemfile
├── README.md
├── Vagrantfile
├── cookbooks
├── data_bags
│   └── sensu
├── environments
├── nodes
│   └── webserver.json
├── roles
│   ├── sensu-client.json
│   └── sensu-server.json
├── site-cookbooks
│   ├── apache
│   ├── base-cookbooks
│   ├── mysql
│   ├── php
│   └── redis
├── solo.rb
└── vendor
  • Berkshelfでcookbooksの取得

opscodeやローカルのsite-cookbooksにあるcookbookをcookbooks/以下に取得します。

Dockerイメージには導入してないcookbookばかりで業が深い。

※ こちらはBerkshelf 3.0以降では使えません!

$ cat Berksfile
site :opscode

cookbook "yum"
cookbook "yum-centos"
cookbook "yum-epel"
cookbook "yum-percona"
cookbook "yum-elrepo"
cookbook "yum-repoforge"
cookbook "yum-ius"
cookbook "yum-pgdg"
cookbook "td-agent", git: "https://github.com/treasure-data/chef-td-agent.git"
cookbook "nginx"
cookbook "sensu"
cookbook "auditd"
cookbook 'base-cookbooks', path: 'site-cookbooks/base-cookbooks'
cookbook 'apache', path: 'site-cookbooks/apache'
cookbook 'php', path: 'site-cookbooks/php'
cookbook 'redis', path: 'site-cookbooks/redis'
cookbook 'mysql', path: 'site-cookbooks/mysql'
cookbook 'chef-docker',  git: "https://github.com/bflad/chef-docker.git"
$ berks install --path cookbooks
  • node.jsonの作成

webserverというノードアトリビュートでサーバを作ります。

epelリポジトリを導入してApachePHPをインストールするだけです。

$ cat nodes/webserver.json
{
    "run_list":
    [
        "recipe[yum-epel]",
        "recipe[apache]",
        "recipe[php]"
    ]
}
  • Dockerfileの作成

標準リポジトリよりcentosをpullしてomnibusインストーらーを使ってchef-soloをインストールしています。

Berkshelfで取得したCookbookやchef-repositoryに必要なデーター一式をDockerfileのADD構文でローカル->Dockerイメージへsyncしてるのが味噌です。

Dockerfileの構文は単純です。

また1構文毎にコミットポイントが設けられており、イメージ作成時に自動的にスナップショットが取得されるようになっています。

FROM centos
MAINTAINER buta9999

RUN curl -L http://www.opscode.com/chef/install.sh | bash
ENV CHEF_REPO /root/chef-repo
WORKDIR /root/dockerbuild
ADD cookbooks ${CHEF_REPO}/cookbooks
ADD nodes ${CHEF_REPO}/nodes
ADD solo.rb ${CHEF_REPO}/solo.rb
ADD data_bags ${CHEF_REPO}/data_bags
ADD roles ${CHEF_REPO}/roles
RUN cd ${CHEF_REPO} && chef-solo -c ${CHEF_REPO}/solo.rb -j ${CHEF_REPO}/nodes/webserver.json
  • イメージの作成

Dockerfileを作成したディレクトリを指定します。docker buildを実行するカレントにDockerfileを作るのが良さそうです。

デフォルトはcacheを利用します。成功したコミットポイントをスキップしてDockerfileの下行へ遷移していきます。

cacheを利用したくない場合は--no-cacheオプションを指定してdocker build構文を実行します。

$ docker build -t centos/webserver  .
Uploading context 3.108 MB
Uploading context
Step 0 : FROM centos
 ---> 539c0211cd76
Step 1 : MAINTAINER buta9999
 ---> Using cache
 ---> 244e53897526
Step 2 : RUN curl -L http://www.opscode.com/chef/install.sh | bash
 ---> Using cache
 ---> 11cee5f445aa
Step 3 : ENV CHEF_REPO /root/chef-repo
 ---> Using cache
 ---> ee8a750c7eb9
Step 4 : WORKDIR /root/dockerbuild
 ---> Using cache
 ---> cf42203ce8a3
Step 5 : ADD cookbooks ${CHEF_REPO}/cookbooks
 ---> ef938d1b58aa
Step 6 : ADD nodes ${CHEF_REPO}/nodes
 ---> e522db37eeb8
Step 7 : ADD solo.rb ${CHEF_REPO}/solo.rb
 ---> bd3f354c0eaf
Step 8 : ADD data_bags ${CHEF_REPO}/data_bags
 ---> 8c0dec6a99ac
Step 9 : ADD roles ${CHEF_REPO}/roles
 ---> 567cadb0a3a4
Step 10 : RUN cd ${CHEF_REPO} && chef-solo -c ${CHEF_REPO}/solo.rb -j ${CHEF_REPO}/nodes/webserver.json
 ---> Running in 89b99a2f8cf7
[2014-03-11T13:57:26-04:00] INFO: Forking chef instance to converge...
・・省略・・
[2014-03-11T14:04:20-04:00] INFO: template[/etc/php.ini] sending reload action t
o service[httpd] (immediate)
[2014-03-11T14:04:20-04:00] INFO: Processing service[httpd] action reload (php::
default line 50)
[2014-03-11T14:04:21-04:00] INFO: Processing template[/etc/php.d/redis.ini] acti
on create (php::default line 42)
[2014-03-11T14:04:21-04:00] INFO: template[/etc/php.d/redis.ini] backed up to /v
ar/chef/backup/etc/php.d/redis.ini.chef-20140311140421.056733
[2014-03-11T14:04:21-04:00] INFO: template[/etc/php.d/redis.ini] updated file co
ntents /etc/php.d/redis.ini
[2014-03-11T14:04:21-04:00] INFO: template[/etc/php.d/redis.ini] sending reload
action to service[httpd] (immediate)
[2014-03-11T14:04:21-04:00] INFO: Processing service[httpd] action reload (php::
default line 50)
[2014-03-11T14:04:21-04:00] INFO: Processing service[httpd] action restart (php:
:default line 50)
[2014-03-11T14:04:23-04:00] INFO: service[httpd] restarted
[2014-03-11T14:04:23-04:00] INFO: Chef Run complete in 384.048111735 seconds
[2014-03-11T14:04:23-04:00] INFO: Running report handlers
[2014-03-11T14:04:23-04:00] INFO: Report handlers complete
 ---> ce84df388d67
Successfully built ce84df388d67
  • イメージの確認

作成したイメージが表示されます

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos/webserver    latest              ce84df388d67        8 minutes ago       840.9 MB

制約はあるもののべんりです。

あとはpushして既に稼働しているサーバーへdocker pull.そしてEXPOSEポートの設定変更で大正義コンピューティングかと。

Dockerfileを用いてサーバを作る場合は、chefのノードアトリビュート一気通貫レシピを書くのではなく

細かい単位で素早く流用できるようにコミットポイントを設けておくのが良いと思いました。

  • ベースを作りコミット
  • サーバロールごとにイメージを作りコミット
  • 監視..とか?

眠くてよくまとまらなくなってきた。ひとまずここまで。