DockerでLaravelの開発環境を作ってみる(4回目練習Ver)
わけわからない素人がDockerでLaravelの開発環境を作る4回目です。 前回まではPHP、nginx、MySQLの3つのコンテナを1つづつ作成するという手間を掛けていましたが、今回はdocker-composeを使って楽に作ります。
作業環境は
- OS Ubuntu 20.04.2 LTS
- Docker version 20.10.7
- docker-compose version 1.29.2
です。
PHPアプリコンテナを作る
docker-composeでは複数のコンテナをまとめて操作できますが、素人なので一つづつ進めます。
以下のようにディレクトリとファイルを作成します。
lwd-4
├─ docker
│ └─ php
│ │ Dockerfile ← phpコンテナの定義ファイル
│ └
│ docker-compose.yml ← 構成ファイル
└─ src
“Dockerfile"ファイルを作成するときの注意ですが、RUN
命令は実行するたびにDockerイメージのレイヤーが増えていくので、なるべく一つにまとめたほうが良いみたいです。レイヤーが増えることで作成されるDockerイメージが肥大化するようですが、実際にどうなのかはよく分かりません。
とにかく、コマンドを一つにまとめるため、コマンドは’&&‘で結合します。複数のコマンドを記述するのに’&&‘と’;‘がありますが以下の違いがあります。
- ‘&&‘はエラーが起きたら停止し、次のコマンドは実行されません。
- ‘;‘はエラーを無視し、次のコマンドも実行します。
Dockerfile
# FROM : これから作るイメージの元ととなるイメージ
# Debian 10でphp8.0.7のFastCGI実装イメージを元に作成する
FROM php:8.0.7-fpm-buster
# RUN : コンテナ内でコマンドを実行する
# Composerの公式ページにあるコマンドでインストールする
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
&& php composer-setup.php \
&& php -r "unlink('composer-setup.php');" \
&& mv composer.phar /usr/local/bin/composer
# Laravelのインストール
RUN apt-get update \
&& apt-get install -y \
unzip \
git \
&& composer global require laravel/installer \
&& docker-php-ext-install pdo_mysql
docker-compose.yml
version: "3.8" # Docker Engin 19.03.0以降
services:
# PHP サービス
php:
build: ./docker/php # Dockerファイルの場所を指定
volumes:
- ./src/:/var/www # Laravelアプリの配置ディレクトリ
networks:
- examnet
# Dockerネットワーク
networks:
# コンテナ同士はホストから独立したネットワークで通信し、"examnet"という名前をつける
examnet:
driver: bridge
とりあえずPHPコンテナの定義を行ったので、docker-composeでコンテナを起動してみます。
-d
オプションを付けてバックグラウンドで実行します。
$ cd lwd-4
~/lwd-4$ docker-compose up -d
docker-compose ps
でコンテナが実行されているか確認することができます。
~/lwd-4$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------
lwd-4_php_1 docker-php-entrypoint php-fpm Up 9000/tcp
phpコンテナが起動していることが確認できたので、中に入ってLaravelアプリを作成します。
$ docker-compose exec php /bin/bash
laravelへのパスを設定し、アプリを新規作成します。
root@c6c4226fd32e:/var/www/html# export PATH="$HOME/.composer/vendor/bin:$PATH"
root@c6c4226fd32e:/var/www/html# cd ..
root@c6c4226fd32e:/var/www# laravel new example-app
“lwd-4/src/example-app"ディレクトリにいろいろなファイルが作成されました。
ディレクトリのアクセス権限を変更し、コンテナから出ます。
root@c6c4226fd32e:/var/www# chmod o+w example-app/storage/logs
root@c6c4226fd32e:/var/www# chmod o+w example-app/storage/framework/sessions
root@c6c4226fd32e:/var/www# chmod o+w example-app/storage/framework/views
root@c6c4226fd32e:/var/www# exit
次にブラウザから見れるようにnginxコンテナを作成します。
nginxコンテナを作る
“lwd-4/docker/nginx/“ディレクトリを作成し、そこにnginxの設定ファイルを作成します。 また、“docker-compose.yml"ファイルにnginxコンテナを追記します。
lwd-4
├─ docker
│ ├─ nginx ← 作成するディレクトリ
│ │ │ default.conf ← nginxの設定ファイル
│ │ └
│ └─ php
│ │ Dockerfile
│ └
│ docker-compose.yml ← 構成ファイルを更新する
└─ src
└─ example-app
前回まではIPアドレスでPHPコンテナを参照していましたが、docker-composeではサービス名で参照することができるので"php"と記述します。
“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 php:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
“docker-compose.yml"ファイルにnginxコンテナを追記します。
version: "3.8" # Docker Engin 19.03.0以降
services:
# PHP サービス名:php
php:
build: ./docker/php # Dockerファイルの場所を指定
volumes:
- ./src/:/var/www # Laravelアプリの配置ディレクトリ
networks:
- examnet
# nginx Webサーバー サービス名:web
web:
# 作成元イメージ
image: nginx:1.21.0-alpine
# nginxコンテナのポート80を外部にポート8080として公開する
ports:
- 8080:80
# nginxの設定ファイルを置き換える
volumes:
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
networks:
- examnet
# Dockerネットワーク
networks:
# コンテナ同士はホストから独立したネットワークで通信し、"examnet"という名前をつける
examnet:
driver: bridge
今まで作成したコンテナはいらないのでdocker-compose down
コマンドで削除します。
~/lwd-4$ docker-compose down
Stopping lwd-4_php_1 ... done
Removing lwd-4_php_1 ... done
Removing network lwd-4_examnet
削除できたらdocker-compose up -d
でまとめて再作成します。
~/lwd-4$ docker-compose up -d
Creating network "lwd-4_examnet" with driver "bridge"
Creating lwd-4_web_1 ... done
Creating lwd-4_php_1 ... done
2つのコンテナが起動していることが確認できます。
~/lwd-4$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------
lwd-4_php_1 docker-php-entrypoint php- Up 9000/tcp
fpm
lwd-4_web_1 /docker-entrypoint.sh ngin Up 0.0.0.0:8080->80/tcp,:::808
... 0->80/tcp
ブラウザでhttp://127.0.0.1:8080/
が見れることも確認します。
MySQLコンテナを作る
MySQLのデータを置くデイレクトリを作成します。
lwd-4
├─ docker
│ ├─ db
│ │ └─ data ← 作成するディレクトリ
│ ├─ nginx
│ │ │ default.conf
│ │ └
│ └─ php
│ │ Dockerfile
│ └
│ docker-compose.yml ← 構成ファイルを更新する
└─ src
└─ example-app
│ .env ← MySQLへの接続設定する
└─
PHPコンテナからMySQLコンテナへの接続設定を行います。 ホストの”~/lwd-4/src/example-app/.env"ファイルを編集しまが、今までのようにIPアドレスではなく"docker-compose.yml"のサービス名が使用できます。
元のファイルから以下の箇所を変更します。 ~/lwd-4/src/example-app/.envファイルの一部抜粋
・・・省略・・・
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laraveldb
DB_USERNAME=user4th
DB_PASSWORD=pwuser4th
・・・省略・・・
“docker-compose.yml"ファイルにMySQLコンテナの定義を追記します。PHPコンテナの接続設定で使用した値を環境変数に設定します。
version: "3.8" # Docker Engin 19.03.0以降
services:
# PHP サービス名:php
php:
build: ./docker/php # Dockerファイルの場所を指定
volumes:
- ./src/:/var/www # Laravelアプリの配置ディレクトリ
networks:
- examnet
# nginx Webサーバー サービス名:web
web:
# 作成元イメージ
image: nginx:1.21.0-alpine
# nginxコンテナのポート80を外部にポート8080として公開する
ports:
- 8080:80
# nginxコンテナはPHPのコンテナに依存 先にphpコンテナを起動する
depends_on:
- php
volumes:
# アプリディレクトリ
- ./src:/var/www
# nginxの設定ファイルを置き換える
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
networks:
- examnet
# MySQL データベースコンテナ サービス名:mysql
mysql:
image: mysql/mysql-server:8.0.25
# MySQLコンテナで使用する環境変数
# コンテナ作成時にこの内容で初期化さされます
# laraveldbデータベース、user4thユーザーがpwuser4thパスワードで作成され
# rootユーザーバスワードはmy-root-pwになります
environment:
MYSQL_DATABASE: laraveldb
MYSQL_USER: user4th
MYSQL_PASSWORD: pwuser4th
MYSQL_ROOT_PASSWORD: my-root-pw
# ホストのディレクトリをコンテナに割り当てる
# そうしないとコンテナを終了したらデータが残らない
volumes:
# MySQLのデータを置くディレクトリ
- ./docker/db/data:/var/lib/mysql
networks:
- examnet
# Dockerネットワーク
networks:
# コンテナ同士はホストから独立したネットワークで通信し、"examnet"という名前をつける
examnet:
driver: bridge
今まで作成したコンテナはいらないのでdocker-compose down
コマンドで削除し、docker-compose up -d
でまとめて再作成します。
~/lwd-4$ docker-compose down
~/lwd-4$ docker-compose up -d
~/lwd-4$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------
lwd-4_mysql_1 /entrypoint.sh Up (health: 3306/tcp,
mysqld starting) 33060/tcp,
33061/tcp
lwd-4_php_1 docker-php- Up 9000/tcp
entrypoint php-fpm
lwd-4_web_1 /docker- Up 0.0.0.0:8080->80/tc
entrypoint.sh ngin p,:::8080->80/tcp
...
MySQLコンテナに入って確認してみます。
~/lwd-4$ docker-compose exec mysql /bin/bash
bash-4.4# mysql -u root -p
Enter password: ← 環境変数で指定したパスワード"my-root-pw"を入力します
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| laraveldb | ← 環境変数で指定したDBがあります
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> select user, host from mysql.user;
+------------------+-----------+
| user | host |
+------------------+-----------+
| user4th | % | ← 環境変数で指定したユーザーがあります
| healthchecker | localhost |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
6 rows in set (0.00 sec)
mysql> quit ← mysqlツールを終了します
Bye
bash-4.4# mysql -u user4th -p ← 環境変数で指定したユーザーで接続できるか確認します
Enter password: ← 環境変数で指定したパスワード"pwuser4th"を入力します
mysql> ← 接続できることが確認できたので、
mysql> quit ← mysqlツールを終了します
Bye
bash-4.4# exit ← mysqlコンテナから脱出します
exit
~/lwd-4$
次にphpコンテナがmysqlコンテナに接続できるか確認します。
phpコンテナに入り、アプリのディレクトリへ移動して、migrate
コマンドを実行します。
izumi@ohishi-vm:~/lwd-4$ docker-compose exec php /bin/bash
root@4a80a824cd22:/var/www/html# cd ..
root@4a80a824cd22:/var/www# cd example-app
root@4a80a824cd22:/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,273.71ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (606.40ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (651.17ms)
正常に終わったようなのでphpコンテナから脱出して、mysqlコンテナを確認してみます。
root@4a80a824cd22:/var/www/example-app# exit
exit
~/lwd-4$ docker-compose exec mysql /bin/bash
bash-4.4# mysql -u user4th -p
Enter password:
mysql> use laraveldb;
mysql> show tables;
+---------------------+
| Tables_in_laraveldb |
+---------------------+
| failed_jobs | ← phpコンテナからテーブルが作成されています
| migrations |
| password_resets |
| users |
+---------------------+
4 rows in set (0.00 sec)
テーブルが作られていたのでphpからMySQLへの接続ができてます。