ブログを書くのがかなり久しぶりになります。
最近 Laravel を触ってまして、Docker で環境構築して使うことが増えてきたので備忘録として書いておこうと思うので、これから触ってみたいという方の参考になれば嬉しいです
今回実行した環境は以下のとおりです
- Mac Apple M1 MAX
- Ventura 13.1
Docker の仕様について
下記環境を構築します
- Webサーバー: NginX
- PHP: php-fpm (php:8.0.5-fpm-alpine)
- Database: MariaDB
まずは Docker が入ってない人は Docker をインストールしましょう
Docker はわかりやすく概要を説明すると、コンテナに必要なアプリケーションをイメージという単位で構築し、それぞれに上記で記載している Web サーバーや PHP, Database といったアプリケーションやミドルウェアなど自分に必要な構成で自分の端末に構築できる仕組みです。
自分の端末に直接 Web サーバーや Laravel をインストールして動かすこともできますが、案件によって Web サーバーを変更したり PHP のバージョンを変更するのは手間がかかります。
Docker なら必要なときに必要な構成を docker-compose.yml というファイルに定義しておくことでいつでも立ち上げたりシャットダウンしたり、削除することができるので、切り替えが容易に行えて楽です。
また設定ファイルを共有すれば、他の人にもすぐに同じ環境を用意してもらえるので、共同開発するのも便利。
かなり端的に概要を書いているので、もっと詳しく知りたい方はサーバー会社のさくらインターネットさんが公開している「さくらのナレッジ」の記事を読んでみましょう
Docker入門(第一回)~Dockerとは何か、何が良いのか~:さくらのナレッジ
docker-compose.yml
version: "3"
services:
web:
image: nginx:latest
ports:
- 8000:80
volumes:
- ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
- .:/var/www/html
depends_on:
- php-fpm
php-fpm:
build: ./docker/php
volumes:
- .:/var/www/html
depends_on:
- db
db:
image: mariadb:latest
ports:
- 33306:3306
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: root
MYSQL_PASSWORD: root
MYSQL_DATABASE: sampledb
volumes:
- ./db-data:/var/lib/mysql
今回開発するフォルダを作成し、上記ファイルを保存しましょう。
作成するフォルダを sample とし、ユーザーディレクトリに作成した場合下記構成になります。
~/sample/docker-compose.yml
~/ はユーザーディレクトリを指します
このファイルを書く場合インデントに注意してください。インデントが崩れているとエラーになります。
Web サーバー NginX の設定
NginX の設定ファイルが必要なので、default.conf というファイルを用意します
default.conf
server {
listen 80;
root /var/www/html;
index index.php index.html index.htm;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location ~ \.php$ {
root /var/www/html/sample/public;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
root の位置は自分の作成したフォルダが sample
なので、/var/www/html/sample/public
になります。docker-compose.yml
で名前を変更した場合は、このディレクトリ構造の sample
を自分が docker-compose.yml
で指定した値に合わせてください
同様に fastcgi_pass
には docker-compose.yml
に記載している php-fpm
を指定し、ポートはデフォルトの9000番を割り当てています。
このファイルは下記のように配置します
~/sample/docker/web/
│ └──default.conf
└──docker-compose.yml
ここで docker を起動しましょう
ターミナルなどで下記コマンドを実行します。場所は ~/sample に移動してから実行。(%は入力不要です)
% docker-compose up -d
データベース MariaDB
docker-compose.yml に MariaDB
への接続情報を記載しています
上記記載の docker-compose.yml から抜粋
db:
image: mariadb:latest
ports:
- 33306:3306 //← 外部から接続する時のポート番号:内部接続時のポート番号
environment:
MYSQL_ROOT_PASSWORD: root //← Root のパスワード
MYSQL_USER: root //← ユーザー名
MYSQL_PASSWORD: root //← パスワード
MYSQL_DATABASE: sampledb //← 作成するデータベース名
volumes:
- ./db-data:/var/lib/mysql
まずはデータベースが起動しているか確認してみましょう
下記コマンドをターミナルで入力してデータベースのコンテナに接続します
% docker-compose exec db sh
docker-compose exec ○○ sh で起動している○○( docker-compose.yml で定義している services: 内部に記載している web, php-fpm, db のどれか )に接続するという意味です。接続すればターミナルの操作が自分の端末ではなく、コンテナ上での操作に変わります。
#
環境によって異なりますが、% から # のようにターミナルの開始記号が変わっていれば、コンテナに接続できています。
コンテナから抜けたい場合は exit コマンドで。
# exit
%
このように切り替わったことを確認しながら今自分の端末を操作しているのか、コンテナを操作しているのか判断できるようになりましょう。
説明どおりに進めているとコンテナから抜けているので、改めてコンテナに接続します。
% docker-compose exec db sh
次にコンテナ内のデータベースに接続します
# mysql -u root -proot sampledb
mysql コマンドの -u はユーザーをしてするオプション、-p はそのまま続けてパスワードを入力するオプションで、最後に接続するデータベース名を記載します。
これらコマンドを使う時は下記に気をつけてください
- 小文字大文字を間違えてないか
- 半角スペースが全角スペースになっていないか
ハイフンが付いているものはオプションです。-p については続けて入力するパスワードを省くと、コマンド実行後にパスワードを確認してきます。
どちらの方法でも下記のようなメッセージが表示されれば接続できています
Laravel インストール
今回利用するバージョンは 9.52.7 になります
Laravel は PHP のフレームワークになるので、PHP の必要なパッケージやモジュールをインストールするために Docker ファイルを作成します
作成場所は先に記載している docker-compose.yml
に記載している php-fpm の build 部分にしている場所になります
上記記載の docker-compose.yml から抜粋
php-fpm:
build: ./docker/php
ファイル構成で示すと下記の構成になります
~/sample/docker/php/
│ │ └──Dockerfile
│ └─/web/
│ └──default.conf
└──docker-compose.yml
Dokerfile
FROM php:8.0.5-fpm-alpine
RUN apk --update add \
&& apk add build-base curl git zip tar unzip vim oniguruma-dev
RUN cd /usr/bin && curl -sS https://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer
RUN apk add libxml2-dev curl-dev $PHPIZE_DEPS
RUN pecl install xdebug-3.1.5
RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-install mbstring
RUN docker-php-ext-install xml
RUN docker-php-ext-install curl
RUN docker-php-ext-install session
RUN docker-php-ext-install tokenizer
RUN docker-php-ext-enable pdo_mysql mbstring xml curl session tokenizer xdebug
WORKDIR /var/www/html
RUN docker-php-ext-install のように重複している箇所ははまとめて記述することもできます
RUN docker-php-ext-install pdo_mysql mbstring xml curl session tokenizer
ただこの場合どれかのパッケージインストール時にエラーが有る場合、原因が特定しづらいので分けておけばどのパッケージでエラーが出たかわかりやすくなります。
RUN
以降を Docker のコンテナ起動時に実行- apk add でパッケージのインストールを行います。
$PHPIZE_DEPS
の指定はphpize
に必要なパッケージのインストール。PHP拡張モジュールを動的にビルドするのに必要なもので、この指定がないと PHP 本体をビルドし直すことになります。pecl install xdebug
は PHP のデバッグツールですが僕が今回インストールした際にバージョン指定なしでインストールするとエラーが発生したので 3.1.5 を指定しています。docker-php-ext-install
PHP の拡張インストールで、docker-php-ext-enable
を使って有効化しています。
コンテナ再構築
PHP の設定ファイルを追加したので docker-compose
を再度実行し、コンテナを再構築します
% docker-compose up -d
構築が終わったら Laravel をインストールするため php-fmp のコンテナに接続し、インストールコマンドを実行します
% docker-compose exec php-fpm sh
接続するとターミナルの開始記号が下記のようになるはずなので
/var/www/html #
この状態でインストールコマンドを実行します。
/var/www/html # composer create-project --prefer-dist laravel/laravel sample
最後の sample はアプリケーションの名前になり、作成したディレクトリにこの名前のフォルダが作成されます。
~/sample/db-data/
│ /docker/php/
│ │ └──Dockerfile
│ └─/web/
│ └──default.conf
│ /sample/
└──docker-compose.yml
この sample
フォルダの中身が Laravel
プロジェクトになります
Laravel の welome ページをブラウザに表示
上記で作成している default.conf
にドキュメントルートの指定が入っています
default.conf より抜粋
root /var/www/html/sample/public;
この中の index.php
ファイルが Laravel プロジェクトをブラウザで表示する際のトップページになります。
そして、Laravel から データベースに接続する設定を .env というファイルに書き込まないとエラーになるので、.env を編集し MySQL の記述を下記に変更します。
Laravel プロジェクトフォルダ(今回だと sample )の直下に .env というファイルがありますが、見えない場合は不可視ファイルを表示するように設定が必要です
- Mac の場合
cmmand + shift + .
- Windows の場合 タスク バーから エクスプローラー を開く> [表示] > [表示] > [隠しファイル] を選択
.env の DB_ で始まる箇所を編集し、docker-compose.yml にある同一の項目と値を合わせます
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=sampledb
DB_USERNAME=root
DB_PASSWORD=root
- DB_CONNECTION の値は mysql になります。MariaDB ではないので注意しましょう
- DB_HOST の値は
docker-compose.yml
で指定しているサービス名になるので今回はdb
- DB_PORT の値はコンテナ同士を内部通信で行うので
docker-compose.yml
で指定したports
の右側の値(33306:3306) - DB_DATABASE, DB_USERNAME, DB_PASSWORD の値は
docker-compose.yml
に指定した名前をそのまま利用します
これで php-fpm のコンテナに接続し、データベースのコンテナへ接続できるので、php-fpm に接続した状態でデータベースのテーブル定義を Laravel のコマンドを利用して設定します。
コンテナに接続していない場合はまずは接続
% docker-compose exec php-fpm sh
接続したらドキュメントルートから始まるので、Laravel プロジェクトに移動
/var/www/html cd sample
/var/www/html は表示されているはずなので、コピーする際にコピーしないように気をつけてください
cd
というコマンドがディレクトリを移動するコマンドを意味し、今いる階層に存在する sample ディレクトリに移動するという意味になります。
移動したら Laravel の migrate コマンドを実行
/var/www/html/sample php artisan migrate
こんな感じで表示されれば成功。
これは Laravel プロジェクトに artisan ファイルが存在するからこのコマンドが利用できるので、エラーが出た場合は正しいディレクトリ位置にいるか確認してください。また今いる sample ディレクトリの中身を確認して artisan ファイルが存在するかも確認してみましょう。
ディレクトリ内のファイルを確認するには下記コマンドを実行
/var/www/html/sample ls -la
下記のように存在するファイル一覧を表示できます
また、自分の端末のユーザーディレクトリに sample ディレクトリを作成して開発しているので、ユーザーディレクトリの中身を Finder や エクスプローラで確認すれば同様に内部のファイル一覧が確認できます。
コンテナに接続して確認するのも、端末側から確認するのも同じファイルが確認できます。これは同じファイルを扱っている事になりますが下記の違いがあります
- コンテナに接続してアクセスする場合はルートディレクトリが Laravel ディレクトリになり、ドキュメントルートは default.conf に記述した設定になる(今回は
/var/www/html/photom/public
) - 端末から見る場合はルートは端末のルートディレクトリ
Docker の Web サーバーコンテナを利用しているので、これは仮想的なサーバーを端末の中に用意して利用している。こんなイメージを想像してもらえればわかりやすいと思います。
ここまでで準備は整いました。実際にブラウザに表示してみましょう。
/var/www/html/sample php artisan serve
php artisan serve
このコマンドで Web サーバーが起動します。
Web サーバーが起動すると ip アドレスが表示されるので、この ip アドレスをコピーしてブラウザに貼り付けてみます。
様子がおかしいですね。
コンテナ内部から起動するとこのように表示できないエラーが返ってきます。
これはコンテナ内部からの通信設定で起動しているからで、ブラウザを経由するような外部通信だと設定を変えないといけないんですよね。(これに気づくのに時間がかかりました)
ですので、まずは一度起動を停めます
Press Ctrl+C to stop the server
と記載があるので、キーボードを Ctrl + C
入力して停めます。そしてコンテナの接続から抜けて自分の端末接続に切り替えます
/var/www/html/sample exit
次に .env のファイルを書き換えます
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=33306
DB_DATABASE=photom
DB_USERNAME=root
DB_PASSWORD=root
変わるのは DB_HOST と DB_PORT ですね。内部通信・外部通信というのがいまいち理解しづらいですが、ターミナルでコンテナに接続してそこから別のコンテナに接続通信を行う場合は内部通信。ブラウザなどを使って外側から通信する場合が外部通信といった感じです。
内部通信の場合は DB_HOST の名前を docker-compose.yml
で指定しているサービス名を指定していましたが、外部通信に変更する場合は
- DB_HOST を 先程表示された ip アドレスに( 127.0.0.1 )
- DB_PORT を
docker-compise.yml
ファイルの内部と外部で設定した左側の内容に( 33306:3306 )
Laravel を触っていてブラウザに表示した際に接続エラーが出た場合は、この設定値に誤りがあるケースが多いので確認してみましょう。
ちなみになぜわざわざ外部と内部のポートを変えているかというと、自分の環境にほかの開発用アプリケーションがインストールしてあって、それらが既存の 80番や3306番を利用しているかで、ここがバッティングするとエラーになって使えないからです。
コンテナー同士の内部通信であればそれらの影響を受けないのでデフォルトの値で利用できますが、開発端末の方はそういうわけに行かないので、外部通信のポートをあえて変更して設定しています。
では改めて端末側からサーバーを起動してみましょう。必ず Laravel プロジェクトにいることを確認してください
% php artisan serve
先ほどと同じ用に ip アドレスが表示されるのでブラウザの画面を更新します
この画面が表示されれば成功です。
参考資料
今回記事執筆に参考させていただきました
Comments
koji
3年程前にraiseTechでお世話になったkojiです。 今dockerでlaravelとvueのアプリを作っているので参考にさせていたただきました。ありがとうございます。
YAT
Koji さん > 3年経ってエンジニアのスキルがかなり上がってるんですね、素晴らしいです! これからもよろしくお願いします