DockerでLaravelの開発環境を作ってみる(3回目練習Ver)
わけわからない素人がDockerでLaravelの開発環境を作る3回目です。 今回でMySQLデータベースを設定します
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/
が表示されることを確認します。
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"と言うデータベースのバージョンコントロールを見つけたので使ってみました。
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イメージページにそれっぽい情報があったので試してみます。
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つを使うことができました。