概要
自分用の備忘録です。
用語が間違っていたり、理解が微妙に違うこともあるかもしれませんが、あくまで自分用ですのでご了承ください。
目標
コンテナ環境を構築して、nginx経由でLaravelにアクセスできるようにします。
LaravelからはMysqlやRedisにもアクセスできることとします。
使用バージョン
2023/6/16時点でのLaravel最新バージョンを使用。
各ソフトウェアのバージョンもそれに合わせたものを使用します。
Laravel:10
PHP:8.2
nginx: 1.25.1
mysql: 8.1.0
redis: 7.0
手順
ディレクトリを用意する
今回の作業ディレクトリはstudy
という名前で用意しました。
この作業ディレクトリにdocker
ディレクトリを作成します。
$ mkdir docker
$ ls
docker
コンテナに関するファイルは、こちらのdockerディレクトリに追加していきます。
Dockerfileを用意する
nginxのDockerfileを作成
dockerディレクトリにnginxディレクトリを作成し、そのディレクトリ内にDockerfile
を作成します。
$ pwd
/Users/username/study/docker
$ mkdir nginx
$ ls
nginx
$ cd nginx
$ vim Dockerfile
今回はDockerHubの公式イメージを元に少し調整したものを使用します。
Docker Hub nginx Official Image
※既存イメージをそのまま使用する場合はDockerfileは不要となります。
FROM nginx:1.25.1
ENV LANG ja_JP.UTF-8
nginxコンテナを動かしてみる
正しくDockerfile
が用意できたことを確認するために、試しにnginxコンテナを動かしてローカルアクセスしてみます。
この手順はスキップ可能です。
$ docker build -t nginx:latest .
$ docker run -it -d -p 80:80 --name nginx_container nginx
$ docker exec -it nginx_container bash
$ nginx -v ←コンテナ内で実行
nginx version: nginx/1.25.1
バージョンが表示されれば成功です。
Webブラウザでlocalhost:80
にアクセスするとnginxのデフォルトページが表示されます。
起動するときはポートの指定を忘れないように…!
PHPのDockerfileを作成
dockerディレクトリにphpディレクトリを作成し、このディレクトリ内にDockerfile
を作成します。
$ pwd
/Users/username/study/docker
$ mkdir php
$ ls
php
$ cd php
$ vim Dockerfile
今回はDocker Hubの公式イメージを元に少し調整したものを使用します。
Docker Hub php Official Image
FROM php:8.2-fpm
ENV LANG ja_JP.UTF-8
後でたくさん書き足すのですが、順を追って書いていきたいのでひとまずこれだけ記載しておきます。
MysqlのDockerfileを作成
dockerディレクトにmysqlディレクトリを作成し、mysqlディレクトリ内にDockerfileを作成します。
$ pwd
/Users/username/study/docker
$ mkdir mysql
$ ls
mysql
$ cd mysql
$ vim Dockerfile
今回はDockerHubの公式イメージを少し調整したものを使用します。
Docker Hub mysql Official Image
FROM mysql:8.1.0
ENV LANG ja_JP.UTF-8
reidsのDockerfileを作成
dockerディレクトリにredisディレクトリを作成し、redisディレクトリ内にDockerfileを作成します。
$ pwd
/Users/username/study/docker
$ mkdir redis
$ ls
redis
$ cd redis
$ vim Dockerfile
今回はDocker Hubの公式イメージを元に少し調整したものを使用します。
Docker Hub redis Official Image
FROM redis:7.0
ENV LANG ja_JP.UTF-8
docker-composeを作成
docker-composeは複数のコンテナを一括管理するためのツールです。
docker-compose.ymlにあらかじめ各コンテナをオプション等を起動することで、毎回オプションを入力することなく、自動でコンテナの起動などを行うことができます。
dockerディレクトリと同じ階層にdocker-compose.yml
を作成します。
$ pwd
/Users/username/study
vim docker-compose.yml
version: '3'
services:
nginx:
build: docker/nginx
ports:
- "80:80"
depends_on:
- php-fpm
php-fpm:
build: docker/php
depends_on:
- mysql
- redis
mysql:
build: docker/mysql
volumes:
- docker/mysql/var/lib/mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: test
MYSQL_USER: test
MYSQL_PASSWORD: test
redis:
build: docker/redis
nginx
nginxコンテナにはコンテナの外からアクセスがいくので、ポートを指定しておく必要があります。
今回はホストコンピュータ/nginxコンテナの両ポート共に80に設定してあります。
また、nginxコンテナはphp-fpmコンテナ起動後に起動してほしいため、起動順序の設定も記載しておきます。
php-fpm
また、php-fpmコンテナはmysqlコンテナとredisコンテナの起動後に起動してほしいため、起動順序の設定を記載しておきます。
mysql
mysqlコンテナは環境変数をいくつか設定する必要があります。
公式ドキュメントに沿って設定していきます。
MYSQL_ROOT_PASSWORD
ルートユーザーのパスワードを設定します。この変数は必須です。
本来はファイルに機密事項を記載しない方がよく、別ファイルから変数を読み込む方法がありますが、ひとまず割愛します。
MYSQL_DATABASE
コンテナ起動時に作成するデータベースを指定します。
ユーザー/パスワードを指定した場合、そのユーザーにはGRANT ALLのアクセス権が付与されます。
MYSQL_USER
, MYSQL_PASSWORD
MYSQL_DATABASEで作成したデーターベースにアクセスできるユーザーを作成します。
この変数はオプションであり必須ではありませんが、ユーザー作成をする場合は両オプションを指定する必要があります。
また、今回使用するデータベースでは、コンテナを停止した際にもデータが消えないようにしたいので、追加で設定をしていきます。
公式ドキュメントに記載されている方法は2通りありますが、今回はホストコンピュータにデータ保存用のvar
ディレクトリを作成し、/var/lib_mysql
ディレクトリにマウントします。
マウントの設定は上記のdocker-compose.yml
に記載した通りで、マウント用のディレクトリは下記手順で作成します。
$ pwd
/Users/username/study/docker/mysql
$ mkdir var
$ ls
Dockerfile var
コンテナを起動し、データが作成されると、varディレクトリにも同じファイルが保存されます。
redis
特に追加で必要な設定はないため、build
のみ指定しておきます。
docker-composeでコンテナを起動
docker-compose up -d
上記コマンドを実行することで、イメージのビルドからコンテナ起動までを一括で行ってくれます。
イメージが存在する場合はビルドがスキップされるので、Dockerfile
を更新した場合は--build
オプションをつけて実行します。
また、作業ディレクトリ名_default
という名前でネットワーク作成し、各コンテナをservice
項目で指定したサービス名でこのネットワークに接続してくれます。
Laravelアプリケーションを作成
コンテナの作成が完了したので、Laravelアプリケーションを作成し、各コンテナをLaravel用に調整していきます。
必要なコマンドをインストール
LaravelのインストールにはGitやunzipなどのコマンドが必要になるため、php-fpmコンテナのDockerfileにインストールのコマンドを追記します。
今回使用しているPHPのイメージはdebian:12-slim
を元に作成されており、パッケージのインストールにはapt
/apt-get
コマンドが使用できるようになっています。
RUN apt-get update \
&& apt-get install -y git zlib1g-dev libzip-dev unzip \
&& pecl install zip \
&& docker-php-ext-enable zip
RUNコマンドは元となるdockerイメージに対して実行する処理を記述します。
バックスラッシュを用いることで、複数行に分けて記載可能です(見やすいように改行して記載できる)。
&&をつけることで1つのRUNコマンドに対して複数の処理を記載でき、これらを1つのレイヤとしてみなされるため、軽量になります。
コンテナに入って、試しにGitがインストールされていることを確認してみます。
php-fpmコンテナのイメージを更新したので、コンテナに反映するためには再ビルドする必要があります。
現在コンテナが起動状態のため、一度コンテナを停止・削除してから再ビルド・コンテナ作成・起動を行います。
$ docker-compose down
$ docker-compose up -d
$ docker exec -it <CONTAINER ID> bash
$ git -v
git version 2.39.2
Gitのバージョンが表示されることが確認できました。
確認が済んだので、一旦コンテナを落としておきます。
$ exit
$ docker-compose down
Composerをインストール
php-fpmコンテナにComposerをインストールします。
今回はComposer公式ドキュメントに記載されている方法でインストールするので、インストールコマンドを実行するように、php-fpmコンテナのDockerfile
に実行コマンドを追記します。
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php -r "if (hash_file('sha384', 'composer-setup.php') === 'e21205b207c3ff031906575712edab6f13eb0b361f2085f1f1237b7126d785e826a450292b6cfd1d64d92e6563bbde02') { 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
php-fpmコンテナのイメージを更新したので、コンテナに反映するためには再ビルドが必要です。
$ docker-compose up -d --build
これで再起動が完了しました。
php-fpmコンテナの中に入って、Composerがインストールされていることを確認してみます。
$ docker exec -it <CONTAINER ID> bash
$ composer -v
上記コマンドでComposerのバージョンが表示されればOK。
確認ができたので、一旦コンテナを落としておきます。
$ exit
$ docker-compose down
Laravelをインストール
次に、Composerを使用してLaravelをインストールします。
Composerはphp-fpmコンテナにインストールされているため、php-fpmコンテナ内でLaravelのインストールを行います。
また、コンテナ内のLaravelプロジェクト用ディレクトリとローカルのディレクトリをマウントさせておくことで、ローカルでの差分をすぐにコンテナに反映させることができるため、マウントの設定も追加していきます。
まず、ローカルにマウント用のprojectディレクトリを作成します。
$ pwd
/Users/username/study
$ mkdir project
$ ls
docker docker-compose.yml project
docker-compose.ymlにマウントの設定を足します。
projectディレクトリには書き込み/読み取りの権限を付与しておきます。
php-fpm:
build: ./docker/php
volumes:
- ./project:/project:rw ← NEW!
depends_on:
- mysql
- redis
これでもう一度起動すると、projectディレクトリがマウントされます。
もう一度コンテナを起動し直して、php-fpmコンテナ内でLaravelプロジェクトをインストールします。
$ cd /
$ composer create-project laravel/laravel project
インストール完了後にローカルのprojectディレクトリを確認すると、Laravelがインストールされています。
localhostでLaravelにアクセスする
locahostにアクセスしたときに、Laravelのページが表示されるようにします。
そのためにはnginxの設定を修正する必要があります。
nginxのconfファイルを修正
localhostにアクセスしたときに、Laravelのpublic/index.php
が表示されるように修正する必要があります。
nginxコンテナのdefault.conf
をローカルにコピーして、必要に応じて修正したものを、コンテナ起動時にnginxコンテナのdefault.conf
に上書きします。
ローカルのファイルはdocker/nginx/conf/default.conf
にコピーします。
$ pwd
/Users/username/study/docker/nginx
$ mkdir conf
$ cd conf
$ vim default.conf
$ cat /etc/nginx/conf.d/default.conf
nginxコンテナのdefault.conf
の内容は以下の通りです。
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
catコマンドで表示・コピーしてきたものを、ローカルのdefault.confにコピーします。
ここからLaravel公式ドキュメントを参考に設定を修正していきます。
server {
:
:
root /project/public;
index index.php
location / {
try_files $uri $uri/ /index.php?$query_string;
}
:
:
Laravelでは全ての処理をpublic/index.phpから始めます。 そのため、locationのrootをproject/public、indexをindex.phpに変更し、locationの外に記述します。
try_files`は左から順にファイルまたはディレクトリを探してくれる設定です。
さらに下記の設定も修正します。
server {
:
:
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
:
:
fastcgi_pass
にはphp-fpmコンテナのサービス名とポート番号を指定します。
ポート番号はdocker ps
またはdocker-compose ps
コマンドを実行することで確認できます。
fastcgi_param
とinclude
の値はは公式ドキュメントのままです。
次に、このdefault.conf
をコンテナ起動時にphp-fpmコンテナのdefault.conf
に上書きするための設定を追加します。
COPY conf/default.conf /etc/nginx/conf.d/default.conf
COPY
コマンドで上書きが可能です。
ローカルに置いてあるファイルはDockerfile
から見たパスを記載します。
また、nginxコンテナにもLaravelプロジェクトを配置するため、docker-compose.yml
にマウントの設定を追加します。
nginx:
build: ./docker/nginx
volumes:
- ./project:/project:ro ← NEW!
ports:
- "80:80"
depends_on:
- php-fpm
設定が完了したのでイメージのビルド/コンテナの立ち上げを行います。
localhostにアクセスすると、Laravelのデフォルトのページが表示されます。
LaravelからDBにアクセス
LaravelからDBにアクセスするには設定の追加が必要になります。
LaravelのDBアクセス時に使用するドライバーの設定は、config/database.php
に記載されており、さらにそこではenvファイルからの読み込みが行われています。
なので、.env
ファイルを修正する必要があります。
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=test
DB_USERNAME=test
DB_PASSWORD=test
DB_HOST
にはdocker-compose.yml
で設定したMysqlコンテナのサービス名、DB_DATABASE
/DB_USERNAME
/DB_PASSWORD
にはそれぞれMYSQL_DATABASE
/MYSQL_USER
/MYSQL_PASSWORD
を記述します。
また、この設定を追加しただけではうまくドライバーを読み込んでくれないので、拡張モジュールをインストールする必要があります。
config/database.php
のmysqlのoptionsにpdo_mysql
をロードする旨が記載されているため、pdo_mysql
をインストールするようphp-fpmコンテナ用のDockerfileに下記を追記します。
RUN docker-php-ext-install pdo_mysql
ここでは新たにRUNコマンドを記載していますが、実際のファイルにはgit等をインストールしたときに記載したRUNコマンドに追記する形で記載しています。
これでDBにアクセスできるはず。
確認のために、適当なテーブルとデータを作成し、そのデータをLaravel側から読み込みできるようにしてみます。
まずmysqlコンテナからmysqlにログインし、testDBにexample_table
テーブルを作成します。
また、2件の適当なデータも作成しておきます。
$ docker exec -it <CONTAINER ID> bash
$ mysql -utest -p --port 3306
mysql > use test
mysql > create table example_table (id int(11) auto_increment not null, name varchar(30) not null, age int(3) not null, primary key (id));
mysql> desc example_table;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(30) | NO | | NULL | |
| age | int | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+
mysql> insert into example_table (name, age) values ('Sato', 25), ('Tanaka', 30);
mysql> select * from example_table;
+----+--------+-----+
| id | name | age |
+----+--------+-----+
| 1 | Sato | 25 |
| 2 | Tanaka | 30 |
+----+--------+-----+
データの作成が完了したので、artisanコマンドを使って実際にDBアクセスしてみます。
$ pwd
/project
php artisan db:table example_table
example_table ...........................................
Columns ............................................... 3
Size ............................................ 0.02MiB
Column ............................................. Type
id autoincrement, integer ....................... integer
name string ...................................... string
age integer ..................................... integer
Index ...................................................
PRIMARY id .............................. unique, primary
テーブル情報が正しく取得できました。
次にtinkerを実行し、テーブルデータを取得できるかどうかも確認してみます。
$ pwd
/project
$ php artisan tinker
> use Illuminate\Support\Facades\DB;
> DB::table('example_table')->get()
= Illuminate\Support\Collection {#6225
all: [
{#6228
+"id": 1,
+"name": "Sato",
+"age": 25,
},
{#6230
+"id": 2,
+"name": "Tanaka",
+"age": 30,
},
],
}
データを取得できることが確認できました。
さらに、php-fpmコンテナからartisanコマンド経由でmysqlにログインできるようにします。
php-fpmコンテナのDockerfile
にmysql-cli
のインストールを追記します。
RUN apt-get install -y git default-mysql-client
再度ビルドし、立ち上げ直すとmysq-cliがインストールされます。
実際にartisanコマンドを叩いてみます。
$ pwd
/project
$ php artisan db
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.1.0 MySQL Community Server - GPL
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
MySQL [test]>
artisanコマンド経由でmysqlにログインすることができました。
LaravelからRedisにアクセス
LaravelからRedisにアクセスするには設定の追加が必要になります。
LaravelのRedisアクセス時に使用するドライバーの設定は、config/database.php
に記載されており、さらにそこではenvファイルからの読み込みが行われています。
なので、.env
ファイルを修正する必要があります。
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379
REDIS_HOST
にはdocker-compose.yml
で設定したRedisコンテナのサービス名を記述します。
また、この設定を追加しただけではうまくドライバーを読み込んでくれないので、php-fpmコンテナに拡張モジュールを追加します。
RUN pecl install redis \
&& docker-php-ext-enable redis
これで動くようになったか実際に確認してみます。
artisanコマンド経由でRedisに適当な値を保存してみます。
$ pwd
/project
$ php artisan tinker
> use Illuminate\Support\Facades\Redis;
> Redis::set(“example”, "test");
= true
Redisファサードを使用して保存したため、config/database.php
のdefault
の設定を使用しています。
今回はホスト以外の値はデフォルトのままなので、redisコンテナのDB0に保存されているはずです。
また、REDIS_PREFIX
の設定をしていないため、デフォルトの設定によりlaravel_database_example
というkeyで保存されます。
$ redis-cli
127.0.0.1:6379> get laravel_database_example
"test"
redisに値が保存されていることが確認できました。
redisで保存した値を取得することも可能です。
$ redis-cli
127.0.0.1:6379> set laravel_database_example2 aaaaaaaaaaaaaa
OK
$ pwd
/project
$ php artisan tinker
> use Illuminate\Support\Facades\Redis;
> Redis::get("example2");
= "aaaaaaaaaaaaaa"
また、php-fpmコンテナ内からredisにログインできるようにDockerfile
を調整します。
RUN apt-get install -y redis-tools
再ビルドして反映すると、php-fpmコンテナでredis-cliが使用できるようになります。
ホストをredis
にすることで、redisコンテナのredisサーバーに接続することができます。
$ redis-cli -h redis
redis:6379>