はじめに
この記事では、WSL2 を使用して Docker + Laravel の開発環境(LAMP 環境)を構築するまでの手順を解説しています。
WSL2 をインストール済みであることを前提としています。
WSL2 を導入するまでの手順は以下の記事で紹介しています。
やりたいこと
この記事では最終的に以下の機能を持った開発環境を構築していきます。今回は、太字の部分を実装していきます。
- Lravel の開発環境
- npm を導入して JavaScript FW の開発にも対応する
- リバースプロキシを導入して
test.example.com
のようなポート番号無しのドメインでアクセスできるようにする - mailhog を導入してメール送信のテストを行えるようにする
- X-Debug の導入
開発環境
- OS: Windows11(21H2)
- WSL: Ubuntu-20.04 Version 2
- Docker: Version 20.10.9
- Docker Compose: Version 1.29.2
ディレクトリ構成
今回作成するプロジェクトのディレクトリ構成は以下のようになっています。
適宜アレンジしてもらっても構いません。
docker-lamp
├── docker
│ ├── mailhog
│ │ └── Dockerfile
│ ├── mysql
│ │ ├── Dockerfile
│ │ ├── init
│ │ │ └── init.sql
│ │ └── my.cnf
│ ├── nginx-proxy
│ │ └── Dockerfile
│ ├── phpMyAdmin
│ │ └── Dockerfile
│ └── web
│ ├── Dockerfile
│ ├── apache
│ │ └── 000-default.conf
│ └── php
│ └── php.ini
├── docker-compose.yml
└── htdocs
└─ ここにLaravelのプロジェクトを作成する
Docker Compose とは?
Docker Compose とは、複数のコンテナの起動や停止・破棄などの処理を一連の操作をまとめて実行することができ、管理を容易にする機能のことです。
設定ファイルを用意し、コマンドを実行することでその設定ファイルを読み込んで全てのコンテナを起動することが出来ます。
docker-compose.yml の設定
docker-compose.yml
とは、Docker Compose を使ってコンテナを一元管理するための設定ファイルです。
今回使用するファイルの全体像です。
# Compose fileのバージョン指定
version: '3.8'
# 立ち上げるコンテナを記述していく
services:
nginx-proxy:
container_name: nginx-proxy-container
build: ./docker/nginx-proxy
ports:
- 80:80
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
# ApacheとPHPが動作するコンテナ
web:
# コンテナ名を指定する
container_name: web-container
# 作成したDockerfileを利用してコンテナをビルドする
build: ./docker/web
# ポートのマッピングを設定する
# 下記の記述だと、localhost:8081とブラウザから指定すると、Apacheの80番ポートに接続される
ports:
- 8081:80
# コンテナとホスト側のディレクトリを同期させる設定
volumes:
# Laravelのソースが入る箇所を同期
- ./htdocs:/var/www/html
# MySQLを動かすコンテナ
database:
# コンテナ名を指定
container_name: db-container
build: ./docker/mysql
volumes:
# ボリュームにマウントしデータを永続化する
- db-store:/var/lib/mysql
ports:
- 3306:3306
# PHPMyadminを動かすコンテナ
phpmyadmin:
# コンテナ名を指定
container_name: phpmyadmin-container
build: ./docker/phpMyAdmin
ports:
- 8082:80
# 依存関係をMySQLに設定
depends_on:
- database
# mailhogのコンテナ
mailhog:
# コンテナ名を指定
container_name: mailhog-container
build: ./docker/mailhog
ports:
# 管理画面に接続するポート(違うポート番号にすると管理画面に接続できない)
- 8025:8025
# 使用するボリュームを指定
volumes:
db-store:
docker-compose.yml のバージョン
まず最初に、Compose File のバージョンを指定する必要があります。
# Compose fileのバージョン指定
version: '3.8'
2021 年 10 月時点で、version
は3.8
を指定していれば問題ありません。
ただし、Compose ファイル形式をサポートしている Docker Engine のバージョンを合わせる必要があります。使用している環境に合わせて変更する必要がある場合があるので注意してください。
https://docs.docker.jp/compose/compose-file/compose-versioning.html
さらに詳細を知りたい場合は公式ページを参照してください。
各種コンテナの設定
コンテナの設定はservices:
配下に記述していきます。yml
ファイルはインデントを基準にして階層構造を作っていきます。要は設定項目を区切っていく形になります。
services:
# 立ち上げるコンテナを記述していく
#↑インデントで階層を合わせる
ファイルの先頭にリバースプロキシの設定を記述していますが、先にその他のサーバの設定を見ていたほうが分かりやすいと思ったので別の記事で紹 介します。
Web サーバの設定
まずは Web サーバの設定です。
services:
# 中略
# ApacheとPHPが動作するコンテナ
web:
# コンテナ名を指定する
container_name: web-container
# 作成したDockerfileを利用してコンテナをビルドする
build: ./docker/web
# ポートのマッピングを設定する
# 下記の記述だと、localhost:8081とブラウザから指定すると、Apacheの80番ポートに接続される
ports:
- 8081:80
# コンテナとホスト側のディレクトリを同期させる設定
volumes:
# Laravelのソースが入る箇所を同期
- ./htdocs:/var/www/html
サービス名は任意の名前を付けることができます。そのプロジェクトで何のサーバを動かしているか分かりやすい名前にするのが良いと思います。
コンテナ名の指定
ここではコンテナ名を指定しています。
container_name: web-container
必須項目ではありませんが、コンテナが複数存在して分かりにくい場合は明示しておくことで、どのプロジェクトと関係しているものなのか判別できると思います。
build:
Dockerfile のディレクトリのパスを指定します。
build: ./docker/web
今回のプロジェクトでは、docker
ディレクトリ配下に Dockerfile を配置しているのでそのディレクトリを指定しています。
ymlファイル
のある場所を起点としてパスを指定します。
port:
ポートマッピングの設定を行います。ポートマッピングとは、ブラウザ側からポートを指定してアクセスをした場合、動作しているコンテナのポートと対応づけを行うことです。
ports:
- 8081:80
この設定ではブラウザ側からhttp://localhost:8081
とアクセスした場合に、動作しているコンテナの80番ポート
にリクエストが対応されます。
80 番ポートは、Web サーバが Web ブラウザなどと HTTP 通信を行うために使用するポートです。
volumes:
volume
とは、データを永続化出来る場所のことです。イメージ的には外付け HDD のような役割を果たします。
通常コンテナ起動後、内部にデータを保存してもコンテナを破棄すると消えてしまいます。そのため、ホスト側の指定したディレクトリとコンテナ内のディレクトリをマウントさせることで、コンテナを停止したあともデータを保持することが出来ます。
volume を同期させるなどと言われることもあります。
# コンテナとホスト側のディレクトリを同期させる設定
volumes:
# ホスト側:コンテナ側
- ./htdocs:/var/www/html # Laravelのソースが入る箇所
Dockerfile の設定
Web サーバで使用する Dockerfile を作成します。
ここでは主に、Apache や PHP を実行するために必要なモジュールのインストールや、設定ファイルをコンテナにコピーする処理などが実行されます。
FROM php:8.1.9-apache-bullseye
# apacheの設定ファイルをコンテナにコピー
COPY ./apache/000-default.conf /etc/apache2/sites-available/000-default.conf
# phpの設定ファイルをコンテナにコピー
COPY ./php/php.ini /usr/local/etc/php/php.ini
# パッケージの更新及び必要ソフトのインストール
RUN apt-get update \
&& apt-get install -yqq \
zlib1g-dev \
libpq-dev \
mariadb-client \
unzip \
libzip-dev \
zip \
&& docker-php-ext-install \
pdo_mysql \
mysqli \
# rewriteモジュールを有効化
&& a2enmod rewrite \
&& docker-php-ext-enable mysqli \
# xdebug install
&& pecl install xdebug \
&& docker-php-ext-enable xdebug
# 指定したドメインでコンテナにルーティングされるように設定
# nginx-proxyに関連した設定
ENV VIRTUAL_HOST=test.example.com
# Composer Install
# 公式の Composer イメージを利用
COPY /usr/bin/composer /usr/bin/composer
# rootユーザー実行した際に警告が出ないようにする
ENV COMPOSER_ALLOW_SUPERUSER 1
# Composerのホームディレクトリを変更
ENV COMPOSER_HOME /composer
# コマンドが実行できるようにパスを通す
ENV PATH $PATH:/composer/vendor/bin
# Node.js Install
RUN apt-get install -y nodejs \
npm \
&& npm install n -g \
&& n latest
RUN composer global require "laravel/installer"
ここで指定したコマンドがdocker compose build
または初回実行時のdocker compose up
で実行されます。
ベースのイメージを指定
まずベースとなるイメージを指定します。bullseye(ブルズアイ)
は Debian 系の Linux ディストリビューションで構成されています。バージョンごとにコー ドネームが付けられており、Dcoker イメージのタグに使われています。
コードネーム | バージョン | 読み方 |
---|---|---|
bullseye | v11 | ブルズアイ |
buster | v10 | バスター |
stretch | v9 | ストレッチ |
jessie | v8 | ジェシー |
FROM php:8.1.9-apache-bullseye
このイメージではPHP 8.1.9
が起動します。
PHP の設定
php.ini
の設定を確認します。
[Date]
# タイムゾーンを日本に指定
date.timezone = "Asia/Tokyo"
[mbstring]
# デフォルトの言語を日本語に指定
mbstring.language = "Japanese"
# 内部エンコーディングを指定
mbstring.internal_encoding = "UTF-8"
# xdebugを使用するための設定
[xdebug]
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.client_host = host.docker.internal
xdebug.log = /tmp/xdebug.log
xdebug.client_port = 9013
xdebug.discover_client_host = 1
php.ini
には php の実行環境を設定します。
ここで内部エンコーディングの指定に関してですが、公式ドキュメントにはこのように記載されています。
mbstring.language string
mbstring で使用される言語設定(NLS)のデフォルト値。 この設定はmbstring.internal_encoding
を定義するため、php.ini
の中でmbstring.internal_encoding
は、mbstring.language
の後に置く必要があることに注意してください。
他の記事ではこの記述が逆になって記載しているものが多かったので注意してください。
mbstring.internal_encoding は非推奨
先程記述する順序について確認しましたが、mbstring.internal_encoding
の設定は現在非推奨になっています。
警告 この非推奨の機能は、きっと 将来 削除 されるでしょう。
内部文字エンコーディングのデフォルト値を定義します。
この値は空のままにしておいて、代わりに default_charset を設定すべきです。
php.ini の設定を変更しておきます。
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.language = "Japanese"
default_charset = "UTF-8"
[xdebug]
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.client_host = host.docker.internal
xdebug.log = /tmp/xdebug.log
xdebug.client_port = 9013
xdebug.discover_client_host = 1
Composer をインストール
Composer をインストールする記述を確認します。
# Composer Install
# 公式の Composer イメージを利用
COPY /usr/bin/composer /usr/bin/composer
# rootユーザー実行した際に警告が出ないようにする
ENV COMPOSER_ALLOW_SUPERUSER 1
# Composerのホームディレクトリを変更
ENV COMPOSER_HOME /composer
# コマンドが実行できるようにパスを通す
ENV PATH $PATH:/composer/vendor/bin
バージョンを指定する場合は--from=composer:1.x.x
のように指定します。今回は最新のバージョンを使用するためlatest
を指定しています。
環境変数の詳細は公式ドキュメントを参考にしてください。
Node.js をインストール
nodejs
とnpm
をインストールした後、細かくバージョンを指定できるようにnパッケージ
をインストールします。
# Node.js Install
RUN apt-get install -y nodejs \
npm \
&& npm install n -g \
&& n latest
# ※2022年10月21日現在では v19.0.0 がインストールされる
npm のバージョンは各環境に合わせて必要なバージョンを指定してください。
MySQL の設定
次に MySQL の設定を見ていきます。
services:
# 中略
# MySQLを動かすコンテナ
database:
# コンテナ名を指定
container_name: db-container
build: ./docker/mysql
volumes:
# ボリュームにマウントしデータを永続化する
- db-store:/var/lib/mysql
ports:
- 3306:3306
volumes:
volume の仕組みは前述したとおりです。設定している内容を確認します。
services:
# 中略
database:
# 中略
volumes:
# ボリュームにマウントしデータを永続化する
- db-store:/var/lib/mysql
Dockerfile の設定
ここでは環境変数の設定や、設定ファイルのコピーを実行する処理を記述しています。
必要であれば.env
ファイルで管理して下さい。
FROM mysql:latest
# コンテナ内の環境変数を指定。詳細はDockerHubを確認
ENV TZ=Asia/Tokyo \
MYSQL_DATABASE=docker-database \
MYSQL_USER=docker \
MYSQL_PASSWORD=docker \
MYSQL_ROOT_PASSWORD=rootpass
# 設定ファイルをコンテナにコピー
COPY ./my.cnf /etc/mysql/conf.d/my.cnf
COPY ./init/* /docker-entrypoint-initdb.d/
mysql:latest
使用するイメージの指定はmysql:5.7
のように:
の後にタグを指定することができます。DockerHub を見ればわかりますが、各種イメージにはタグが振られているのでそれ指定することで、任意のイメージを取得します。
特にバージョンを指定しない限りmysql:latest
のイメージを取得します。latest
とは最新版のイメージのことです。
latest 版を使用する場合の注意点
公開されているイメージの内容は日々更新されており、環境構築するタイミングでは 3 ヶ月前のlatest
イメージと、3 ヶ月後のlatest
のイメージでは内容が異なったり、何らかの不具合が発生したりすることがあります。
公式ページのベストプラクティスにもこう書かれています。
イメージをビルドする場合には、常にわかりやすいタグをつけるようにします 。 このタグを用いて、バージョン情報をコード化したり、目的とする用途(たとえば prod や test など)や安定性など、いろいろな情報を付与したりします。 こうしておけば、アプリケーションをさまざまな環境にデプロイする際にわかりやすくなります。 自動的に生成される latest タグには頼らないようにします。
必要に応じてバージョンを固定するようにしてください。
初回起動時に実行する SQL 文を指定
MySQL の Docker イメージでは、/docker-entrypoint-initdb.d/
配下に.sh
や.sql
などのスクリプトファイルを配置するとコンテナ起動時に実行させることが出来ます。
実行したい SQL 文を記述したファイルを作成して、
CREATE DATABASE IF NOT EXISTS sample_laravel
/docker-entrypoint-initdb.d/
配下にコピーする処理を記述しておきます。
COPY ./init/* /docker-entrypoint-initdb.d/
今回は、起動時に指定したデータベースが存在しなければ作成するというシンプルなsql
を実行させています。
my.conf
my.cnf ではサーバの設定を記述します。
[mysqld]
# デフォルトの文字セット
# この変数を設定する場合は、文字セットの照合順序を指定するように collation_server も設定する必要があります
character-set-server = utf8mb4
# サーバーのデフォルトの照合順序
collation-server = utf8mb4_unicode_ci
[client]
# クライアントから到達するステートメントの文字セット
default-character-set = utf8mb4
その他詳細は公式ドキュメントを参照して下さい。
phpMyAdmin の設定
次に、phpMyAdmin の設定を見ていきます。
services:
# 中略
# PHPMyadminを動かすコンテナ
phpmyadmin:
# コンテナ名を指定
container_name: phpmyadmin-container
build: ./docker/phpMyAdmin
ports:
- 8082:80
# 依存関係をMySQLに設定
depends_on:
- database
Dockerfile の設定
使用するイメージを指定して環境変数を設定するシンプルな内容となっています。
注意点として、PMA_HOSTS=database
は yml ファイルで指定したサービス名を指定するように注意してください。
FROM phpmyadmin/phpmyadmin:latest
ENV PMA_ARBITRARY=1 \
# ↓ymlのサービス名と合わせる
PMA_HOSTS=database \
PMA_USER=root \
PMA_PASSWORD=rootpass
環境変数
設定内容はDcokerHub の公式ページを参考にしました。
PMA_ARBITRARY=1
:1 に設定すると、任意のサーバーへの接続が許可されます。PMA_HOSTS=database
:接続するデータベースを指定します。PMA_USER=root
:ログインユーザー名を指定します。PMA_PASSWORD=root
:ユーザーのパスワードを指定します。
depends_on:
depends_on:
を指定することでコンテナ間の依存関係設定することが出来ます。
このように設定すると、db-container
→phpmyadmin-container
の順番に起動します。
# 依存関係をMySQLに設定
depends_on:
- database
その他詳細については、こちらの記事で詳しく解説されているので参考になると思います。
最後に
ここまでで各種コンテナの基本的な設定が完了しました。
次回ではリバースプロキシを導入してhttp://localhost:8080
ではなく、任意のドメインで開発環境にアクセスできるようにしていきます。