vagrant環境自動構築 – php, nginx, PostgreSQL

vagrant環境自動構築 – php, nginx, PostgreSQL

はじめに

このページで得られるもの

vagrant環境の設定方法を習得

前提

  • VirtualBox, vagrantをインストール済み
  • ホームディレクトリにソースディレクトリ(Sites), vagrant設定ディレクトリ(Vagrant)が存在すること ※ディレクトリパスは任意です。
  • 開発環境用の自己証明書を作成していること(今回はmkcertコマンドで作成)

開発環境

macOS Catalina(version 10.15.5)

設定ファイル

適宜読み替えてください

Vagrant/test.com/Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|

  # centos 8.1 install
  config.vm.box = "centos/8"
  config.vm.box_url = "http://cloud.centos.org/centos/8/x86_64/images/CentOS-8-Vagrant-8.1.1911-20200113.3.x86_64.vagrant-virtualbox.box"

  # boxの名前
  config.vm.define "test"

  # プライベートネットワーク(自身のみアクセス可のipアドレス指定)
  config.vm.network "private_network", ip: "192.168.33.10"

  # スマホや別端末からアクセス許可(とりあえず同じWifi内の端末)
  config.vm.network :public_network, bridge: 'en0: Wi-Fi (AirPort)'

  # /etc/hostsへ自動書き込み(box起動中の間のみ)
  config.vm.hostname = "local.test.com"

  # 初めてのvagrant upの時
  config.vm.provision :shell, :path => "~/Vagrant/test.com/provision/provision.sh"
  config.vm.provision :shell, privileged: true, :path => "~/Vagrant/test.com/provision/setup_postgresql.sh"
  config.vm.provision :shell, privileged: true, :path => "~/Vagrant/test.com/provision/setup_php.sh"
  config.vm.provision :shell, privileged: true, :path => "~/Vagrant/test.com/provision/setup_nginx.sh" # 証明書を連携したいため
  config.vm.provision :shell, privileged: true, :path => "~/Vagrant/test.com/provision/setup_nvm.sh" # node.js
  config.vm.provision :shell, privileged: true, :path => "~/Vagrant/test.com/provision/setup_other.sh" # selinuxとか

  # 共有フォルダ設定
  config.vm.synced_folder "~/Sites/test.com", "/var/www/vhosts/local.test.com",
  :owner => "vagrant",
  :group => "vagrant",
  :mount_options => ["dmode=777","fmode=777"],
  type: "virtualbox"
  
  # disksize custmize (vagrant plugin install vagrant-disksize)
  config.disksize.size = "40GB"

  config.vm.synced_folder ".", "/vagrant",
  :mount_options => ["dmode=777","fmode=777"],
  type: "virtualbox"

  # 毎回実行
  config.vm.provision "shell", run: "always", :path => "start.sh"
    
  # vagrant up 高速化 https://qiita.com/hayatoise/items/8621e140e9ec321fdf88
  config.vm.provider "virtualbox" do |vb|
      vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
      vb.gui = false
      vb.memory = "2048"
  end
end

Vagrant/test.com/provision/provision.sh

#!/bin/bash
​
systemctl stop firewalld
systemctl disable firewalld
​
timedatectl set-timezone Asia/Tokyo
localectl set-locale LANG=ja_JP.UTF-8
source /etc/locale.conf
​
# langpacks-jaは以下のエラーが出るため必要となるパッケージ
# default: Failed to set locale, defaulting to C
dnf install -y langpacks-ja
dnf install -y vim git wget locate
​
# nkfコマンド
## centos8が新しいからかnkfコマンドがDLできない。centos7から借りる
rpm -Uvh http://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/n/nkf-2.1.3-5.el7.x86_64.rpm
​
dnf -y update

Vagrant/test.com/provision/setup_postgresql.sh

#!/bin/bash
​
echo '########### set up 「postgresql12」start ###########'
​
dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
dnf -qy module disable postgresql #デフォルトのモジュールはmodule disableで無効
dnf install -y postgresql12 postgresql12-devel postgresql12-server postgresql12-contrib
​
# 自動起動設定
systemctl enable postgresql-12.service
​
# データベースクラスタ作成
if [ -z "$(ls /var/lib/pgsql/12/data/pg_hba.conf)" ]; then
  PGSETUP_INITDB_OPTIONS="-E UTF8 --no-locale" /usr/pgsql-12/bin/postgresql-12-setup initdb
fi
​
# postgresql.conf
if [ ! "$(cat /var/lib/pgsql/12/data/postgresql.conf | grep '### torikky add config ###')" ]; then
  echo "### torikky add config ###" >>/var/lib/pgsql/12/data/postgresql.conf
  echo "listen_addresses = '*'" >>/var/lib/pgsql/12/data/postgresql.conf
fi
​
# pg_hba.conf
if [ ! "$(cat /var/lib/pgsql/12/data/pg_hba.conf | grep 'torikky add config')" ]; then
  mv /var/lib/pgsql/12/data/pg_hba.conf /var/lib/pgsql/12/data/pg_hba.conf.${ymd}
  cat <<'EOF' >>/var/lib/pgsql/12/data/pg_hba.conf
# that name.
#
# This file is read on server startup and when the server receives a
# SIGHUP signal.  If you edit the file on a running system, you have to
# SIGHUP the server for the changes to take effect, run "pg_ctl reload",
# or execute "SELECT pg_reload_conf()".
#
# Put your actual configuration here
# ----------------------------------
#
# If you want to allow non-local connections, you need to add more
# "host" records.  In that case you will also need to make PostgreSQL
# listen on a non-local interface via the listen_addresses
# configuration parameter, or via the -i or -h command line switches.
​
​
​
# TYPE  DATABASE        USER            ADDRESS                 METHOD
​
# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
#host    all             all             127.0.0.1/32            ident
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 ident
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            ident
host    replication     all             ::1/128                 ident
host all all all trust # あまり良くないが。。。
EOF
fi
​
# postgresユーザのパスワード設定
export PGHOST=localhost
export PGPORT=5432
export PGDATABASE=test
export PGSCHEMA=public
export PGUSER=postgres
export PGPASSWORD=postgres
export CREATEDATABASE=${PGDATABASE}
su - postgres
psql ${PGDATABASE} -c "alter role postgres with password 'postgres';"
createdb ${CREATEDATABASE}
\q
​
echo '########### set up 「postgresql12」 end  ###########'

Vagrant/test.com/provision/setup_php.sh

#!/bin/bash
​
echo '########### set up 「php」start ###########'
​
# 初期設定
ymd=$(date +%Y%m%d)
phpenv_root="/usr/local/phpenv"
version="7.4.4" # TODO 入力させてそのバージョンをインストールできるようにしたい。
​
# TODO /usr/local内でglobalに参照できるやり方へ修正
​
# phpenv
if [ ! -e ${phpenv_root} ]; then
  mkdir ${phpenv_root}
  chmod 755 ${phpenv_root}
  git clone git://github.com/phpenv/phpenv.git ${phpenv_root}
fi
​
if [ ! -e ${phpenv_root}/plugins ]; then
  mkdir ${phpenv_root}/plugins
fi
​
if [ ! -e ${phpenv_root}/plugins/php-build ]; then
  git clone https://github.com/php-build/php-build ${phpenv_root}/plugins/php-build
fi
​
# php 7.4.4 なら確実にOK ※他のバージョンはわかりません。
dnf install -y libxml2-devel openssl-libs openssl-devel sqlite-devel bzip2-devel libcurl-devel libpng-devel libjpeg-devel libicu-devel gcc-c++ oniguruma readline-devel libxslt-devel libzip libzip-devel autoconf libpq-devel
dnf install -y http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/oniguruma-devel-6.8.2-1.el8.x86_64.rpm
dnf install -y https://download-ib01.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/l/libtidy-5.6.0-5.el8.x86_64.rpm
dnf install -y https://download-ib01.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/l/libtidy-devel-5.6.0-5.el8.x86_64.rpm
​
# PATH設定
if [ ! "$(cat ~/.bashrc | grep 'phpenv')" ]; then
  cat <<'EOF' >>~/.bashrc
# home directory pattern
# export PATH="$HOME/.phpenv/bin:$PATH"
# custom root directory pattern
export PHPENV_ROOT='/usr/local/phpenv'
export PATH="$PHPENV_ROOT/bin:$PATH"
eval "$(phpenv init -)"
EOF
  source ~/.bashrc
fi
​
# postgres driver
if [ ! "$(cat ${phpenv_root}/plugins/php-build/share/php-build/default_configure_options | grep 'pgsql')" ]; then
  cp ${phpenv_root}/plugins/php-build/share/php-build/default_configure_options ${phpenv_root}/plugins/php-build/share/php-build/default_configure_options.${ymd}
  cat <<'EOF' >>/usr/local/phpenv/plugins/php-build/share/php-build/default_configure_options
--with-pgsql
--with-pdo-pgsql
EOF
fi
​
# とりあえず7.4.4 TODO いずれバージョンを選べるようにしたいね。
echo '#### php install start ####'
phpenv install 7.4.4
phpenv global 7.4.4
echo '#### php install  end  ####'
​
# phpenv設定ファイル修正 ※ @で置換前と置換後の文字列区別し、シングルクォートで空白丸ごと文字列として認識させる
if [ "$(cat ${phpenv_root}/versions/${version}/etc/php-fpm.conf | grep ';pid = run/php-fpm.pid')" ]; then
  sed -i.${ymd} -e s@';pid = run/php-fpm.pid'@'pid = /run/php-fpm.pid'@ ${phpenv_root}/versions/${version}/etc/php-fpm.conf
fi
​
if [ "$(cat ${phpenv_root}/versions/${version}/etc/php-fpm.d/www.conf | grep 'nobody')" ]; then
  sed -i.${ymd} -e s@'user = nobody'@'user = nginx'@ ${phpenv_root}/versions/${version}/etc/php-fpm.d/www.conf
  sed -i.${ymd} -e s@'group = nobody'@'group = nginx'@ ${phpenv_root}/versions/${version}/etc/php-fpm.d/www.conf
  sed -i.${ymd} -e s@'listen = 127.0.0.1:9000'@'listen = /run/php-fpm.sock'@ ${phpenv_root}/versions/${version}/etc/php-fpm.d/www.conf
  sed -i.${ymd} -e s@';listen.owner = nobody'@'listen.owner = nginx'@ ${phpenv_root}/versions/${version}/etc/php-fpm.d/www.conf
  sed -i.${ymd} -e s@';listen.group = nginx'@'listen.group = nginx'@ ${phpenv_root}/versions/${version}/etc/php-fpm.d/www.conf
fi
​
# コマンドの登録
if [ ! -e ${phpenv_root}/versions/${version}/bin/php-fpm ]; then
  ln -nfs ${phpenv_root}/versions/${version}/sbin/php-fpm ${phpenv_root}/versions/${version}/bin/php-fpm
  phpenv rehash
  ln -nfs ${phpenv_root}/shims/php /usr/local/bin/php
  ln -nfs ${phpenv_root}/shims/phar /usr/local/bin/phar
  ln -nfs ${phpenv_root}/shims/php-config /usr/local/bin/php-config
  ln -nfs ${phpenv_root}/shims/phpize /usr/local/bin/phpize
  ln -nfs ${phpenv_root}/shims/php-fpm /sbin/php-fpm
fi
​
# サービスの登録
cat <<'EOF' >/etc/systemd/system/php-fpm.service
[Unit]
Description=PHP FastCGI Process Manager
After=network.target nginx.service
​
[Service]
Type=forking
PIDFile=/run/php-fpm.pid
ExecStartPre=/usr/bin/rm -f /run/php-fpm.pid
ExecStart=/sbin/php-fpm -D
#ExecReload=/bin/kill -s HUP $MAINPID
#KillSignal=SIGQUIT
#TimeoutStopSec=5
#KillMode=control-group
#PrivateTmp=true
​
[Install]
WantedBy=multi-user.target
EOF
​
# xdebugの設定
if [ ! "$(cat ${phpenv_root}/versions/${version}/etc/conf.d/xdebug.ini | grep 'xdebug add config')" ]; then
  cp ${phpenv_root}/versions/${version}/etc/conf.d/xdebug.ini ${phpenv_root}/versions/${version}/etc/conf.d/xdebug.ini.${ymd}
  cat <<'EOF' >>/usr/local/phpenv/versions/${version}/etc/conf.d/xdebug.ini
# xdebug add config
remote_autostart=1
xdebug.remote_enable=1
xdebug.remote_host=192.168.33.1
xdebug.idekey=PHPSTORM
xdebug.remote_port=9001
EOF
fi
​
systemctl enable php-fpm
​
echo '########### set up 「php」 end  ###########'

Vagrant/test.com/provision/setup_nginx.sh

#!/bin/bash
​
echo '########### set up 「nginx」start ###########'
​
dnf install -y nginx
​
# 証明書関連を格納(予め mkcert で自己証明書作成していること)
if [ ! -e /etc/nginx/ssl ]; then
mkdir /etc/nginx/ssl
fi
cp /vagrant/_wildcard.test.com+4* /etc/nginx/ssl
chmod 700 /etc/nginx/ssl | chown root:root  /etc/nginx/ssl/* | chmod 600 /etc/nginx/ssl/*
​
# サイトの設定ファイル作成
cat <<'EOF' > /etc/nginx/conf.d/test.conf
server {
listen 443 ssl;
server_name  local.test.com;
root    /var/www/vhosts/local.test.com/public;
index   index.php index.html index.htm;
​
# 大きいファイル対応 ※拡張が必要な場合はコメントインしてください。
#client_max_body_size 20M;
​
# 自己署名証明書
ssl_certificate /etc/nginx/ssl/_wildcard.test.com+4.pem;
# 暗号化鍵
ssl_certificate_key /etc/nginx/ssl/_wildcard.test.com+4-key.pem;
​
charset utf-8;
access_log  /var/log/nginx/access.log  main;
error_log  /var/log/nginx/error.log;
​
location / {
try_files $uri $uri/ /index.php?$query_string;
}
​
# 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;
}
​
# pass the PHP scripts to FastCGI server listening on php-fpm.sock;
location ~ \.php$ {
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php-fpm.sock;
try_files $uri =404;
}
}
EOF
​
systemctl daemon-reload
systemctl enable nginx
​
echo '########### set up 「nginx」 end  ###########'

Vagrant/test.com/provision/setup_nvm.sh

#!/bin/bash
​
echo '########### set up 「nvm」start ###########'
​
if [ ! -e ~/.nvm ]; then
    git clone https://github.com/creationix/nvm.git ~/.nvm
fi
​
if [ ! "$(cat ~/.bash_profile | grep 'nvm')" ]; then
    cat <<'EOF' >>~/.bash_profile
# nvmの実行
if [[ -s ~/.nvm/nvm.sh ]];
  then source ~/.nvm/nvm.sh
fi
EOF
    source ~/.bash_profile
fi
​
nvm install stable # 安定版インストール
​
npm -g install npm-check-updates
ncu -u
npm -g install
​
echo '########### set up 「nvm」 end  ###########'

Vagrant/test.com/provision/setup_other.sh

#!/bin/bash
​
echo '########### set up 「other」start ###########'
​
# selinux無効化 ※置換文字列に空白やスラッシュが入っていないためこれでOK
if [ "$(cat /etc/selinux/config | grep 'SELINUX=enforcing')" ]; then
  sed -i.${ymd} -e "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config
fi
​
echo '########### set up 「other」end ###########'
共有 :

最後に

今回、開発環境の自動構築設定について共有しました。

背景として新サービス構築にあたりその仮想環境をどうにか自動化できないかなと思い試行錯誤しました。また、今後もサービスの構築やらでリソースを取られるのも嫌でしたのでvagrantの機能を十二分に発揮したいなと考えて何とか着地しました。

今回共有した設定内容は、適宜環境に合わせて修正していただけばと思います。

Vagrantfileのprovisionを各モジュール単位に切り分けても良いし、一つのファイルにまとめてもよいと思います。自分の場合は各モジュール単位に切り分ければ他サービスを構築するとなっても必要な部分だけコピーしてそのまま流用できるかなと考えて上記のやり方にしてみました。

お役に立てれば幸いです。