LoginSignup
57

More than 5 years have passed since last update.

Docker + Itamae でレシピ作成の試行錯誤を 高速化 #itamae #docker

Last updated at Posted at 2014-12-24

Docker + Itamae でレシピ作成の試行錯誤を 高速化 :rocket: #itamae #docker

概要

:whale:Docker + :sushi:Itamae でレシピ作成の試行錯誤を 高速化 :rocket: します

目的

  • Itamae のレシピ作成時間を短縮
    • 特に工夫をしないと、レシピのプロビジョニングリトライは非常に時間がかかる
      • 例えば、Ubuntu 環境に rbenv + ruby(2.1.3) + rails(4.1.8) 環境をインストールしたところ 15 分かかりました 何も工夫をしなければ再試行に + 15 分かかります
    • 普段のプログラミング同様、何事も一発で成功することは少ない。試行錯誤は発生する

※ Itamae に限った話ではないので、プロビジョニングツール全般に応用可能

前提

  • Vagrant で構築した CoreOS 環境 の上に Docker で作成した Ubuntu 14.04 のコンテナを作成し、その環境を利用します 1
  • Docker の基本操作の知識が必要です 2
  • Immutable なレシピ(冪等性を気にしない)

試行

要件

  • OS: Ubuntu 14.04
  • rbenv + ruby 2.1.3
  • rails 4.1.8
  • WebServer: WEBric
  • DB: sqlite
  • Todo アプリケーションを scaffold して rails 起動

手順

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              trusty              04c5d3b7b065        8 days ago          192.7 MB
  • 作成した Ubuntu 14.04 コンテナを確認
$ docker ps
CONTAINER ID        IMAGE                  COMMAND               CREATED             STATUS              PORTS                                        NAMES
0e50ba901b58        sample/ubuntu:trusty   "/usr/sbin/sshd -D"   4 seconds ago       Up 3 seconds        0.0.0.0:80->3000/tcp, 0.0.0.0:2222->22/tcp   berserk_ardinghelli
sudo docker run -d -p 2222:22 -p 80:3000 sample/ubuntu:trusty /usr/sbin/sshd -D
  • Rails 環境の構築まで成功したら、 Docker の commit を実行してイメージを作成します
$ docker commit <container name | id> rails_sample
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
rails_sample        latest              777715acc917        26 seconds ago      546.9 MB
sample/ubuntu       trusty              544a982d72bf        51 minutes ago      255.3 MB
ubuntu              trusty              04c5d3b7b065        8 days ago          192.7 MB
  • コンテナを停止・削除して、 commit した新規イメージでコンテナを再作成します
$ docker stop <container name | id>
$ docker rm <container name | id>
$ sudo docker run -d -p 2222:22 -p 80:3000 rails_sample /usr/sbin/sshd -D
$ docker ps
CONTAINER ID        IMAGE                 COMMAND               CREATED             STATUS              PORTS                                        NAMES
3d013b1fe510        rails_sample:latest   "/usr/sbin/sshd -D"   4 seconds ago       Up 3 seconds        0.0.0.0:80->3000/tcp, 0.0.0.0:2222->22/tcp   elegant_colden
  • rails 環境構築用のレシピに Todo アプリケーションを scaffold して、 Rails を起動するまでの記述を追加します

変更前レシピ

execute 'apt-get update' do
  command 'apt-get update -y'
end

package "build-essential" do
  action :install
end

include_recipe 'rtn_rbenv::user'

変更後レシピ

recipe.rb
execute 'apt-get update' do
  command 'apt-get update -y'
end

package "build-essential" do
  action :install
end

include_recipe 'rtn_rbenv::user'
# rails setup の include を追加
include_recipe './rails_setup.rb'
rails_setup.rb
package "libsqlite3-dev" do
  action :install
end

execute "setup rails" do
  cwd "/home/core"
  user "core"
  command <<-EOS
. /home/core/.bash_profile
rbenv rehash
rails new todo --skip-bundle
cd todo
cat << EOT >> Gemfile
gem 'execjs'
gem 'therubyracer'
EOT
bundle install
rails generate scaffold Tudu name:string estimate:integer results:integer complete:boolean
bundle exec rake db:migrate
bundle exec rails server -d
  EOS
end

※ model 名 todo は rails に予約されているので、 tudu にしています

  • itamae 実行
$ bundle exec itamae ssh -p 2222 -j node.json -i /path/to/your/key/key_name -h 172.17.8.101 -u core rails_setup.rb
  • 起動確認

rails1.png

データを2件登録してみました

rails2.png

:hourglass_flowing_sand: 実行時間の比較 (:chicken: + :chicken: => :chicken::chicken:) (:baby_chick: + :baby_chick: => :chicken:)

:chicken: + :chicken: => :chicken::chicken:

  • 途中で Docker のイメージを作成せずに、 itamae のレシピを全て再実行した場合
(15 分 × 2) + 2 分 = 32 分

:baby_chick: + :baby_chick: => :chicken:

  • 途中で Docker のイメージを作成した場合(今回紹介した手順)
15 分 + 2 分 + N 分 = 17 + N 分

N 分 は新規イメージの作成にかかる時間。
今回の例だと docker commit の実行は 10 秒程度で終わりました。
その他オペレーション込みで 1 分程度。

たった 1 回の試行でここまで差がつくので、
試行回数が多ければもっと大きな差がつくでしょう。
普段のプログラミングと同様、レシピの作成が一発で成功する方が少ないと思うのですが、
皆さんいかがでしょうか?

効率的にレシピを作成するノウハウを余り見かけないので、今回の記事を作成しました。
私は基本的に(リアルワールドで)誰とも情報交換していないこともあり、情報弱者の可能性は高く、
今回紹介した方法より優れた方法はたくさんあるかもしれません。
この記事への突込みが入って、より優れた方法を引き出すきっかけになれば、
それはそれでいいかな、と思います。

:runner: 作業フロー

  1. レシピ内の最小ステップ 3 をインクリメンタルに作成
    1. dry-run
      1. 成功
        1. 次のステップへ
      2. 失敗
        1. レシピ修正
    2. プロビジョニング実行
      1. 成功
        1. コンテナをイメージ化
        2. 新規イメージで新規コンテナ作成
      2. 失敗
        1. レシピ修正
        2. プロビジョニングに失敗したらイメージからコンテナを再作成してリトライ
  2. 新規コンテナで作業再開
  3. 全てのレシピが完成するまで 1-2 を繰り返す
  4. レシピ全体を通して実行
  5. レシピが完成したら作業用のイメージ、コンテナを破棄

:pencil: 補足

  • Vagrant + sahara などでもスナップショットを活用して作業用の中間イメージを作成できるが、 docker ほど早くない。
    vagrant + sahara のみを使っていて、 Docker を利用したことがない方は是非試してみてください。

  • レシピ試行の際の1回あたりの実行時間が長いと、単純に時間がかかるという以外に下記の弊害がある

    • :dizzy_face: 思考が途切れる
    • :sleepy: 眠くなる

試行錯誤を繰り返すたびに、作業のパフォーマンスが下がっていく。

:smiling_imp: 戯れ言

  • :whale: Docker を利用した記事で Rocket ( :rocket: ) のアイコンを使うブラックジョーク 4

外部資料

:books: 脚注

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
57