DockerでLaravelの開発環境を作ってみる(3回目練習Ver)

目次

わけわからない素人がDockerでLaravelの開発環境を作る3回目です。 今回でMySQLデータベースを設定します

1回目はここ。

2回目はここ。

OSは"Ubuntu 20.04.2 LTS"で行います。

PHPアプリコンテナを作る

以下のようにディレクトリを作成します。

www
├─ nginx
│   │ default.conf  ← nginxの設定ファイル
│   └
└─ mysql
     └─ data

作成したディレクトリに移動しPHPコンテナにcomposer、Laravelをインストールします。

$ cd www
~/www$ docker run -dit --name php-3rd -v "$PWD":/var/www php:8.0.7-fpm-buster
$ docker exec -it php-3rd /bin/bash
root@e002aabdd9f8:/var/www/html# php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
root@e002aabdd9f8:/var/www/html# php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
root@e002aabdd9f8:/var/www/html# php composer-setup.php
root@e002aabdd9f8:/var/www/html# php -r "unlink('composer-setup.php');"
root@e002aabdd9f8:/var/www/html# mv composer.phar /usr/local/bin/composer
root@e002aabdd9f8:/var/www/html# apt-get update
root@e002aabdd9f8:/var/www/html# apt-get -y install unzip git
root@e002aabdd9f8:/var/www/html# composer global require laravel/installer
root@e002aabdd9f8:/var/www/html# export PATH="$HOME/.composer/vendor/bin:$PATH"

“/var/www"ディレクトリに移動し、laravel newコマンドでLaravelプロジェクトを作ります。

root@e002aabdd9f8:/var/www/html# cd /var/www
root@e002aabdd9f8:/var/www# laravel new example-app

作成したプロジェクトのディレクトリに書き込み権限を追加します。

  • “storage/logs”
  • “storage/framework/sessions”
  • “storage/framework/views”
root@e002aabdd9f8:/var/www# cd example-app
root@e002aabdd9f8:/var/www/example-app# chmod o+w storage/logs
root@e002aabdd9f8:/var/www/example-app# chmod o+w storage/framework/sessions
root@e002aabdd9f8:/var/www/example-app# chmod o+w storage/framework/views

nginxコンテナを作る

nginxの設定ファイルを作成するため、PHPコンテナのIPアドレスを調べます。 PHPコンテナ内ではなくホストからdocker container inspectコマンドで確認します。

$ docker container inspect --format="{{.NetworkSettings.IPAddress}}" php-3rd
172.17.0.2

IPアドレスが確認できたので、nginxの設定ファイルを作成します。 “default.conf"の内容です。

server {
    listen 80;
    server_name example.com;
    root /var/www/example-app/public;

    add_header X-Frame-Options "SAMEORIGIN";
    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;

    location ~ \.php$ {
        # FastCGI サーバー
        fastcgi_pass 172.17.0.2:9000;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

nginxコンテナを開始します。

~www$ docker run --name nginx-3rd -v "$PWD"/nginx:/etc/nginx/conf.d -v "$PWD":/var/www -d -p 8080:80 nginx:1.21.0-alpine

Webブラウザでhttp://127.0.0.1:8080/が表示されることを確認します。

ブラウザにLaravelのページが表示されます

ブラウザにLaravelのページが表示されます

MySQLコンテナを用意する

MySQLのバージョンは新しい"8.0.25"にしました。 rootパスワードにはmy-secret-pwを指定しています。

~www$ docker run --name mysql-3rd -v "$PWD"/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql/mysql-server:8.0.25

MySQLコンテナのIPアドレスを確認します。

$ docker container inspect --format="{{.NetworkSettings.IPAddress}}" mysql-3rd
172.17.0.4

PHPコンテナからMySQLコンテナへの接続設定を行います。 PHPコンテナ内の”/var/www/example-app/.env"ファイルを編集します。 元のファイルから以下の箇所を変更しました。

DB_CONNECTION=mysql
DB_HOST=172.17.0.4
DB_PORT=3306
DB_DATABASE=example_app
DB_USERNAME=root
DB_PASSWORD=my-secret-pw

全体の内容はこうなっています。

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:JP/zhhkmDS6La+IueY/0RabPITYszjqruqupT++IaJg=
APP_DEBUG=true
APP_URL=http://example-app.test

LOG_CHANNEL=stack
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=172.17.0.4
DB_PORT=3306
DB_DATABASE=example_app
DB_USERNAME=root
DB_PASSWORD=my-secret-pw

BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

MEMCACHED_HOST=127.0.0.1

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

テストにDBを使ってみたいのですが、Laravelのことは何もわからないのでどうして良いのか分かりません。 というわけで、公式ドキュメントを見ていたら"migrate"と言うデータベースのバージョンコントロールを見つけたので使ってみました。

Database: Migrations

root@e002aabdd9f8:/var/www/example-app# php artisan migrate

   Illuminate\Database\QueryException 

  could not find driver (SQL: select * from information_schema.tables where table_schema = example_app and table_name = migrations and table_type = 'BASE TABLE')

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:692
    688▕         // If an exception occurs when attempting to run a query, we'll format the error
    689▕         // message to include the bindings with SQL, which will make this exception a
    690▕         // lot more helpful to the developer instead of just the database's errors.
    691▕         catch (Exception $e) {
  ➜ 692▕             throw new QueryException(
    693▕                 $query, $this->prepareBindings($bindings), $e
    694▕             );
    695▕         }
    696▕ 

      +33 vendor frames 
  34  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

ドライバーが見つからないとエラーメッセージが表示されました。何をすれば良いのかわからないときは、なんとなくで何かをやってみれば次にやることが見つかります。次はドライバーのインストールです。

PHPのドキュメント「MySQL用PHPドライバの概要」によると、 “mysqli"と"PDO_MySQL"があるようです。

エラーが発生したソース”/home/izumi/www/example-app/vendor/laravel/framework/src/Illuminate/Database/Connection.php"によるとPDOを使っているので"PDO_MySQL"ドライバをインストールします。

PHPのDockerイメージページにそれっぽい情報があったので試してみます。

https://hub.docker.com/_/php

PHPコンテナでコマンドを実行します。

root@e002aabdd9f8:/var/www/example-app# docker-php-ext-install pdo_mysql

インストールが終わったらもう一度migrateを実行します。

root@e002aabdd9f8:/var/www/example-app# php artisan migrate

   Illuminate\Database\QueryException 

  SQLSTATE[HY000] [1130] Host '172.17.0.2' is not allowed to connect to this MySQL server (SQL: select * from information_schema.tables where table_schema = example_app and table_name = migrations and table_type = 'BASE TABLE')

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:692
    688▕         // If an exception occurs when attempting to run a query, we'll format the error
    689▕         // message to include the bindings with SQL, which will make this exception a
    690▕         // lot more helpful to the developer instead of just the database's errors.
    691▕         catch (Exception $e) {
  ➜ 692▕             throw new QueryException(
    693▕                 $query, $this->prepareBindings($bindings), $e
    694▕             );
    695▕         }
    696▕ 

      +33 vendor frames 
  34  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

今度はPHPコンテナ'172.17.0.2’がMySQLコンテナに接続拒否されました。

MySQLコンテナに入って確認してみます。

$ docker exec -it mysql-3rd /bin/bash

mysqlコマンドをrootユーザーで起動します。

bash-4.4# mysql -u root -p
Enter password:  ← Dockerコマンドで指定したパスワード"my-secret-pw"を入力します
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.25 MySQL Community Server - GPL

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

PHPコンテナからはrootユーザーで接続しているのでユーザー情報を確認します。

mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select user, host from user;
+------------------+-----------+
| user             | host      |
+------------------+-----------+
| healthchecker    | localhost |
| mysql.infoschema | localhost |
| mysql.session    | localhost |
| mysql.sys        | localhost |
| root             | localhost |
+------------------+-----------+
5 rows in set (0.00 sec)

rootユーザーはlocalhostからしか接続できないようになっています。 今回は学習用なのでrootユーザーでどこからでも接続できるようにセキュリティを弱めます。

mysql> update user set host='%' where user='root';
mysql> flush privileges;

PHPコンテナでmigrateを実行します。

root@e002aabdd9f8:/var/www/example-app# php artisan migrate

   Illuminate\Database\QueryException 

  SQLSTATE[HY000] [1049] Unknown database 'example_app' (SQL: select * from information_schema.tables where table_schema = example_app and table_name = migrations and table_type = 'BASE TABLE')

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:692
    688▕         // If an exception occurs when attempting to run a query, we'll format the error
    689▕         // message to include the bindings with SQL, which will make this exception a
    690▕         // lot more helpful to the developer instead of just the database's errors.
    691▕         catch (Exception $e) {
  ➜ 692▕             throw new QueryException(
    693▕                 $query, $this->prepareBindings($bindings), $e
    694▕             );
    695▕         }
    696▕ 

      +33 vendor frames 
  34  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
root@e002aabdd9f8:/var/www/example-app# 

MySQLコンテナに接続できているようですが’example_app’が見つかりません。 勝手にデータベースを作ってくれないのでMySQLコンテナ内で’example_app’データベースを作成します。

mysql> create database example_app;

PHPコンテナでmigrateを実行します。

root@e002aabdd9f8:/var/www/example-app# php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (1,356.29ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (603.25ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (595.72ms)

今度は成功したようです。MySQLコンテナで’example_app’データベースがどうなったのか確認します。

mysql> use example_app;
mysql> show tables;
+-----------------------+
| Tables_in_example_app |
+-----------------------+
| failed_jobs           |
| migrations            |
| password_resets       |
| users                 |
+-----------------------+
4 rows in set (0.00 sec)

phpコンテナからMySQLコンテナにテーブルを作ることができました。

終了するときはquitコマンドを使用します。

mysql> quit
Bye

  やっとphp、nginx、MySQLの3つを使うことができました。

4回目へ続く。