LoginSignup
3
4

More than 5 years have passed since last update.

PHPの環境構築手順(Chef+VirtualBox+Vagrant)

Posted at

概要

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
3
4
0

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
3
4