Dockerを使って1コマンドで起動できるLaravel開発環境を構築する


DockerでLaravelの開発環境を構築します。
プロジェクトをcloneしたらコマンド1つで開発が始められるようになります。
もう環境構築に半日も工数をとる必要はありません。

構築する開発環境

構築する環境は以下の通りです。

  • ホスト
    • Docker 19.03.5(インストール済み)
  • コンテナ
    • PHP 7.3
    • Apache 2.4
    • MySQL 5.7.29
    • PHPMyAdmin(おまけ)

いわゆるLAMP環境です。

ディレクトリ構成

最終的なディレクトリ構成は以下の通りです。Laravelプロジェクトはmyappに保存します。

project
├── docker
│   ├── docker-compose.yml
│   └── php-apache
│       ├── apache2.conf
│       └── php.ini
│       └── Dockerfile
└── myapp (Laravelプロジェクト)
    ├── app
   ・・・
    └── startup.sh

startup.shは.envの作成など、Laravelプロジェクト初期化に必要なコマンドをまとめたファイルです。
後ほど紹介します。

Dockerfile作成

Dockerfileは以下の通りです。

project/docker/php-apache/Dockerfile
FROM php:7.3-apache

COPY --from=composer /usr/bin/composer /usr/bin/composer
RUN apt-get update && apt-get install -y \
    unzip \
    libzip-dev \
    zlib1g-dev \
    && docker-php-ext-install \
    zip \
    pdo_mysql \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* \
    && a2enmod rewrite
COPY ./apache2.conf /etc/apache2/apache2.conf
COPY ./php.ini /usr/local/etc/php/php.ini

WORKDIR /var/www/myapp

Dockerfile解説

Dockerfileの内容を解説します。
不要な場合は次章の「docker-compose.yml作成」まで読み飛ばしてください。


FROM php:7.3-apache

Docker Hubを探すと、PHPとApacheが同梱されているイメージがあるので今回はそれを使用します。

COPY --from=composer /usr/bin/composer /usr/bin/composer

--from=composerでPHPコンテナからComposerコンテナを使用することができます。
マルチステージビルドという仕組みです。
Composerのコンテナから/usr/bin/composerをコピーすることでPHPコンテナ内でComposerのコマンドを使用できるようになります。

RUN apt-get update && apt-get install -y \
    unzip \
    libzip-dev \
    zlib1g-dev \
    && docker-php-ext-install \
    zip \
    pdo_mysql \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* \
    && a2enmod rewrite

環境構築後に「いざ、composer install!」とすると、やれzipコマンドがない、unzipがないなど色々言われます。
都度、apt-getで必要なものをインストールさせるとこんな感じになります。
また、docker-php-ext-installを使用して、MySQLのPDOドライバもインストールしています。
最後のa2enmod rewriteはApacheの設定です。

COPY ./apache2.conf /etc/apache2/apache2.conf
COPY ./php.ini /usr/local/etc/php/php.ini

ApacheやPHPの設定ファイルを変更したい場合は、ホスト側で設定ファイルを作成してコンテナの設定ファイルを上書きします。
私の場合は、コンテナ内からapache2.confをコピーしてきて以下を追記したものを使っています。

project/docker/php-apache/apache2.conf
~省略~

<VirtualHost *:80>
    ServerName myapp.com
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/myapp/public

    <Directory "/var/www/myapp">
            AllowOverride All
    </Directory>
</VirtualHost>

ドキュメントルートをLaravelプロジェクトのpublicディレクトリに変更するのを忘れないようにしましょう。

※php.iniの内容は環境構築に直接関係ないので割愛します。

WORKDIR /var/www/myapp

最後はコンテナにアクセスした時にプロジェクトのルートがデフォルトになるようにWORKDIRを設定します。

docker-compose.yml作成

docker-compose.ymlは以下の通り。

project/docker/docker-compose.yml
version: "3"
services:
  mysql:
    image: mysql:5.7.29
    container_name: mysql    
    ports:
      - '3306:3306'
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: default
      MYSQL_USER: default
      MYSQL_PASSWORD: secret
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
  app:
    build: php-apache
    container_name: myapp
    ports:
      - '8000:80'
    volumes:
      - ../myapp.:/var/www/myapp:cached

docker-compose.yml解説

docker-compose.ymlの内容を解説します。
不要な場合は次章の「コンテナの起動」まで読み飛ばしてください。

project/docker/docker-compose.yml
mysql:
  image: mysql:5.7.29
  container_name: mysql    
  ports:
    - '3306:3306'
  environment:
    MYSQL_ROOT_PASSWORD: root
    MYSQL_DATABASE: default
    MYSQL_USER: default
    MYSQL_PASSWORD: secret
    TZ: 'Asia/Tokyo'
  command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

MySQLコンテナの設定です。
image:MySQLのイメージを指定します。
ports:ホストの3306ポートとコンテナの3306ポートを紐づけています。
environment:環境変数です。データベースの初期設定をしています。
command:文字エンコーディングの設定をしています。

project/docker/docker-compose.yml
app:
  build: php-apache
  container_name: myapp
  ports:
    - '8000:80'
  volumes:
    - ../myapp:/var/www/myapp:cached

アプリケーションコンテナの設定です。
builddocker/php-apache内のDockerfileをビルドするように指定しています。
ports:ホストの8000ポートとコンテナの80ポートをリンクさせています。
volumes:ホストのLaravelプロジェクトのディレクトリをコンテナにマウントします。
ホスト側でアプリを編集すれば、コンテナ側にも編集内容が反映されるようになります。
:cached:Mac for Dockerを使っているとボリュームのマウントがやたらコストかかるのでキャッシュさせるようにします。

コンテナの起動

とりあえずこれでコンテナの構成は完了です。コンテナを起動しましょう。

project/docker/
$ docker-compose up

数分もすればMySQLとPHPのコンテナが立ち上がります。
これで開発環境は完成です。

Laravelプロジェクトの初期化

Laravelプロジェクトを初期化します。
.env.exampleをdocker-compose.ymlで設定したMySQLの初期設定に合わせて変更します。

myapp/.env.example
DB_HOST=mysql
DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secret

DB_HOSTにはcontainer_nameの値を設定します。

次にいくつか実行しなければならないコマンドをstartup.shにまとめておきます。
.envの作成からシーディングまで指定しておきます。

myapp/startup.sh
cp .env.example .env
composer install
touch /var/www/myapp/storage/logs/laravel.log
chmod -R 777 /var/www/myapp/storage
chmod -R 777 /var/www/myapp/bootstrap
php artisan key:generate
php artisan migrate
php artisan db:seed

作成したら以下のコマンドでPHPコンテナに接続します。

myapp/docker
$ docker exec -it myapp bash

接続したら、プロジェクトのルートディレクトリにいるので次のコマンドを実行します。

phpコンテナ:/var/www/myapp
$ sh startup.sh

artisanコマンドなどを使用する場合もdocker execで同じようにコンテナにアクセスして実行します。

コマンドの実行が終わったらlocalhost:8000にアクセスします。
アプリケーションが稼働しているはずです。

開発者はプロジェクトをcloneしたらdocker-compose upsh startup.shだけで開発が始められます。

アクセスできない場合

Docker for Windowsを使用している場合は、docker-machine lsコマンドで表示されるIPアドレス:8000でアクセスできます。
また、指定したポート番号が他のアプリとかぶっているとコンテナが起動しません。
docker-compose.ymlのポート番号を変更してdocker-compose upをやりなおしてみてください。

PHPMyAdminの追加(おまけ)

簡単なので、PHPMyAdminも追加してみましょう。
PHPMyAdminはブラウザ上で使用できるDBクライアントツールです。
docker-compose.ymlに追記します。

project/docker/docker-compose.yml
version: "3"
services:
  mysql:
    image: mysql:5.7.29
    container_name: mysql    
    ports:
      - '3306:3306'
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: default
      MYSQL_USER: default
      MYSQL_PASSWORD: secret
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
  app:
    build: php-apache
    container_name: myapp
    ports:
      - '8000:80'
    volumes:
      - ../myapp:/var/www/myapp:cached
  # 以下追記
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    ports:
      - 8080:80
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=mysql
      - PMA_USER=root
      - PMA_PASSWORD=root
    container_name: "phpmyadmin"

docker-compose upを実行してlocalhost:8080にアクセスします。
PHPMyAdminが稼働しているはずです。

まとめ

Dockerを使えば開発環境の構築が1コマンドでできる!
(startup.shは環境ではないのでノーカン)