vargrant+chefでつくるPHP5.5+MySQL5.6+CakePHP3環境
vargrant+chefでつくるPHP5.5+MySQL5.6+CakePHP3環境
巷で話題のvagrant、chefを試してみました。
折角なのでそれぞれ最新バージョンを積極的に入れてみることにしました。(結構苦労しました…)
とりあえず手っ取り早く環境を作る手順を書いて行きます。
前提環境
- ホストマシン環境
- MacOS 10.9
- VirtualBox 4.3.6
- Vagrant 1.4.1
- Chef 11.8.2
- vagrant-omnibus 1.2.1
- ruby 2.0.0p247
- gem 2.0.3
各種ソフトウェアのインストール
VirtualBox
仮想マシンソフトです。以下URLからダウンロードしてインストールします。
https://www.virtualbox.org/wiki/Downloads
vagrant
仮想マシン(ここではVirtualBox)の管理を便利にするツールです。以下URLからダウンロードしてインストールします。
http://www.vagrantup.com/
仮想マシンの起動
今回作った設定ファイルとCakePHP3のファイルをまとめてgithubに置きましたので、とりあえずこれをcloneして進めます
mac$ git clone --recursive https://github.com/takemaru123/vagrant-cakephp3-sample.git mac$ cd vagrant-cakephp3-sample mac$ vagrant up
これだけで、vagrantのbox(仮想マシンテンプレート)がダウンロードされ、apache,php,mysqlなどが仮想マシン上に構築されます
以下のようにすると、仮想マシン上のコンソールに入ることができます
mac$ vagrant ssh
以下のように動作確認してみましょう。
centos$ cat /etc/redhat-release CentOS release 6.5 (Final) centos$ php -v PHP 5.5.7 (cli) (built: Dec 11 2013 07:13:20) Copyright (c) 1997-2013 The PHP Group Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick Rethans centos$ mysql --version mysql Ver 14.14 Distrib 5.6.15, for Linux (x86_64) using EditLine wrapper
また、ホストマシンのブラウザから、以下のURLを実行すると、Internal Server Errorとなると思います。
http://192.168.33.10/
これはCakePHP周りの設定をまだ行っていないためですが、HTTPサーバーが起動している事はわかると思います。
cakephp3の設定
cloneしたレポジトリには、CakePHPのappディレクトリは含まれていますが、CakePHP本体は含まれていません。CakePHP本体はComposerというPHPのパッケージ管理ツールを用いて導入します。
仮想マシンのコンソールに入ります。
mac$ vagrant ssh
CakePHPのappディレクトリへ移動し、Composer関係の操作を実施します。
ちなみに、ホストマシンのvagrant-cakephp3-sampleディレクトリと、仮想マシンの/vagrantディレクトリが同期されているのがここでわかるとおもいます。
centos$ cd /vagrant/app centos$ curl -sS https://getcomposer.org/installer | php centos$ php composer.phar install
これでcomposerがインストールされ、composer.jsonに記載されていた必要なライブラリ類(CakePHP本体等)がインストールされました。
この時点で以下URLをホストマシンから叩くと、CakePHPの動作確認画面を確認することができます。
http://192.168.33.10/
折角MySQLも入れたので、CakePHPの設定ファイルを書き換え、MySQLへ繋がるようにします。
この操作はホストOS(mac)、仮想マシンどちらから行っても大丈夫です。
/path/to/vagrant-cakephp3-sample/app/App/Config/app.php 又は /vagrant/app/App/Config/app.php
以下のように書き換えます。
※ファイル : vagrant-cakephp3-sample3/app/App/Config/acl.php ※抜粋 'Datasources' => [ 'default' => [ 'className' => 'Cake\\Database\\Driver\\Mysql', 'persistent' => false, 'host' => 'localhost', 'login' => 'root', 'password' => '', 'database' => 'test', 'prefix' => false, 'encoding' => 'utf8', ],
再度ブラウザからアクセスし、「Cake is able to connect to the database.」と表示されれば成功です。
これで環境が一通りできあがりました。
Vagrantファイル
ここからは各種設定ファイルやレシピについて書いていきます。
まずVagrantを使用する仮想マシン毎に、ベースとなるディレクトリを作成します。このディレクトリ以下にVagrantの設定ファイルやchefのレシピを設置します。
また、このディレクトリ内は仮想マシンとの共有ディレクトリになりますので、開発するプログラムをここに設置すると、ホストマシンのエディタでコードを書き、仮想マシンで動作させるといった流れが可能になります。
mac$ mkdir vagrant-cakephp3-sample mac$ cd vagrant-cakephp3-sample
次に、仮想マシンの設定を記述するVagrantファイルのひな形を作成します。
mac$ vagrant init
Vagrantの内容は以下のようになります。
VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = "CentOS_6.5_x86_64" config.vm.box_url = "https://github.com/2creatives/vagrant-centos/releases/download/v6.5.1/centos65-x86_64-20131205.box" config.vm.network :private_network, ip: "192.168.33.10" # cakephpを使うために必要 config.vm.synced_folder "./", "/vagrant", mount_options: ['dmode=777', 'fmode=666'] config.omnibus.chef_version = :latest config.vm.provision :chef_solo do |chef| chef.cookbooks_path = "./site-cookbooks" chef.add_recipe "base" chef.add_recipe "mysql56" chef.add_recipe "php55" chef.json = { httpd: { port: 80, docroot: "/vagrant/app/webroot" }, php: { timezone: "Asia/Tokyo" }, mysql: { password: '' }, } end end
以下抜粋です。
config.vm.box = "CentOS_6.5_x86_64" config.vm.box_url = "https://github.com/2creatives/vagrant-centos/releases/download/v6.5.1/centos65-x86_64-20131205.box"
CentOSがインストールされている仮想マシンをネット上から取ってくるように設定しています。(有志の方が公開しているものです)
一度ダウンロードすればPC内にテンプレート(box)として保存され、また同じboxから仮想マシンを作る場合は、ローカルに保持しているboxが使われるようになります。
config.vm.network :private_network, ip: "192.168.33.10"
ホストマシン(mac)から仮想マシンにアクセスする際のIPアドレスを設定しています。
仮想マシンを複数立ち上げる場合などは、適宜変更する必要があります。
config.omnibus.chef_version = :latest
今回使ったboxにはchefがインストールされていないため、omnibusを使い、仮想マシンにchefを仮想マシンに自動インストールします。
chef.cookbooks_path = "./site-cookbooks" chef.add_recipe "base" chef.add_recipe "mysql56" chef.add_recipe "php55"
仮想マシンが起動した後に実行するchefのレシピを定義しています。
ここではbase,mysql56,php55の3つのレシピが実行されます。
chef.json = { httpd: { port: 80, docroot: "/vagrant/app/webroot" }, php: { timezone: "Asia/Tokyo" }, mysql: { password: '' }, }
chef実行時の変数をここで指定しています。
レシピ:base
chefのレシピを記述して行きます。
まずはレシピのベースとなるテンプレートを作成します。
mac$ knife cookbook create base -o site-cookbooks/
自分で作成したレシピは、site-cookbooksというディレクトリに設置するのが決まりのようです。
このコマンドで、
vagrant-cakephp3-sample/site-cookbooks/base
というディレクトリが作成され、更にその中に複数のディレクトリやファイルが作成されました。
レシピの内容を記述していきます。
※ファイル : vagrant-cakephp3-sample/site-cookbooks/base/recipes/default.rb # スワップ領域作成 # 参考:http://qiita.com/naoya@github/items/2059e3755962e907315e bash 'create swapfile' do user 'root' code <<-EOC dd if=/dev/zero of=/swap.img bs=1M count=1024 && chmod 600 /swap.img mkswap /swap.img EOC only_if "test ! -f /swap.img -a `cat /proc/swaps | wc -l` -eq 1" end mount '/dev/null' do # swap file entry for fstab action :enable # cannot mount; only add to fstab device '/swap.img' fstype 'swap' end bash 'activate swap' do code 'swapon -ae' only_if "test `cat /proc/swaps | wc -l` -eq 1" end # iptables無効 service "iptables" do action [:stop, :disable] end # yum関係 %w{gcc make wget telnet readline-devel ncurses-devel gdbm-devel openssl-devel zlib-devel libyaml-devel httpd}.each do |p| package p do action :install end end # httpd設定 service "httpd" do action [:start, :enable] end template "httpd.conf" do path "/etc/httpd/conf/httpd.conf" source "httpd.conf.erb" mode 0644 notifies :restart, 'service[httpd]' end
baseレシピでは、OSの基本設定や、CentOS標準のyumコマンドでインストールできるパッケージのインストール、Apacheのインストール、設定を行うようにしています。
以下抜粋です。
# スワップ領域作成 # 参考:http://qiita.com/naoya@github/items/2059e3755962e907315e bash 'create swapfile' do user 'root' code <<-EOC dd if=/dev/zero of=/swap.img bs=1M count=1024 && chmod 600 /swap.img mkswap /swap.img EOC only_if "test ! -f /swap.img -a `cat /proc/swaps | wc -l` -eq 1" end mount '/dev/null' do # swap file entry for fstab action :enable # cannot mount; only add to fstab device '/swap.img' fstype 'swap' end bash 'activate swap' do code 'swapon -ae' only_if "test `cat /proc/swaps | wc -l` -eq 1" end
今回利用したboxではスワップ領域が無かったため、念のためスワップ領域を作成しています。
# iptables無効 service "iptables" do action [:stop, :disable] end
開発環境なのでiptablesは無効とします。
ここではiptablesの停止、また、次回仮想マシンOS起動時にはiptablesを起動しないようにしています。
# yum関係 %w{gcc make wget telnet readline-devel ncurses-devel gdbm-devel openssl-devel zlib-devel libyaml-devel httpd}.each do |p| package p do action :install end end
CentOS標準のyumコマンドで導入すべきパッケージをここでインストールしています。
本来であればpackageリソースはOSに合わせて、実際に実行されるコマンドがyumだったりapt-getだったりしますが、ここではCentOSで実行される前提で書いてしまっています。
# httpd設定 service "httpd" do action [:start, :enable] end
Apacheの起動、OS起動時に自動的にApacheが起動するように設定しています。
template "httpd.conf" do path "/etc/httpd/conf/httpd.conf" source "httpd.conf.erb" mode 0644 notifies :restart, 'service[httpd]' end
chefのtemplateという機能を使って、httpd.confを設定しています。
また、設定変更後はnotifiesを使って、Apacheを再起動するように指定しています。
httpd.confはchefのtemplateで設定しているため、templateの設定を行います。
こののファイルのベースは、実際インストールしたApacheのhttpd.conf(仮想マシンの/etc/httpd/conf/httpd.conf)の内容です。
必要なところだけ以下の様に変数を埋め込める形にします。
※ファイル : vagrant-cakephp3-sample/site-cookbooks/base/templates/default/httpd.conf.erb ※抜粋 Listen <%= node[:httpd][:port] %> DocumentRoot "<%= node[:httpd][:docroot] %>" <Directory "<%= node[:httpd][:docroot] %>"> 〜 </Directory>
node〜で指定した変数は、Vagrantファイルのchef.json = 〜で設定した内容が読み込まれます。
これにより、可変部分のみをVagrantファイルに記述することができます。
レシピ:mysql56
MySQL5.6をインストールするレシピを作成します。
baseとは別のcookbookにした理由はなんとなくです。
概要としては、OS標準やサードパーティを含め、yumでMySQL5.6を導入する方法がないため、Oracleが公式で配布しているrpmパッケージをダウンロードし、インストールする方式をとっています。
レシピファイルは以下のようになります。
vagrant-cakephp3-sample/site-cookbooks/mysql56/recipes/default.rb
大部分は以下のページをほぼそのまま使わせていただきましたので、詳細はそちらをご参照ください。
MySQL5.6のchefの書き方の決定版が出来たので公開する。 - nigoblog
以下、追加した内容をご紹介します。
# サーバー起動 service "mysql" do action [:start, :enable] end
MySQLサーバーを起動し、仮想マシン起動時にも自動起動するように設定します。
# my.cnf template "my.cnf" do path "/usr/my.cnf" source "my.cnf.erb" mode 0644 notifies :restart, 'service[mysql]' end
Apache設定時にも利用したtemplate機能を使って、my.cnfを設定します。
# 初期パスワード設定 # 参考:http://blog.youyo.info/blog/2013/07/11/chef-mysql56/ script "Secure_Install" do interpreter 'bash' user "root" not_if "mysql -u root -p#{node[:mysql][:password]} -e 'show databases'" code <<-EOL export Initial_PW=`head -n 1 /root/.mysql_secret |awk '{print $(NF - 0)}'` mysql -u root -p${Initial_PW} --connect-expired-password -e "SET PASSWORD FOR root@localhost=PASSWORD('#{node[:mysql][:password]}');" mysql -u root -p#{node[:mysql][:password]} -e "SET PASSWORD FOR root@'127.0.0.1'=PASSWORD('#{node[:mysql][:password]}');" mysql -u root -p#{node[:mysql][:password]} -e "FLUSH PRIVILEGES;" EOL end
chef実行時に、MySQLのパスワードを自動設定するようにしています。
MySQL5.6は初期パスワードとしてランダムパスワードが設定されるため、まずはそれを利用してパスワード設定コマンドを実行します。
パスワードはVagrantファイルで設定できるようにしています。
また、参考サイトではMySQLクライアントのみをインストールしておりますが、こちらではServerのインストールにも対応するため、attributeを以下にようにしました。
※ファイル : vagrant-cakephp3-sample/site-cookbooks/mysql56/attribute/default.rb versions = "5.6.15-1.el6.x86_64" default['mysql']['versions'] = versions default['mysql']['file_name'] = "MySQL-#{versions}.rpm-bundle.tar" default['mysql']['remote_uri'] = "http://ftp.jaist.ac.jp/pub/mysql/Downloads/MySQL-5.6/MySQL-#{versions}.rpm-bundle.tar" default['mysql']['rpm'] = [ { :rpm_file => "MySQL-server-#{versions}.rpm", :package_name => "MySQL-server" }, { :rpm_file => "MySQL-client-#{versions}.rpm", :package_name => "MySQL-client" }, { :rpm_file => "MySQL-devel-#{versions}.rpm", :package_name => "MySQL-devel" }, { :rpm_file => "MySQL-shared-#{versions}.rpm", :package_name => "MySQL-shared" } ]
レシピ:php55
PHP5.5をインストールするレシピを作成します。
baseとは別のcookbookにした理由はなんとな(ry
概要としましては、こちらもOS標準のyumレポジトリには無いので、remiというサードパーティのレポジトリからインストールするようにしています。
まずはattributeを以下のように定義します。
※ファイル : vagrant-cakephp3-sample/site-cookbooks/php55/attribute/default.rb default['remi']['file_name'] = "remi-release-6.rpm" default['remi']['remote_uri'] = "http://rpms.famillecollet.com/enterprise/remi-release-6.rpm"
レシピファイルは以下のようになります。
※ファイル : vagrant-cakephp3-sample/site-cookbooks/php55/recipe/default.rb # remi repository導入 remote_file "/tmp/#{node['remi']['file_name']}" do source "#{node['remi']['remote_uri']}" not_if { ::File.exists?("/tmp/#{node['remi']['file_name']}") } end package node['remi']['file_name'] do action :install provider Chef::Provider::Package::Rpm source "/tmp/#{node['remi']['file_name']}" end # phpインストール %w{php php-devel php-mbstring php-mcrypt php-mysql php-phpunit-PHPUnit php-pecl-xdebug}.each do |p| package p do action :install options "--enablerepo=remi --enablerepo=remi-php55" end end # php設定 template "php.ini" do path "/etc/php.ini" source "php.ini.erb" mode 0644 notifies :restart, 'service[httpd]' end
以下抜粋です。
# remi repository導入 remote_file "/tmp/#{node['remi']['file_name']}" do source "#{node['remi']['remote_uri']}" not_if { ::File.exists?("/tmp/#{node['remi']['file_name']}") } end package node['remi']['file_name'] do action :install provider Chef::Provider::Package::Rpm source "/tmp/#{node['remi']['file_name']}" end
remi導入のためのrpmパッケージをダウンロードし、インストールしています。
# phpインストール %w{php php-devel php-mbstring php-mcrypt php-mysql php-phpunit-PHPUnit php-pecl-xdebug}.each do |p| package p do action :install options "--enablerepo=remi --enablerepo=remi-php55" end end
PHP関係のパッケージをインストールします。
options "--enablerepo=remi --enablerepo=remi-php55" を指定するところがキモです。
# php設定 template "php.ini" do path "/etc/php.ini" source "php.ini.erb" mode 0644 notifies :restart, 'service[httpd]' end
templateの仕組みを使い、php.iniを設定しています。
また、php.ini変更時はApacheを再起動するようにしています。
※ファイル : vagrant-cakephp3-sample/site-cookbooks/php53/templates/default/php.ini.erb ※抜粋 date.timezone = '<%= node[:php][:timezone] %>'
timezoneの設定をVagrantファイル側から読み込むようにしています。
まとめ
長くなりましたが、Vagrant,chefを使い、CakePHP3を動作させる環境を作るところまでを行いました。
手探り状態で来たため、ここまでくるのに数日を費やしてしまいました。
自分でレシピを書いていこうとすると、最初はいろいろ試行錯誤の連続になるようです。
しかしインフラや開発環境をコード化して、git管理できるというのは大変魅力を感じました。
チーム開発の場合は開発環境を統一できますし、私の場合は自宅のデスクトップ機やノートなどの複数マシン間で開発環境を統一したいという目論見もありました。
今後はVagrant+chefの開発環境を布教すると共に、さくらVPSやEC2等ももchefで管理していけたらと思います。