Laravel向けのDocker開発環境を整えたので共有します。
本番でもDockerが使えるように色々試しているとこですので、自分が把握できた範囲の構成です。
githubに置いときます。
目標とミドルウェアの構成
目標はDockerを立ち上げて直ぐにLaravelの開発ができるようにすること。composerとnodejsも一緒に用意します。
構成とバージョン。最新になるようにしています。
- php (php-fpm) 7.4.1
- composer 1.10.13
 - nodejs v12.18.4
 - npm 6.14.6
 
 - mysql 8.0 (5.7も可能)
- パスワードなど初期設定をする。
 
 - nginx 1.19.2
- Laravel向けのconfを用意する。
 
 
ホスト環境
今回の趣旨に関係ありませんが、ホストOSはWindows10です。
- Windows 10 Home バージョン2004(OSビルド 19041.508)
 - WSL2 (Ubuntu 20.04.1 LTS)
 - Docker version 19.03.13, build 4484c46d9d
 - docker-compose version 1.27.4, build 40524192
 
WSL2が出てWindows HomeでもDockerが使えるようになりました。 インストール方法はMicrosoftの手順を解説したQiita @KoKeCrossの記事の通り進めて行けばOKです。
ディレクトリ構成
/project
├─ /docker    # コンテナ内のデータ保存先
|  ├─ /db
|  |  ├─ /data           # データベース保存先
|  |  ├─ /sql
|  |  └─ /my.conf        # mysqlの設定(今回は空ファイル)
|  ├─ /nginx
|  |  └─ /default.conf   # Nginxの設定
|  └─ /php
|     ├─ /Dockerfile     # phpコンテナの設定
|     └─ /php.ini        # phpの設定
├─ /web       # アプリケーションコード
└─ docker-compose.ymldocker-compose.yml
php, nginx, dbのコンテナを作ります。mysqlはdb。
version: '3'
volumes:
  vendor-store:
  node_modules-store:
services:
  php:
    container_name: php
    build: ./docker/php
    volumes:
    - ./web:/var/www
    - vendor-store:/var/www/laravel/vendor
    - node_modules-store:/var/www/laravel/node_modules
    environment:
      TZ: Asia/Tokyo
  nginx:
    image: nginx
    container_name: nginx
    ports:
    - 80:80
    volumes:
    - ./web:/var/www
    - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
    - php
  db:
    image: mysql:8.0
    container_name: db
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: database
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
    - ./docker/db/data:/var/lib/mysql
    - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
    - ./docker/db/sql:/docker-entrypoint-initdb.d
    ports:
    - 3306:3306
imageはDocker-Hubにあるビルド済みイメージを指定している。 有名なミドルウェアは公式のものがあります。 phpコンテナはNodejsやcomposerをインストールするため、Dockerfileからビルドします。
volumesはホストとコンテナのディレクトリとファイルを同期する。
ホストの/webをphp・nginxコンテナのエントリーポイント/var/wwwに指定しました。
Laravelプロジェクトは/webにクローンするか、phpコンテナの/var/wwwで新規作成して開発が可能です。
vendorとnode_modulesは名前付きボリュームに格納して、ホスト側とコンテナ側と分離して管理している。 同期処理が発生しないため、その分速くなる。
dbのenvironmentに初期設定を渡せる。 これを.envに書いたり、ホストのSQLクライアントの接続にそのまま使えます。 その他の変数はdockerhub mysqlでご確認ください。
mysql:8.0をmysql:5.7にしても動作確認とれた。
php/Dockerfile
FROM php:7.4.1-fpm
COPY php.ini /usr/local/etc/php/
RUN apt update
RUN apt install -y wget git unzip libpq-dev
# Install Node.js 12
RUN apt install -y npm \
  && npm install n -g \
  && n 12
# Install PHP Extensions
RUN apt install -y zlib1g-dev mariadb-client libzip-dev libonig-dev \
  && docker-php-ext-install zip pdo_mysql
# Install Composer
RUN curl -sS https://getcomposer.org/installer | php \
  && mv composer.phar /usr/local/bin/composer \
  && composer self-update
WORKDIR /var/www
# php-fpmはデフォルトのユーザwww-dataで動く。https://stackoverflow.com/questions/48619445/permission-denied-error-using-laravel-docker
# 変更する場合は /usr/local/etc/php-fpm.d/www.conf でユーザー名を変える。
RUN chown -R www-data:www-data /var/www
RUN composer global require "laravel/installer"php:7.4.1-fpmのイメージにNode.jsやComposerをインストールしていくDockerfileです。
aptだとNodejsは古いため、パッケージマネージャのnで新しいバージョンをインストールしています。 以下のようにスクリプトでインストールする方法もあります。
# Install Node.js 12
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - \
 && apt install -y nodejsphp 7.4ではビルド時にonigumaが見つからないとエラーが出ます。
aptではlibonig-dev(library onigumaかな?)をインストールすると回避できる。
参考1,参考2
必要な拡張はdocker-php-ext-installに追加していく。
nginxはphp-fpmを通してLaravelを実行します。
/var/www以下のファイルにユーザwww-dataの実行権限を与えます。
www-dataはphp-fpmのデフォルトユーザです。
/usr/local/etc/php-fpm.d/www.confを修正してユーザ名を変更できます。
/php/php.ini
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"cliもfpmのphpもこの設定を参照します。
/nginx/default.conf
server {
  listen 80;
  // root /var/www/{Laravelプロジェクト名}/public;
  root /var/www/laravel/public;
  add_header X-Frame-Options "SAMEORIGIN";
  add_header X-XSS-Protection "1; mode=block";
  add_header X-Content-Type-Options "nosniff";
  index index.php;
  charset utf-8;
  location / {
    try_files $uri $uri/ /index.php?$query_string;
  }
  location = /favicon.ico { access_log off; log_not_found off; }
  location = /robots.txt  { access_log off; log_not_found off; }
  error_page 404 /index.php;
  // phpファイルはfastcgi(=php-fpm)で処理するよって書いてある
  location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    // ホスト名(=コンテナ名):ポート
    fastcgi_pass php:9000;
    fastcgi_index index.php;
    include fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param PATH_INFO $fastcgi_path_info;
  }
  location ~ /\.(?!well-known).* {
      deny all;
  }
 }
LaravelをNginxで動作させる設定です。 ApacheではLaravel同梱の.htaccessが設定してくれるが、Nginxでは.htaccessに当たるものがないためNginxのconfを修正する必要がある。(.htaccessを極力使わないほうがいい)
公式の設定Nginx | laravel.comからphpコンテナのfpmを見るよう修正しています。 ネットワークはDockerに管理されており、ホスト名はコンテナ名と同等です。
ドキュメントルートを/var/www/laravel/publicとしています。
プロジェクト名が変わるときはパスに注意。
docker-composeのコマンド
ホスト側でよく使うコマンドです。
# コンテナ起動
$ docker-compose up -d
# コンテナ削除
$ docker-compose down
# コンテナ、イメージ、ボリューム、ネットワークを一括完全消去
$ docker-compose down --rmi all --volumes
# phpコンテナに接続する(コンテナ名を変えて他のコンテナに接続できる)
$ docker-compose exec php bash
Dockerfileなど修正した場合は一括削除してから起動しなおすといい。
初回はLaravel 8.x インストールに従ってphpコンテナ内で作業するとプロジェクトを作成できます。
ログの書き込みなどでpermission deninedが出る場合は、# chown -R www-data:www-data /var/wwwを実行するとphp-fpmに権限が与えられて解消できます。(php-fpmユーザを変更した場合はそのユーザ名にする)
参考
DockerFile
Dockerの操作
書籍
Dockerって何?の状態で読むと難しすぎたが、Dockerの概念を他で学び試して遊んでからわかるようになった。 Dockerの運用管理向け、業務で何度も読み返しそうな良著。