Vagrant(CentOS6.5)にchefでRails4.1 + Ruby2.1.2 + Nginx + Unicorn + MySQL環境を作る
何かいつも同じ事やってる気がするので自分のためにもまとめておきます。
- Vagrant のインストール
公式サイトから最新版(執筆時は1.6.3)をダウンロードしてインストール
Vagrant - VirtualBox を公式サイトからインストール
公式サイトから最新版(執筆時は4.3.12)をダウンロードしてインストール
- Boxの追加
$ vagrant box add centos65 https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box
==> box: Adding box 'centos65' (v0) for provider: box: Downloading: https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box||<==> box: Successfully added box 'centos65' (v0) for 'virtualbox'!
その他のBoxは下記にあるので、そこから別のBOXをダウンロードしてインストールしてもOKA list of base boxes for Vagrant - Vagrantbox.es
作成出来たBOXを一応確認
$ vagrant box listcentos65 (virtualbox, 0)
- Vagrantfileの作成
どこか任意の場所にディレクトリ作成
$ mkdir -p /vagrant/develop
$ cd /vagrant/develop
$ vagrant init
$ vi Vagrantfile
# -*- mode: ruby -*-
private_networkはお好きなIPでどうぞ
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "centos65"
config.vm.network "private_network", ip: "192.168.33.11"
config.vm.synced_folder "./data", "/vagrant_data"
#config.vm.network :forwarded_port, guest: 8080, host: 8080
config.vm.provider :virtualbox do |vb|
# Use VBoxManage to customize the VM. For example to change memory:
vb.customize ["modifyvm", :id, "--memory", "512"]
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
end
Encoding.default_external = 'UTF-8'
end
vb.customizeも別に無くてもいいと思います。フォワードしたいポートがあれば、以下のようにコメントアウト外して記載してください
#config.vm.network :forwarded_port, guest: 8080, host: 8080
- Syncフォルダの生成
# config.vm.synced_folder "./data", "/vagrant_data"
この記載でここのdataフォルダをvagrant内の/vagrant_dataに結び付けたいのでディレクトリを作成しておきます
$ mkdir data - Vagrantの起動
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
default: Adapter 2: hostonly
==> default: Forwarding ports...
default: 8080 => 8080 (adapter 1)
default: 22 => 2200 (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2200
default: SSH username: vagrant
default: SSH auth method: private key
default: Warning: Connection timeout. Retrying...
==> default: Machine booted and ready!
SSHが確認できたら一度またホストに戻ります。
-
SSHの設定
起動したVMをknife-solo(後述)から簡単に扱えるようにするため、ssh-configを~/.ssh/configに追記しておく。
$ vagrant ssh-config --host development >> ~/.ssh/config
$ cat ~/.ssh/config
Host development
HostName 127.0.0.1
User vagrant
Port 2200
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile /Users/YOUR_ID/.vagrant.d/insecure_private_key
IdentitiesOnly yes
LogLevel FATAL
$ ssh development
Last login: Wed Jul 16 04:53:22 2014 from 10.0.2.2
[vagrant@vagrant-centos65 ~]$ logout
Connection to 127.0.0.1 closed. -
ホストにknife-soloのインストール
$ gem install knife-solo
$ knife configure
knife configureを実行すると色々聞かれるが、とりあえずは全部デフォルトで - knife-soloを使ってChefレポジトリを初期化
$ knife solo init chef-repo
# vagrant_develop用のcookbookの雛形を生成
$ cd chef-repo
# yumパッケージ関係
$ knife cookbook create yum -o site-cookbooks
# nginxインストールのため
$ knife cookbook create yum-epel -o site-cookbooks
# nginx
$ knife cookbook create nginx -o site-cookbooks
# git
$ knife cookbook create git -o site-cookbooks
# ps axu | grep mysql + ruby
$ knife cookbook create rbenv-ruby -o site-cookbooks
# MySQL
$ knife cookbook create mysql -o site-cookbooks
# iptables止めるため
$ knife cookbook create iptables -o site-cookbooks
全レシピはここに置いてあります。
全体的なディレクトリ構成はこんな感じです。
$ pwd
/vagrant/develop
[/vagrant/develop]$ lsVagrantfile chef-repo/ data/
[/vagrant/develop]$ cd chef-repo/
[/vagrant/develop/chef-repo]$ lsBerksfile cookbooks/ data_bags/ environments/ nodes/ roles/ site-cookbooks/
[/vagrant/develop/chef-repo]$ cd site-cookbooks/
[/vagrant/develop/chef-repo/site-cookbooks]$ lsgit/ iptables/ mysql/ nginx/ rbenv-ruby/ yum/ yum-epel/
- nodes/development.jsonを作成し編集する。
$ vi /vagrant/develop/chef-repo/nodes/development.json{
"run_list": [
"recipe[yum]",
"recipe[yum-epel]",
"recipe[git]",
"recipe[nginx]",
"recipe[mysql]",
"recipe[rbenv-ruby]",
"recipe[iptables]"
]
} - knife soloの準備
$ knife solo prepare development
Bootstrapping Chef...
Preparing... ########################################### [100%]
1:chef ########################################### [100%]
Thank you for installing Chef! - chefの実行
$ knife solo cook development
20分ぐらいたぶんかかります。
# まっさらな状態からプロビジョニングし直したい場合
$ vagrant destroy -f && vagrant up && knife solo prepare development && cd chef-repo && knife solo cook development - インストール状況の確認
vagrantに入って諸々のインストール状況を確認してみます
$ vagrant ssh
$ ps axu | grep nginx
vagrant 5495 0.0 0.1 103240 852 pts/0 S+ 05:56 0:00 grep nginx
root 9075 0.0 0.3 97180 2008 ? Ss 05:43 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx 21216 0.0 0.4 97568 2352 ? S 05:44 0:00 nginx: worker process
$ ps axu | grep mysql
vagrant 5497 0.0 0.1 103240 852 pts/0 S+ 05:56 0:00 grep mysql
$ rbenv versions
root 20302 0.0 0.0 108164 72 ? S 05:44 0:00 /bin/sh /usr/bin/mysqld_safe --datadir=/var/lib/mysql --socket=/var/lib/mysql/mysql.sock --pid-file=/var/run/mysqld/mysqld.pid --basedir=/usr --user=mysql
mysql 20552 0.1 10.5 1075884 53092 ? Sl 05:44 0:01 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
* 2.1.2 (set by /usr/local/rbenv/version)
$ ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-linux]
という事で良さそうに見えます。
- Railアプリの設定
実はここで http://192.168.33.11/ を見ても 404 Not Found なのでRailsアプリを新規で作成してみます。
実際はMacにもRuby on Railsの同じ環境が入っている人が多いと思いますのでMac上というかホストサイドから直接やってもいので、syncディレクトに設定した /vagrant_data にRailsアプリを作りたいと思います。
実はそのためにchefでnginxのドキュメントルートの設定を /vagrant_data/public/ にしてありました。
$ cat /etc/nginx/conf.d/192.168.33.11.conf
upstream unicorn {
server unix:/tmp/unicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name 192.168.33.11;
root /vagrant_data/public/;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://unicorn;
break;
}
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /vagrant_data/public/;
}
}vagrant上にて
$ cd /vagrant_data/
$ bundle initWriting new Gemfile to /vagrant_data/Gemfile
$ vi Gemfile+ gem 'rails', '4.1.1'
$ bundle install --path vendor/bundle
$ bundle exec rails new . --skip-test-unit --database=mysql
gem 'unicorn'
gem 'therubyracer', platforms: :ruby
のコメントアウトを外す
変更後のGemfile# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.1.1'
# Use mysql as the database for Active Record
gem 'mysql2'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.3'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
gem 'therubyracer', platforms: :ruby
# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring', group: :development
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
# Use unicorn as the app server
gem 'unicorn'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
# Use debugger
# gem 'debugger', group: [:development, :test]$ bundle install --without production
Fetching gem metadata from https://rubygems.org/...........
Running `bundle update` will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.
などと言われたので素直にupdateする
$ bundle update - お試しページの作成をしてみる
$ bundle exec rails g controller Roots index
※`autodetect': Could not find a JavaScript runtime.
のエラーが出たら gem 'therubyracer' が有効になってるか確認
Routeの変更
$ vi config/routes.rb
Rails.application.routes.draw do
+ root :to => 'roots#index'
+ #get 'roots/index'
$ vi config/database.yml
+ password: root_passwd
$ bundle exec rake db:create - config/unicorn.rbの作成
# -*- coding: utf-8 -*-
RAILS_ROOT = File.expand_path("../..", __FILE__)
listen "/tmp/unicorn.sock"
pid "tmp/pids/unicorn.pid"
# ワーカの数を指定
worker_processes 2
# リクエストのタイムアウト秒を指定
timeout 15
# ダウンタイムをなくすため、アプリをプレロード
#preload_app true
stdout_path File.expand_path('log/unicorn-stdout.log', ENV['RAILS_ROOT'])
stderr_path File.expand_path('log/unicorn-stderr.log', ENV['RAILS_ROOT'])
# before_fork, after_forkではUnicornのプロセスがフォークする前後の挙動を指定できる
# 以下のおまじないの詳細はドキュメント参照
before_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
old_pid = "#{server.config[:pid]}.oldbin"
unless old_pid == server.pid
begin
Process.kill :QUIT, File.read(old_pid).to_i
rescue Errno::ENOENT, Errno::ESRCH
end
end
defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end
def rails_root
require "pathname"
Pathname.new(__FILE__) + "../../"
end
/etc/nginx/conf.d/192.168.33.11.conf の記載のパスが一致すること
upstream unicorn {
server unix:/tmp/unicorn.sock fail_timeout=0;
} - 起動
$ bundle exec unicorn_rails -c config/unicorn.rb -E development -D
http://192.168.33.11/
にアクセスしてRoots#index
Find me in app/views/roots/index.html.erb
が見えれば成功
Unicornを終了したい時は直接プロセスを切るらしい
$ ps -ef | grep unicorn | grep -v grepvagrant 7685 1 0 06:46 ? 00:00:00 unicorn_rails master -c config/unicorn.rb -E development -D
vagrant 7688 7685 8 06:46 ? 00:00:26 unicorn_rails worker[0] -c config/unicorn.rb -E development -D
vagrant 7690 7685 9 06:46 ? 00:00:28 unicorn_rails worker[1] -c config/unicorn.rb -E development -D$ kill -9 7685
$ !ps
ps -ef | grep unicorn | grep -v grep
Unicornのエラーなどが見たければ
$ tail -f log/unicorn-stderr.log-
I, [2014-07-16T06:46:37.781500 #7688] INFO -- : Refreshing Gem list
I, [2014-07-16T06:46:37.784650 #7690] INFO -- : Refreshing Gem list
-
今回の全ファイルは以下のGitHubに置いてあります。