概要
Vagrant+VirtualBox+Chefで開発環境を構築する
分類 | 構築する環境 | バージョン |
---|---|---|
OS | centos | 6.5 |
WEBサーバー | Nginx | 1.0.15 |
言語 | PHP | 5.5.34 |
DB | PostgreSQL | 8.4.20 |
前提
- ホストOSがOSX(mac)
- ホストOSにRubyがインストールされていること
ホストOSの環境作成
Vagrantのインストール
VirtualBoxのインストール
ホスト
$ sudo gem install bundler
$ bundle init
Gemfile
source "https://rubygems.org"
gem 'chef'
gem 'knife-solo'
gem 'berkshelf'
ホスト
$ mkdir php_env_by_chef
$ cd php_env_by_chef
ホスト
$ bundle install
ChefSoloの為のファイル作成
Vagrantfileの作成と初期設定
ホスト
$ vagrant plugin install vagrant-omnibus
$ vagrant init
$ vi Vagrantfile
Vagrantfile
Vagrant.configure(2) do |config|
config.vm.hostname = "guest"
# config.vm.box = "ボックス名"
# config.vm.box_url = "ボックスURL"
config.vm.box = "opscode-centos-6.5"
config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box"
# IPアドレスの設定
config.vm.network "private_network", ip: "192.168.33.10"
# vagrant-omnibusの有効化
config.omnibus.chef_version = :latest
end
(注)以下のエラーが出たら
The following berks command failed to execute:
/usr/local/bin/berks --version --format json
The stdout and stderr are shown below:
stdout:
stderr: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/dependency.rb:296:in `to_specs': Could not find 'berkshelf' (>= 0) among 58 total gem(s) (Gem::LoadError)
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/dependency.rb:307:in `to_spec'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_gem.rb:47:in `gem'
from /usr/local/bin/berks:22:in `<main>'
Vagrantfileに以下を追加
(参考)http://qiita.com/futoase/items/a1b5f7e32da847ba6595
Vagrantfile
Vagrant.configure(2) do |config|
config.berkshelf.enabled = false
end
ChefSoloに必要なファイルを展開する
ホスト
$ knife solo init .
Nginxの導入
クックブックの作成
ホスト
$ bundle exec knife cookbook create nginx -o ./site-cookbooks
レシピの作成
ホスト
$ vi site-cookbooks/nginx/recipes/default.rb
site-cookbooks/nginx/recipes/default.rb
include_recipe "yum-epel"
package "nginx" do
action :install
end
service "nginx" do
action [ :enable, :start ]
supports :status => true, :restart => true, :reload => true
end
Berksfileの追加とクックブックの更新
ホスト
$ vi Berksfile
Berksfile
source "https://api.berkshelf.com"
cookbook "yum-epel"
cookbook "nginx", path: "./site-cookbooks/nginx"
ホスト
$ bundle exec berks vendor cookbooks
run_listの作成
ホスト
$ vi Vagrantfile
Vagrantfile
Vagrant.configure(2) do |config|
...
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = ["./cookbooks", "./site-cookbooks"]
chef.run_list = %w[
recipe[yum-epel]
recipe[nginx]
]
end
end
Vagrantの起動とプロビジョンの実行
ホスト
$ vagrant up --provision
PHPを導入
クックブックの作成
ホスト
$ bundle exec knife cookbook create php-env -o ./site-cookbooks
レシピの作成
ホスト
$ vi site-cookbooks/php-env/recipes/default.rb
site-cookbooks/php-env/recipes/default.rb
%w{php-fpm}.each do |pkg|
package pkg do
action :install
notifies :restart, "service[php-fpm]"
end
end
service "php-fpm" do
action [:enable, :start]
end
template "php.ini" do
source "php.ini.erb"
path "/etc/php.ini"
user node['php_env']['user']
group node['php_env']['user']
mode 0644
notifies :restart, "service[php-fpm]"
end
PHPの設定ファイルの作成
(注)今回の場合、事前にPHPのプロビジョンを実行しphp.iniのファイルを以下ディレクトリにコピーしている
ホスト
$ vi site-cookbooks/php-env/templates/default/php.ini.erb
site-cookbooks/php-env/templates/default/php.ini.erb
...
; PHP's default character set is set to empty.
; http://php.net/default-charset
// チェックを外す
default_charset = "UTF-8"
; Always populate the $HTTP_RAW_POST_DATA variable. PHP's default behavior is
; to disable this feature. If post reading is disabled through
; enable_post_data_reading, $HTTP_RAW_POST_DATA is *NOT* populated.
...
Attributeの初期値を設定
ホスト
$ vi site-cookbooks/php-env/attributes/default.rb
site-cookbooks/php-env/attributes/default.rb
default["php_env"]["user"] = "root"
Berksfileの追加とクックブックの更新
ホスト
$ vi Berksfile
Berksfile
source "https://api.berkshelf.com"
...
cookbook "php-env", path: "./site-cookbooks/php-env"
ホスト
$ bundle exec berks vendor cookbooks
run_listの追加
ホスト
$ vi Vagrantfile
Vagrantfile
Vagrant.configure(2) do |config|
...
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = ["./cookbooks", "./site-cookbooks"]
chef.run_list = %w[
recipe[yum-epel]
recipe[nginx]
recipe[php-env]
]
end
...
end
プロビジョンの実行
ホスト
$ vagrant provision
PHP-FPMとNginxを連携する
Nginxレシピの編集
ホスト
$ vi site-cookbooks/nginx/recipes/default.rb
site-cookbooks/nginx/recipes/default.rb
...
template 'nginx.conf' do
path '/etc/nginx/nginx.conf'
source "nginx.conf.erb"
owner 'root'
group 'root'
mode '0644'
notifies :reload, "service[nginx]"
end
Nginxの設定ファイルの作成
ホスト
$ vi site-cookbooks/nginx/templates/default/nginx.conf.erb
site-cookbooks/nginx/templates/default/nginx.conf.erb
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80 default_server;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm index.php;
}
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
<% if node['nginx']['env'].include?("php") %>
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
<% end %>
}
}
Attributeの初期値の設定
ホスト
$ vi site-cookbooks/nginx/attributes/default.rb
site-cookbooks/nginx/attributes/default.rb
default['nginx']['env'] = []
クックブックの更新
ホスト
$ bundle exec berks vendor cookbooks
Attributeの追加
ホスト
$ vi Vagrantfile
Vagrantfile
Vagrant.configure(2) do |config|
...
config.vm.provision :chef_solo do |chef|
chef.json = {
nginx: {
env: ["php"]
}
}
...
end
end
プロビジョンの実行
ホスト
$ vagrant provision
OPcacheを導入(php-pecl-zendopcacheパッケージの追加)
php_envレシピの編集
ホスト
$ vi site-cookbooks/php-env/recipes/default.rb
site-cookbooks/php-env/recipes/default.rb
...
# php-pecl-zendopcacheを追加
%w{php-fpm php-pecl-zendopcache}.each do |pkg|
package pkg do
action :install
notifies :restart, "service[php-fpm]"
end
end
...
クックブックの更新
ホスト
$ bundle exec berks vendor cookbooks
プロビジョンの実行
ホスト
$ vagrant provision
PHPの接続確認
ゲストOSにログインしてPHPファイルの作成
ホスト
$ vagrant ssh
ゲスト
$ sudo vi /usr/share/nginx/html/index.php
/usr/share/nginx/html/index.php
<?php
phpinfo();
?>
ブラウザで確認
http://192.168.33.10/index.php
(注)80番ポートが解放されていない場合一旦iptablesを停止して確認
ゲスト
$ sudo /etc/rc.d/init.d/iptables stop
PHP5.5をインストール
レシピの作成
ホスト
$ vi site-cookbooks/php-env/recipes/php55.rb
site-cookbooks/php-env/recipes/php55.rb
yum_repository 'remi' do
description 'Les RPM de Remi - Repository'
baseurl 'http://rpms.famillecollet.com/enterprise/6/remi/x86_64/'
gpgkey 'http://rpms.famillecollet.com/RPM-GPG-KEY-remi'
fastestmirror_enabled true
action :create
end
yum_repository 'remi-php55' do
description 'Les RPM de remi de PHP 5.5 pour Enterprise Linux 6'
baseurl 'http://rpms.famillecollet.com/enterprise/6/php55/$basearch/'
gpgkey 'http://rpms.famillecollet.com/RPM-GPG-KEY-remi'
fastestmirror_enabled true
action :create
end
%w{php php-fpm php-opcache}.each do |pkg|
package pkg do
action :install
notifies :restart, "service[php-fpm]"
end
end
service "php-fpm" do
action [:enable, :start]
end
template "php.ini" do
source "php.ini.erb"
path "/etc/php.ini"
user node['php_env']['user']
group node['php_env']['user']
mode 0644
notifies :restart, "service[php-fpm]"
end
クックブックの更新
ホスト
$ bundle exec berks vendor cookbooks
run_listの追加
ホスト
$ vi Vagrantfile
Vagrantfile
Vagrant.configure(2) do |config|
config.vm.provision :chef_solo do |chef|
chef.run_list = %w[
recipe[yum]
recipe[yum-epel]
recipe[nginx]
recipe[php-env::php55]
]
end
end
プロビジョンの実行
(注)先にインストールしたPHPを削除している
ホスト
$ vagrant ssh -c "sudo yum remove php* -y"
$ vagrant provision
PostgreSQLの導入
クックブックの作成
ホスト
$ bundle exec knife cookbook create postgresql -o ./site-cookbooks
レシピの作成
(参考)DBユーザーの作成
ホスト
$ vi site-cookbooks/postgresql/recipes/default.rb
site-cookbooks/postgresql/recipes/default.rb
package "postgresql" do
action :install
end
package "postgresql-server" do
action :install
end
execute "postgresql-init" do
not_if "test -f /var/lib/pgsql/data/postgresql.conf"
command "service postgresql initdb"
action :run
end
service "postgresql" do
action [:enable, :start]
end
execute "create-database-user" do
user "postgres"
exist = <<-EOH
psql -U postgres -c "select * from pg_user where usename='#{node['postgresql']['user']}'" | grep -c #{node['postgresql']['user']}
EOH
command "createuser -U postgres -SdR #{node['postgresql']['user']}"
not_if exist
end
Attributeの初期値の設定
ホスト
$ vi site-cookbooks/postgresql/attributes/default.rb
site-cookbooks/postgresql/attributes/default.rb
default['postgresql']['super_user'] = "postgres"
default['postgresql']['user'] = "vagrant"
Berksfileの追加とクックブックの更新
ホスト
$ vi Berksfile
Berksfile
...
cookbook "postgresql", path: "./site-cookbooks/postgresql"
ホスト
$ bundle exec berks vendor cookbooks
run_listの追加
ホスト
$ vi Vagrantfile
Vagrantfile
Vagrant.configure(2) do |config|
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = ["./cookbooks", "./site-cookbooks"]
chef.json = {
nginx: {
env: ["php"]
}
}
chef.run_list = %w[
recipe[yum]
recipe[yum-epel]
recipe[nginx]
recipe[php-env::php55]
recipe[postgresql]
]
end
end
プロビジョンの実行
ホスト
$ vagrant provision
PHPとPostgreSQLの接続
php55レシピの更新(php-pgsqlパッケージの追加)
ホスト
$ vi site-cookbooks/php-env/recipes/php55.rb
site-cookbooks/php-env/recipes/php55.rb
...
#php-pgsqlを追加
%w{php php-fpm php-opcache php-pgsql}.each do |pkg|
package pkg do
action :install
end
...
postgresqlレシピにテンプレートの追加
ホスト
$ vi site-cookbooks/postgresql/recipes/default.rb
site-cookbooks/postgresql/recipes/default.rb
...
template "pg_hba.conf" do
path "/var/lib/pgsql/data/pg_hba.conf"
source "pg_hba.conf.erb"
user node['postgresql']['super_user']
mode "0644"
notifies :restart, "service[postgresql]"
end
PostgreSQLのクライアント認証設定ファイルの作成
(参考)pg_hba.confファイル
ホスト
$ vi site-cookbooks/postgresql/templates/default/pg_hba.conf.erb
site-cookbooks/postgresql/templates/default/pg_hba.conf.erb
# TYPE DATABASE USER CIDR-ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all 127.0.0.1/32 trust
# IPv6 local connections:
host all all ::1/128 trust
クックブックの更新
ホスト
$ bundle exec berks vendor cookbooks
プロビジョンの実行
ホスト
$ vagrant provision
接続テスト
ホスト
$ vagrant ssh
ゲスト
$ createdb test
$ vi /usr/share/nginx/html/pgsql_connection_test.php
/usr/share/nginx/html/pgsql_connection_test.php
<?php
$dsn = 'pgsql:dbname=test host=localhost port=5432';
$user = 'vagrant';
$password = '';
try{
$dbh = new PDO($dsn, $user, $password);
echo 'PostgreSQLと接続成功';
}catch (PDOException $e){
echo('Error:'.$e->getMessage());
die();
}
ブラウザで確認
http://192.168.33.10/pgsql_connection_test.php
ホストOSとゲストOSのディレクトリを同期する(rsync)
(参考) Rsync Synced Folder
クックブックの作成
ホスト
$ bundle exec knife cookbook create rsync -o ./site-cookbooks
レシピの作成
ホスト
$ vi site-cookbooks/rsync/recipes/default
site-cookbooks/rsync/recipes/default
package "rsync" do
action :install
end
Berksfileの追加とクックブックの更新
ホスト
$ vi Berksfile
Berksfile
...
cookbook "rsync", path: "./site-cookbooks/rsync"
ホスト
$ bundle exec berks vendor cookbooks
run_listの追加と同期するディレクトリの設定
ホスト
$ vi Vagrantfile
Vagrantfile
Vagrant.configure(2) do |config|
config.vm.provision :chef_solo do |chef|
chef.run_list = %w[
...
recipe[rsync]
]
end
config.vm.synced_folder "/Users/#{ENV['USER']}/php_app", "/usr/share/nginx/html/", type: "rsync", create: true, owner: "vagrant", group: "vagrant", rsync__exclude: [".git/", "vendor/"]
end
プロビジョニングの実行
ホスト
$ vagrant provision
同期処理の自動化
ホスト
$ vagrant rsync-auto