Docker + Chef で楽々環境作り

夏頃にDockerコンテナというベータ版がリリースされたはずですが
それとは違い、Chef-soloをキックする方法です。

そんな素晴らしい手法を紹介していた参考サイト。
Dockerイメージをchef-soloでプロビジョニングする | Developers.IO:

こういう事が発見&実行できる人がうらやましいですぞ。

まず最初の目的はSinatraの環境をさくっと作っちゃう事です。前回は手作業で作って途中でDockerコンテナをコミットしておけばいつでもそこから出来る!っとか言ってましたが、出来上がってから考えると、めんどくさいっちゅうの&管理が大変だっちゅうの。

Chefで管理した方がいいでしょう。というのも最近コード化をちょこっとやった影響もあるのでしょう。
コンテナをコミットしていくのもいつでも使いたい時に鬼速で起動できるというメリットはあるにはありますが、中の構成はハッキリ言うて時間の経過とともに分かりませんになっていく。

てなわけで、いわゆるコード化をやるっちゅうの。

RedmineのDockerfileを過去に作っているのですが

redmineのDockerfileがやっとできた

Dockerfileで進めてもいいんですが、まぁ過去の事は置いといてここ数日の流れからせっかくだしRubyで行こうぜと。楽しいし。と言うことです。

まずは原理を知るために使用するレシピは単にApacheをインストールするだけのものです。
Chefを触るのはちょっと久し振りなのでリハビリも兼ねてです。
ホストサーバーはruby gem chef knife-soloが使える環境って事で最初は省略するなり。

ツリーはこんな感じになりました。

$ tree
.
├── Dockerfile
└── chef-repo
├── cookbooks
│   └── apache
│       ├── CHANGELOG.md
│       ├── README.md
│       ├── attributes
│       ├── definitions
│       ├── files
│       │   └── default
│       ├── libraries
│       ├── metadata.rb
│       ├── providers
│       ├── recipes
│       │   └── default.rb
│       ├── resources
│       └── templates
│           └── default
├── data_bags
├── environments
├── nodes
│   └── docker.json
├── roles
├── site-cookbooks
└── solo.rb

手抜きではなくて、こっちの方が自分でもいいと思ったので、一気にコマンドオンリー(ほぼ)でいきます。

$ mkdir chef-sinatra
$ cd chef-sinatra
$ rbenv global 2.1.5
$ ruby -v
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-linux]
$ rbenv rehash
$ gem -v
2.2.2

$ gem install chef --no-ri --no-rdoc
$ knife configure
$ gem install knife-solo --no-ri --no-rdoc

クックブックを作成しよう。
$ cd chef-repo

リポジトリ作成
$ knife cookbook create apache
$ vi cookbooks/apache/recipes/default.rb
$ cat chef-repo/cookbooks/apache/recipes/default.rb
#
# Cookbook Name:: apache
# Recipe:: default
#
# Copyright 2014, YOUR_COMPANY_NAME
#
# All rights reserved - Do Not Redistribute
#
package "httpd" do
  action :install
end

service "httpd" do
  action [ :enable, :start ]
end

続いてはDockerfile作成
chef-solo -o レシピ名 だと上手くいかなかったのね。
結局のとこsolo.rbがないよ?と聞かれるので、参考サイトとほぼ同じ感じになりました。

$ cat Dockerfile
FROM centos:centos6
MAINTAINER takekentw
ENV HOME /chef-repo
ADD chef-repo /chef-repo
RUN curl -L http://www.opscode.com/chef/install.sh | bash
RUN cd ${HOME} && chef-solo -c ${HOME}/solo.rb -j ${HOME}/nodes/docker.json

では、コンテナを作ります。
$ sudo docker build -t centos:build .
Sending build context to Docker daemon 24.58 kB
Sending build context to Docker daemon
Step 0 : FROM centos:centos6
 ---> 25c5298b1a36

~~ 中略 ~~

Thank you for installing Chef!
 ---> ebd58aa8e77d
Removing intermediate container bd030c4e2254
Step 5 : RUN cd ${HOME} && chef-solo -c ${HOME}/solo.rb -j ${HOME}/nodes/docker.json
 ---> Running in 76e096bf5c8b
[2014-12-06T00:43:52+00:00] INFO: Forking chef instance to converge...
[2014-12-06T00:43:52+00:00] INFO: *** Chef 12.0.0 ***
[2014-12-06T00:44:06+00:00] INFO: service[httpd] enabled

~~ 中略 ~~

Removing intermediate container 76e096bf5c8b
Successfully built 396e4e905e33

出来上がりました。
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
centos              build               396e4e905e33        About a minute ago   418.9 MB

起動してみます。
$ sudo docker run -it -p 80 --name chef_01 centos:build /bin/bash
bash-4.1#
bash-4.1# whoami
root
bash-4.1# service httpd status
httpd dead but pid file exists
bash-4.1# service httpd start
Starting httpd: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.14 for ServerName
                                                           [  OK  ]

ここでコンテナからデタッチしました。[ Ctrl+p q ]
$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
ad3082574949        centos:build        "/bin/bash"         32 seconds ago      Up 31 seconds       0.0.0.0:49154->80/tcp     chef_01

接続テスト。
$ curl http://localhost:49154
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
        <head>
                <title>Apache HTTP Server Test Page powered by CentOS</title>
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
                <style type="text/css">

 

 

うむうむ。

では問題なさそなので、昔に作ったbaseも試してみよう。ちなみにbaseレシピとはtakekenというユーザーの作成と基本的なパッケージをインストールするものです。
やってみると結構忘れているのでリハビリはまだ続けるのです。

ほぼ忘れてましたが、外部のCookbooksを使うのでberkshelfを入れてインストールしてcookbooksを生成しときます。

$ gem install berkshelf

ひな形を作成します。
$ knife solo init .

んでこれも忘れがちになる。
過去に試した時とberksでcookbooksを取りに行く取得先も変わったようだ。

$ berks install

中身はこんな感じです。
過去に作った使いまわしなのですけどね。

$ tree
.
├── Dockerfile
└── chef-repo
├── Berksfile
├── Berksfile.lock
├── cookbooks
│   ├── selinux
│   │   ├── CHANGELOG.md
│   │   ├── README.md
│   │   ├── attributes
│   │   │   └── default.rb
│   │   ├── libraries
│   │   │   └── selinux_service_helpers.rb
│   │   ├── metadata.json
│   │   ├── providers
│   │   │   └── state.rb
│   │   ├── recipes
│   │   │   ├── _common.rb
│   │   │   ├── default.rb
│   │   │   ├── disabled.rb
│   │   │   ├── enforcing.rb
│   │   │   └── permissive.rb
│   │   ├── resources
│   │   │   └── state.rb
│   │   └── templates
│   │       └── default
│   │           └── sysconfig
│   │               └── selinux.erb
│   └── yum
│       ├── CHANGELOG.md
│       ├── README.md
│       ├── attributes
│       │   └── main.rb
│       ├── libraries
│       │   └── matchers.rb
│       ├── metadata.json
│       ├── providers
│       │   ├── globalconfig.rb
│       │   └── repository.rb
│       ├── recipes
│       │   └── default.rb
│       ├── resources
│       │   ├── globalconfig.rb
│       │   └── repository.rb
│       └── templates
│           └── default
│               ├── main.erb
│               └── repo.erb
├── data_bags
├── environments
├── nodes
│   └── docker.json
├── roles
├── site-cookbooks
│   └── base
│       ├── CHANGELOG.md
│       ├── README.md
│       ├── attributes
│       ├── definitions
│       ├── files
│       │   └── default
│       ├── libraries
│       ├── metadata.rb
│       ├── providers
│       ├── recipes
│       │   └── default.rb
│       ├── resources
│       └── templates
│           └── default
│               └── sudoers.erb
└── solo.rb


site-cookbooks/base/templates/default/sudoers.erbはsuduersファイルほぼそのままでwheelを有効にした程度です。

$ cat site-cookbooks/base/recipes/default.rb
#
# Cookbook Name:: base
# Recipe:: default
#
# Copyright 2014, YOUR_COMPANY_NAME
#
# All rights reserved - Do Not Redistribute
#
# 外部cookbookを利用してepelをインストール
yum_repository 'epel' do
description 'Extra Packages for Enterprise Linux'
#       url 'http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm'
#       gpgkey  'http://ftp.riken.jp/Linux/fedora/epel/RPM-GPG-KEY-EPEL-6'
mirrorlist 'http://mirrors.fedoraproject.org/mirrorlist?repo=epel-6&arch=$basearch'
gpgkey 'http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6'
action :create
end
# 基本的なパッケージをインストール
%w{ gcc make openssh-server kernel-devel zlib-devel openssl-devel readline-devel perl wget curl bind-utils git ntp openssh-clients rsync sysstat vim sudo }.each do |p|
package p do
action :install
end
end
# 外部cookbookを利用してselinuxを無効
selinux_state "SELinux Disabled" do
action :disabled
end

# 作業ユーザー作成
user "takeken" do
comment "takeken"
home "/home/takeken"
shell "/bin/bash"
password "$1$Sdk6GWI3$8wCs/GirgmAfyjEd3K8rp/"
supports :manage_home => true, :non_unique => false
action [:create, :manage]
end
#
group "wheel" do
action :modify
members [ 'takeken' ]
append true
end
#
template "sudoers" do
owner "root"
group "root"
path "/etc/sudoers"
mode "0440"
source "sudoers.erb"
end

$ cat Berksfile
source "https://supermarket.getchef.com"

cookbook 'yum'
cookbook 'selinux'

$ cat nodes/docker.json
{
"run_list" : [
"yum",
"recipe[selinux::disabled]",
"recipe[base]"
]
}

$ cat solo.rb
file_cache_path "/tmp/chef-solo"
cookbook_path [
"/chef-repo/site-cookbooks",
"/chef-repo/cookbooks"
]

このくらいかしらね。

ではbuildします。


$ sudo docker build -t base:base_03 .
Sending build context to Docker daemon   130 kB
Sending build context to Docker daemon
---> Running in 9013228dd96c
[2014-12-06T11:05:33+00:00] INFO: Forking chef instance to converge...
[2014-12-06T11:07:07+00:00] INFO: Report handlers complete
---> 916d8c4850fc
Removing intermediate container 9013228dd96c
Successfully built 916d8c4850fc

だいぶ端折っていますが、だいたい2分くらいですな。

ドッカー\(^o^)



$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
base                base_03             cfc1865ce4c6        About a minute ago   797.9 MB

[root@aeb9ed08e4d3 ~]# id
uid=0(root) gid=0(root) groups=0(root)
[root@aeb9ed08e4d3 ~]# ls -l /home
total 4
drwx------. 2 takeken takeken 4096 Dec  6 11:07 takeken

 

出来上がりました~。sshdってコンテナじゃあいらないのでほんとにただのリハビリになりました。もしsshを使うとして注意すべきところはPassword許可と、PAMをNoにすることでした。

作ってみた感想は欲しい環境によってVirtualBoxなりKVMなりDockerなりを使い分けた方が最終的なコストはベストな選択をするのが最もよさげです。

ではこの辺で。

次回にSinatra環境ができるかどうかは分かりません。なんとなくRubyだけで何か作ろうとしてみたりしていると思いますが、何をやるか分かりません。

 

Similar Posts:


Leave a Reply

Your email address will not be published. Required fields are marked *