vagrant
laravel
docker

Vagrant+DockerでLaravelローカル開発環境構築

More than 1 year has passed since last update.

新しいプロジェクトに入る度に開発環境が変わるので、その度にApacheサーバやら何やらを消しては入れ直しってやるのがいい加減面倒になってきたのでDockerの勉強がてら開発環境構築を自動化してみようという計画

Docker単体での運用でもいいけどDocker for Macは遅いっていう話を聞くし、Windowsだとそもそも10以外門前払いだし...
じゃあVM挟んで運用すればいいよね!( ゚д゚)
けどVMの構築が手間...
そうだ、Vagrantを使おう( ゚д゚)

その前に

Vagrantって?

仮想マシン(VM)の構築を自動化してくれるツール。
VirtualBoxと組み合わせて使う事が多い。

Dockerって?

Linuxコンテナという機能を良しなに使いやすくしたツール。
コンテナのお話とかはちょっと説明が難しいのでこの辺とかこの辺を参考にするとよろし

前提

  • 既にある程度開発が進んでるLaravelプロジェクト
  • プロジェクトは既にGit管理されている
  • 既存の開発環境構築手順があるのでなるべくそれに合わせる
  • DBは別途検証用のマシンに入れてるので今回の構成には組み込まない

実行環境

  • OS: MacOS 10.12 Sierra
  • VirtualBox: 5.0.32
  • Vagrant: 1.9.1
  • Docker: 17.06.0-ce, build 02c1d87

使用するVM

CentOS7

アプリケーション

  • Webサーバ: Apache
  • PHP: 7.0.*
  • Laravel: 5.3.29

実際にやってみた

構成

path/to/project
├── app/
├── Vagrantfile
├── docker-compose.yml
├── php/
│   ├── Dockerfile
│   ├── mod_rewrite.conf
│   ├── app.conf
│   └── php.ini
└── provision_init.sh
  • app: アプリケーションが格納されたフォルダ。これを展開するとLaravelのディレクトリ構成になってる
  • Vagrantfile: Vagrantの設定ファイル
  • docker-compose.yml: Docker Composeの設定ファイル
  • php: Docker Composeで使うフォルダ
    • Dockerfile: Dockerイメージを作成するための設定ファイル
    • mod_rewrite.conf, app.conf: httpd.confのIncludeとかIncludeOptionalで読み込ませるファイル。httpd.confを直接いじるよりも手間がかからない。
    • php.ini: PHPの設定ファイル
  • provision_init.sh: Vagrantでの仮想マシン初期構築時に走るスクリプト。この中でDockerをインストールする。

Vagrantの設定

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.vm.hostname = "app.dev"

  if ENV['VAGRANT_BRIDGE']
      interfaces  = %x(VBoxManage list bridgedifs)
      re          = /Name: +(.*#{ENV['VAGRANT_BRIDGE']}.*)/
      if interfaces =~ re
          config.vm.network :public_network, bridge: $1
      end
  else
      interfaces  = %x(VBoxManage list bridgedifs)
      if interfaces =~ /Name: *(.+)\n/
          config.vm.network :public_network, bridge: $1
      end
  end

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

   config.vm.provider "virtualbox" do |vb|
     vb.memory = "1024"
   end


  config.vm.provision "shell", :path => "provision_init.sh", :privileged => false
  config.vm.provision "shell", run: "always", inline: "systemctl restart network.service"
  config.vm.provision "shell", run: "always", inline: "service docker start"
end
provision_init.sh
sudo yum update -y
sudo yum install wget -y
sudo curl -fsSL https://get.docker.com/ | sh
sudo usermod -aG docker vagrant
sudo sh -c "curl -L https://github.com/docker/compose/releases/download/1.15.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose"
sudo chmod +x /usr/local/bin/docker-compose

Dockerの設定

docker-compose.yml
version: '2'
services:
  php:
    build: ./php
    ports:
      - '80:80'
    volumes:
      - /vagrant/app:/app:rw

FROM centos:latest
RUN yum -y update \
&& yum -y install epel-release http://rpms.famillecollet.com/enterprise/remi-release-7.rpm \
&& yum -y install wget httpd git \
&& yum -y --enablerepo=remi-php70 install php php-mbstring php-xml php-pdo php-pgsql \
&& yum clean all

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

COPY php.ini /etc/
COPY app.conf /etc/httpd/conf.d/
COPY mod_rewrite.conf /etc/httpd/conf.modules.d/

RUN mkdir /app
WORKDIR /app
VOLUME /app

RUN groupadd -g 1000 vagrant \
&& useradd -s /bin/bash -u 1000 -g vagrant vagrant \
&& usermod -aG vagrant apache

EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

app.conf
<VirtualHost *:80>
    DocumentRoot "/app/public"
    <Directory "/app/public">
        AllowOverride All
        Require all granted
        EnableMMAP Off
        EnableSendfile Off
    </Directory>
</VirtualHost>
mod_rewrite.conf
LoadModule rewrite_module modules/mod_rewrite.so

起動

$ cd path/to/project
$ vagrant up
$ vagrant ssh
# ここからVM内
$ cd /vagrant
$ docker-compose up -d

VM内で ip a と叩けばVMに割り当てられたIPアドレスが確認できるので、
そのIPアドレスをブラウザで直接開いてアプリケーションのトップ画面が表示されればクリア。

軽く解説

Vagrantfileについて

config.vm.network :public_network って設定するとネットワークの割り当てにブリッジアダプタを使用するようになる。
ただそれだけだと Vagrant up の度に使用するネットワークアダプタを選ばないといけないので環境変数で設定したり良しなにやってくれるようにしてるのが5行目〜16行目。参考記事も参照されたし。

Dockerfileについて

DockerHubに公開されてるphp-apacheイメージがDebianベースだったので今回の要件に合わず。
やむを得ずCentOSのイメージをベースにApacheとPHPを入れる形に。

アプリケーションフォルダのマウント

config.vm.synced_folder "./", "/vagrant", type: "virtualbox", mount_options: ['dmode=777','fmode=775']
docker-compose.yml
    volumes:
      - /vagrant/app:/app:rw
RUN mkdir /app
WORKDIR /app
VOLUME /app

実マシンの path/to/project が Vagrantマシン内で /vagrant としてマウントされ、その中の app ディレクトリをDockerコンテナ内で /app としてマウントしている。
こうすることでソースコードの編集を実マシン上で行うことができ、デプロイ作業等をすることなくコンテナに変更が反映される。
但し、これだけだとコンテナ内のApacheアプリケーションがパーミッションエラーを起こす( /app/storage に書き込みができない)ので、

RUN groupadd -g 1000 vagrant \
&& useradd -s /bin/bash -u 1000 -g vagrant vagrant \
&& usermod -aG vagrant apache

でapacheユーザ(Apacheアプリケーションが使用するユーザ)をvagrantグループに登録してやると、apacheユーザに /app/ 以下への書き込み権限が付与される。
(先のVagrantfileで config.vm.synced_foldermount_options を設定しているのもこのため)

まとめとか

今回は既にある程度の規模で開発が進んでるプロジェクトだったのでほぼ自己満で終わってるけど、今後新規開発の話があった時の環境構築のベースにしたい。(実はWindows上での検証ができてないのでそれが先...)
あと使うコンテナが1つだけで、ポートとかマウントの設定のためだけにDocker Composeを使ってるのは勿体無いので、他にもコンテナを乗っけて連携とかできればいいかな。
将来的には検証環境や本番環境のアプリケーションもDockerベースで運用できれば最the高。

参考