環境構築からWEBアプリ開発・スマホアプリ開発まで。ときには動画制作やゲームも。

supilog
すぴろぐ

Dockerでlaravel9開発環境を構築(PHP8+nginx+Mysql8)

Dockerでlaravel9開発環境を構築(PHP8+nginx+Mysql8)

PHPのローカル開発環境構築で、そんなに困ったことは実はない。DBを立ち上げて、必要なPHPのバージョンを用意して、ビルトインサーバーで作業する。macは、その辺がやりやすくてありがたい。個人作業が多かったのも大きな点だ。

ただ、複数人で共通の環境を用意する際には、少し面倒なのでDockerのメモを用意しておく。

準備

とりあえず準備として、laravelのプロジェクトを作成します。バージョンは9、プロジェクト名は「supilog」としています。

$ composer create-project laravel/laravel:^9.0 supilog

今回使用するバージョン

laravel9はPHP8.0以上が必要です。今回は8.1を使用します。

laravel 9
PHP 8.1
MySQL 8.0.32
nginx

Docker用ファイルの作成

構成

laravelプロジェクト内は以下のような構成になっています。今回は、Docker用のファイルを以下のように配置していこうと思います。

dockerディレクトリ内の配置は以下のようになる予定です。

docker
├── mysql
│   └── my.cnf
├── nginx
│   └── conf.d
│       └── default.conf
└── php
    ├── Dockerfile
    └── php.ini

docker-compose.yml

プロジェクト直下に配置します。

version: "3"
services:
  mysql:
    image: mysql:8.0.32
    container_name: supilog_mysql
    environment:
        MYSQL_DATABASE: supilog
        MYSQL_ROOT_PASSWORD: password
        MYSQL_USER: supiloguser
        MYSQL_PASSWORD: password
        TZ: "Asia/Tokyo"
    ports:
        - 4306:3306
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
      - ./docker/mysql/data:/var/lib/mysql
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf

  php:
    build: ./docker/php
    container_name: supilog_php
    volumes:
      - ./:/var/www/html
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/php.ini
    depends_on:
      - "mysql"

  nginx:
    image: nginx:latest
    container_name: supilog_nginx
    volumes:
      - ./docker/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
      - ./:/var/www/html
    restart: always
    ports:
      - 8000:80
    depends_on:
      - "php"
container_nameはお好きな名前を

お好きな名前を付けてください。

  mysql:
    container_name: supilog_mysql

  php:
    container_name: supilog_php

  nginx:
    container_name: supilog_nginx
DB設定はローカル環境で実際に使用する設定を

この設定は、実際のユーザー名と使用予定のパスワードを記述しましょう。ローカル環境なので、簡単なパスワードでも問題はないでしょう。

    environment:
        MYSQL_DATABASE: supilog       # データベース名
        MYSQL_ROOT_PASSWORD: password # rootユーザーのパスワード→laravelでは使わないので適当に
        MYSQL_USER: supiloguser       # laravelで使用するユーザー
        MYSQL_PASSWORD: password      # laravelで使用するユーザーのパスワード
MySQLのポート設定は

左側はローカルPC内でのポート番号、右側はDockerコンテナ内でのポート番号。右側は特にいじらずにデフォルトポートで良いです。

左側は、ローカル環境によっては、3306番ポートを使用済みかもしれないので、ずらしています。当然4306も使用中であれば、他のポートを設定します。

    ports:
        - 4306:3306
nginxのポート設定は

右側の80番は修正の必要はないです。左側は8000番としていますが、こちらは最終的にすべてを立ち上げた後に、「http://localhost:8000」とアクセスするポート番号になります。使用されていないポートであれば、お好みで大丈夫です。

    ports:
      - 8000:80

docker/mysql/my.cnf

こちらは本番設定に近づけています。ここでは、あまり深く論じません。

[client]
port=3306
socket=/var/lib/mysql/mysql.sock
default-character-set = utf8
 
[mysql]
prompt = '[\d] mysql> '
default-character-set = utf8
 
[mysqld]
datadir=/var/lib/mysql
tmpdir = /tmp
port=3306
socket=/var/lib/mysql/mysql.sock
user=mysql
character-set-server=utf8
default-storage-engine=InnoDB
explicit_defaults_for_timestamp=1
default_password_lifetime=0
#lower-case-table-names=1
init-connect=SET NAMES utf8
collation-server=utf8_general_ci
pid-file=/var/run/mysqld/mysqld.pid
 
# connection
max_connections=64
table_open_cache=800
table_definition_cache=400
open_files_limit=1120
 
# timeout
wait_timeout=60
interactive_timeout=60
 
# buffer
key_buffer_size = 16M
innodb_buffer_pool_size = 256M
read_buffer_size = 256K
read_rnd_buffer_size = 512K
join_buffer_size = 256K
sort_buffer_size = 512K
 
 
# InnoDB
innodb_file_per_table
innodb_autoextend_increment = 64
innodb_log_files_in_group = 2
innodb_log_file_size = 64M
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 2
innodb_flush_neighbors=1
innodb_thread_concurrency = 4
innodb_commit_concurrency = 4

# log
log-error=/var/log/mysqld.log
general_log = 1
general_log_file = /var/lib/mysql/general.log
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/slow_query.log
long_query_time = 1
 
# ngram
ngram_token_size = 2
 
symbolic-links=0
skip-character-set-client-handshake
 
[mysqldump]
quick
single-transaction
default-character-set=utf8

[client-server]
!includedir /etc/my.cnf.d

docker/nginx/conf.d/default.conf

nginxの設定です。動作目的の簡易的な設定です。

server {
    listen       80;
    server_name  localhost;
    root   /var/www/html/public;
    index  index.php index.html;
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ [^/]\.php(/|$) {
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

docker/php/php.ini

[PHP]
engine = On
zend.exception_ignore_args = On
expose_php = On
max_execution_time = 30
upload_max_filesize = 2M
post_max_size = 8M
memory_limit = 128M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
display_startup_errors = Off
log_errors = On
default_charset = "UTF-8"

[Date]
date.timezone = Asia/Tokyo

[mysqlnd]
mysqlnd.collect_memory_statistics = Off

[Assertion]
zend.assertions = -1

[mbstring]
mbstring.language = Japanese

docker/php/Dockerfile

FROM php:8.1.16-fpm

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

RUN apt-get update \
  && apt-get install -y zlib1g-dev mariadb-client vim libzip-dev \
  && docker-php-ext-install zip pdo_mysql

RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php composer-setup.php
RUN php -r "unlink('composer-setup.php');"
RUN mv composer.phar /usr/local/bin/composer

ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin

コンテナを起動させてみる

プロジェクト直下で以下のコマンドを打ってみます。

$ docker-compose up -d

完了すると以下のような表示がでます。

Creating supilog_mysql ... done
Creating supilog_php   ... done
Creating supilog_nginx ... done

起動確認

StateがすべてUpになっていれば無事に成功です。

$ docker-compose ps

---------------
    Name                   Command               State                 Ports              
------------------------------------------------------------------------------------------
supilog_mysql   docker-entrypoint.sh --cha ...   Up      0.0.0.0:4306->3306/tcp, 33060/tcp
supilog_nginx   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:8000->80/tcp             
supilog_php     docker-php-entrypoint php-fpm    Up      9000/tcp  
---------------
  

この時点でwelcomeページへのアクセスは可能になっているはずです。http://localhost:8000にアクセスしてみてください。(ポート番号を任意に変更した方は、そのポート番号で)

migrationを行う

.envの設定
    environment:
        MYSQL_DATABASE: supilog       # ①データベース名
        MYSQL_ROOT_PASSWORD: password # rootユーザーのパスワード → 使わない
        MYSQL_USER: supiloguser       # ②laravelで使用するユーザー
        MYSQL_PASSWORD: password      # ③laravelで使用するユーザーのパスワード

MySQLコンテナの設定時に、下記のように設定を入れたので、laravel側の設定ファイルを更新していきます。プロジェクト直下にある.envファイルを修正します。

DB_HOSTには、「127.0.0.1」ではなく、mysqlコンテナにつけた名前を記載してあげます。

DB_CONNECTION=mysql
DB_HOST=supilog_mysql
DB_PORT=3306
DB_DATABASE=supilog
DB_USERNAME=supiloguser
DB_PASSWORD=password

「あれ?さっき4306番ポートを設定しなかった?」と思ったアナタするどいですね。4306番はコンテナの外側の世界に向けたポートなので、外部ツールからmysqlコンテナのDBにアクセスしたい時には、4306を使います。

一方で、コンテナ内部でのやり取りは3306が使われるので、これでOK。

phpコンテナにアクセスして、migrationしてみる

下記コマンドで作成したphpコンテナに入り込みます。

$ docker-compose exec php bash

プロジェクト内にいると思うので、artisanコマンドを実行します。migrationが無事に動作したら、開発環境構築完了です。

設定が間違っていてmysqlコンテナに接続が出来ない場合には、下記コマンド実行時に「Connection refused」が発生すると思います。

$ php artisan migrate

---------------

   WARN  Migration table not found.  

   INFO  Preparing database.  

  Creating migration table ....................................................... 45ms DONE

   INFO  Running migrations.  

  2014_10_12_000000_create_users_table ........................................... 49ms DONE
  2014_10_12_100000_create_password_resets_table ................................. 81ms DONE
  2019_08_19_000000_create_failed_jobs_table ..................................... 54ms DONE
  2019_12_14_000001_create_personal_access_tokens_table .......................... 74ms DONE

---------------

まとめ

わざわざ最後まで読んでくださりありがとうございます。

個人的な手順としてまとめたものですが、どなたかの参考になれば幸いです。

一度設定しておけば、どの環境でも共通の状態を作れるというのは強みですね。

それでは!