PHPフレームワーク Laravel + Docker

PHPフレームワークであるLaravelをDockerコンテナとして運用します。データベース管理にphpmyadminを使用するため、nginx、phpmyadminコンテナが必要となります。

以下その手順です。

  1. Dockerネットワークの作成
  2. Docker-Composeファイルの作成
  3. Dockerfileの作成
  4. "laravel new"コマンドによる雛形アプリのインストール

GitHub

ドキュメント

https://laravel.com/docs/7.x

1. Dockerネットワークの作成

各コンテナ共通のネットワークbr0を作成します。

$ docker network create --driver=bridge --subnet=172.18.0.0/16 br0

2. Docker-Composeファイルの作成

nginx, mariadb, phpmyadmin, php-fpmから成るDocker-Composeファイルを作成します。
各イメージ毎にLaravelに必要な追加パッケージ、機能拡張などは別途Dockerfileで指定します。

注) Letsencrypt+nginxリバースプロキシーによるDockerコンテナを稼働していることを前提に作成(Laravel開発環境のみの構築であれば、Letsencrypt+nginxリバースプロキシーによるDockerコンテナは必要ありません)。以下参照のこと。

docker-compose.yml

version: '3'

services:
  mariadb:
    container_name: laravel-mariadb
    image: mariadb
    restart: always
    volumes:
      - ./db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=xxxxxxxx
      - MYSQL_DATABASE=laravel
      - MYSQL_USER=laravel
      - MYSQL_PASSWORD=xxxxxxxx
    networks:
      proxy-tier:
        ipv4_address: 172.18.0.5

  # nginx
  nginx:
    container_name: nginx
    image: nginx:alpine
    tty: true
    environment:
      - VIRTUAL_HOST=test.site.com
      - VIRTUAL_ROOT=/var/www/html
      - VIRTUAL_PORT=80
      # - VIRTUAL_PROTO=fastcgi
      - LETSENCRYPT_HOST=test.site.com
      - LETSENCRYPT_EMAIL=ficus.online@gmail.com
    volumes:
      # shared nginx default.conf between host and container
      - ./nginx_default.conf:/etc/nginx/conf.d/default.conf
      # shared the directory /var/www/html in php-fpm container
      - ./html:/var/www/html
      # shared the directory /var/www/html in phpmysql-fpm container
      - ./html/phpmyadmin:/var/www/html/phpmyadmin
    external_links:
      - nginx-proxy-letsencrypt
    restart: always
    networks:
      proxy-tier:
        ipv4_address: 172.18.0.6
        
  # php-fpm-laravel
  php-fpm-laravel:
    container_name: php-fpm-laravel
    build: 
      context: ./docker_files
      dockerfile: php7.2-fpm-alpine-laravel      
    tty: true
    expose: 
      - "9000"
    ports:
      - 8000:8000
    volumes:
      # for laravel php framework
      - ./html:/var/www/html
    depends_on:
      - laravel-mariadb
    restart: always
    networks:
      proxy-tier:
        ipv4_address: 172.18.0.7

  # phpmyadmin-fpm
  phpmyadmin:
    container_name: phpmyadmin-fpm
    build: 
      context: ./docker_files
      dockerfile: phpmyadmin-alpine
    tty: true
    expose: 
      - "9000"
    environment:
      - PMA_HOST=laravel-mariadb
      - PMA_PORT=3306
      - PMA_ABSOLUTE_URI=http://localhost/phpmyadmin
    volumes:
      - ./html/phpmyadmin:/var/www/html
      - /sessions
    depends_on:
      - laravel-mariadb
    restart: always
    networks:
      proxy-tier:
        ipv4_address: 172.18.0.8

networks:
  proxy-tier:
    external:
      name: br0

volumes:
  shared:
    external: true   

3. Dockerfileの作成

Laravelに必要なパッケージ・機能拡張を含んだイメージファイルを作成するため、別途Dockerfileで標準イメージをカスタマイズします。

phpmyadmin:Dockerfileの作成

$ mkdir docker_files
$ cd docker_files
$ nano phpmyadmin-alpine 

FROM phpmyadmin/phpmyadmin:fpm-alpine
RUN apk add --no-cache bash nano \
    && docker-php-ext-install mysqli \
    && docker-php-ext-enable mysqli

Laravel:Dockerfileの作成

$ nano php7.2-fpm-alpine-laravel

FROM php:7.2-fpm-alpine
    # Set working directory
    WORKDIR /var/www/html

    RUN apk add --no-cache bash nano libpng-dev freetype-dev libjpeg-turbo-dev zip libxml2-dev icu-dev nodejs-current npm \
        && docker-php-ext-install mysqli \
        && docker-php-ext-enable mysqli \
        && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
        && docker-php-ext-install -j$(nproc) gd pdo pdo_mysql zip \
        && docker-php-ext-enable gd pdo pdo_mysql zip \
        && docker-php-ext-install intl \
        && docker-php-ext-enable intl

    # Install Composer and Laravel
    COPY composer_installer.sh /var/www/html
    RUN ./composer_installer.sh && mv composer.phar /usr/local/bin/composer
    RUN chown -R www-data:www-data /var/www/html
    RUN composer global require laravel/installer \
        && ln -s /root/.composer/vendor/laravel/installer/bin/laravel /usr/local/bin/laravel

Laravelに必要なcomposerのインストールスクリプトを作成します(以下参照)。

$ nano composer_installer.sh

#!/bin/sh

EXPECTED_CHECKSUM="$(wget -q -O - https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"

if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
then
    >&2 echo 'ERROR: Invalid installer checksum'
    rm composer-setup.php
    exit 1
fi

php composer-setup.php --quiet
RESULT=$?
rm composer-setup.php
exit $RESULT

4. "laravel new"コマンドによる雛形アプリのインストール

以下コマンドにより各コンテナを起動します。

$ docker-compose up -d

Laravelコンテナに入ります。

$ docker exec -ti php-fpm-laravel bash

Laravel初心者用雛形を新規作成します。

# laravel new laravel-6-beginner

Laravelによるローカルサーバを起動します。

デフォルトのbridgeネットワークを指定する場合、

# cd laravel-6-beginner
# php artisan serve --host 0.0.0.0
Laravel development server started: http://0.0.0.0:8000
PHP 7.2.24 Development Server started at Fri Apr  3 00:13:36 2020

または、カスタムネットワークbr0を指定する場合

# cd laravel-6-beginner
# php artisan serve --host 172.18.0.9
Laravel development server started: http://172.18.0.9:8000
PHP 7.2.24 Development Server started at Fri Apr  3 00:13:36 2020

serveコマンドヘルプ

# php artisan help serve

Description:
  Serve the application on the PHP development server

Usage:
  serve [options]

Options:
      --host[=HOST]     The host address to serve the application on [default: "127.0.0.1"]
      --port[=PORT]     The port to serve the application on
      --tries[=TRIES]   The max number of ports to attempt to serve from [default: 10]
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable ANSI output
  -n, --no-interaction  Do not ask any interactive question
      --env[=ENV]       The environment the command should run under
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

ホストマシンからhttp://127.0.0.1:8000にアクセスして以下デフォルト画面が表示されるか確認して下さい。

php artisan serve inside docker

Docker PHP-Core-Extensionsドキュメント

下記 国際化用拡張モジュール php-intl がインストールされていないため、ロケールクラスのロードエラーが発生。

https://www.php.net/manual/en/intro.intl.php

コンパイルに必要なicu-devの追加、php-ext-installコマンドによる機能拡張モジュールintlのインストールをdockerfileに追加します。

popper.js.map - Failed to load resource: the server responded with a status of 404 (Not Found)

https://laracasts.com/discuss/channels/elixir/popperjsmap-failed-to-load-resource-the-server-responded-with-a-status-of-404-not-found

webpack.mix.js.js('node_modules/popper.js/dist/popper.js', 'public/js').sourceMaps() を追加

mix.js('resources/assets/js/app.js', 'public/js')
   .sass('resources/assets/sass/app.scss', 'public/css')
   .js('node_modules/popper.js/dist/popper.js', 'public/js').sourceMaps()
   .version();

再コンパイル

bash-5.0# npm run dev

<恒久策>以下スクリプトをapp.blade.phpに追加

<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>