コンテナーを利用した PHP 開発
前提条件
PHP アプリケーションのコンテナー化 を完了していること。
概要
本節ではコンテナー化したアプリケーションに対する開発環境の構築方法を学びます。 ここでは以下を行います。
- ローカルデータベースを追加してデータを保存します。
- データベースとの処理のため phpMyAdmin を追加します。
- Compose の設定を通じて、コード編集および保存とともに、実行中の Compose サービスが自動的に更新されるようにします。
- dev 依存パッケージを含んだ開発用コンテナーを生成します。
ローカルデータベースの追加とデータ保存
コンテナーでは、ローカルサービスとしてたとえばデータベースを構築することができます。 サンプルアプリケーションにおいてそれを実現するためには、以下を行っていくことが必要です。
Dockerfileを修正して、データベース接続を行う拡張モジュールをインストールします。compose.yamlファイルを修正して、データベースサービスの追加、およびデータ保存のためのボリューム追加を行います。
拡張モジュールインストールのための Dockerfile 更新
PHP 拡張をインストールするには Dockerfile を修正する必要があります。
IDE またはテキストエディターを使って Dockerfile を開き、内容を修正します。
以下の Dockerfile では新たな行を挿入し、そこで pdo および pdo_mysql 拡張モジュールをインストールします。
コメントはすべて削除しています。
# syntax=docker/dockerfile:1
FROM composer:lts as deps
WORKDIR /app
RUN --mount=type=bind,source=composer.json,target=composer.json \
--mount=type=bind,source=composer.lock,target=composer.lock \
--mount=type=cache,target=/tmp/cache \
composer install --no-dev --no-interaction
FROM php:8.2-apache as final
RUN docker-php-ext-install pdo pdo_mysql
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY --from=deps app/vendor/ /var/www/html/vendor
COPY ./src /var/www/html
USER www-dataPHP 拡張モジュールのインストールについては PHP 向け公式 Docker イメージ を参照してください。
DB およびデータ追加のための compose.yaml ファイル更新
IDE またはテキストエディターを使って compose.yaml ファイルを開きます。
中を見てみれば分かるように、PostgreSQL データベースとボリュームに関する命令が、コメントアウトされて既に記述されています。
このアプリケーションでは MariaDB を用いることにしています。
MariaDB に関する詳細は MariaDB 公式 Docker イメージ を参照してください。
IDE またはテキストエディターを使って src/database.php ファイルを開きます。
これを見れば、データベース接続を行うために環境変数を読み込んでいることが分かります。
compose.yaml ファイルでは以下の修正を行います。
- MariaDB 用のデータベース命令のコメントをはずします。
- データベースパスワードを受け渡すため、サーバーサービスに secret を加えます。
- サーバーサービスにデータベース接続のための環境変数を加えます。
- データ保存を行うためにボリューム命令のコメントをはずします。
以下が修正後の compose.yaml ファイルです。
コメントはすべて削除しています。
services:
server:
build:
context: .
ports:
- 9000:80
depends_on:
db:
condition: service_healthy
secrets:
- db-password
environment:
- PASSWORD_FILE_PATH=/run/secrets/db-password
- DB_HOST=db
- DB_NAME=example
- DB_USER=root
db:
image: mariadb
restart: always
user: root
secrets:
- db-password
volumes:
- db-data:/var/lib/mysql
environment:
- MARIADB_ROOT_PASSWORD_FILE=/run/secrets/db-password
- MARIADB_DATABASE=example
expose:
- 3306
healthcheck:
test:
[
"CMD",
"/usr/local/bin/healthcheck.sh",
"--su-mysql",
"--connect",
"--innodb_initialized",
]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:
secrets:
db-password:
file: db/password.txtメモCompose ファイル内の命令についての詳細は Compose ファイルリファレンス を参照してください。
Compose を使ったこのアプリケーションを実行する前に確認しておきますが、この Compose ファイルは secrets を用いており、データベースパスワードを保持した password.txt ファイルを指定しています。
このファイルはソースリポジトリには存在していないため、各自で生成してください。
docker-php-sample ディレクトリに db という名前の新たなディレクトリを生成します。
そしてそのディレクトリ内に password.txt という名前のファイルを生成します。
IDE またはテキストエディターを使って password.txt を開き、以下のパスワードを入力します。
パスワードは 1 行内に収める必要があり、余計な行を加えてはなりません。
examplepassword.txt ファイルを保存して閉じます。
ここまでに docker-php-sample ディレクトリは以下のようになります。
├── docker-php-sample/
│ ├── .git/
│ ├── db/
│ │ └── password.txt
│ ├── src/
│ ├── tests/
│ ├── .dockerignore
│ ├── .gitignore
│ ├── compose.yaml
│ ├── composer.json
│ ├── composer.lock
│ ├── Dockerfile
│ ├── README.Docker.md
│ └── README.md以下のコマンドを実行してアプリケーションを起動します。
$ docker compose up --build
ブラウザーを開いて http://localhost:9000/database.php にアクセスし、アプリケーションを確認します。 シンプルなウェブアプリケーションにテキストが表示され、また表示更新のたびに加算されるカウンターが表示されたはずです。
端末画面から ctrl+c を押下してアプリケーションを停止します。
データベース内のデータ確認
端末画面から docker compose rm コマンドを実行してコンテナーを削除します。
もう一度 docker compose up を実行すればアプリケーションを再起動することができます。
$ docker compose rm
$ docker compose up --build
http://localhost:9000/database.php にアクセスしているブラウザーを更新してみると、以前のカウンターがそのまま表示されることが分かります。 ボリュームが存在してなかったら、コンテナーを削除した後はデータベースデータが残っていないはずでした。
端末画面から ctrl+c を押下してアプリケーションを停止します。
データベース制御のための phpMyAdmin 追加
compose.yaml を書き換えるだけで、サービスをアプリケーションスタックに加えることが簡単にできます。
compose.yaml を修正して phpMyAdmin 用のサービスを新たに追加します。
詳しくは phpMyAdmin 公式 Docker イメージ を参照してください。
修正した compose.yaml ファイルは以下のとおりです。
services:
server:
build:
context: .
ports:
- 9000:80
depends_on:
db:
condition: service_healthy
secrets:
- db-password
environment:
- PASSWORD_FILE_PATH=/run/secrets/db-password
- DB_HOST=db
- DB_NAME=example
- DB_USER=root
db:
image: mariadb
restart: always
user: root
secrets:
- db-password
volumes:
- db-data:/var/lib/mysql
environment:
- MARIADB_ROOT_PASSWORD_FILE=/run/secrets/db-password
- MARIADB_DATABASE=example
expose:
- 3306
healthcheck:
test:
[
"CMD",
"/usr/local/bin/healthcheck.sh",
"--su-mysql",
"--connect",
"--innodb_initialized",
]
interval: 10s
timeout: 5s
retries: 5
phpmyadmin:
image: phpmyadmin
ports:
- 8080:80
depends_on:
- db
environment:
- PMA_HOST=db
volumes:
db-data:
secrets:
db-password:
file: db/password.txt端末画面から docker compose up を実行してアプリケーションを起動します。
$ docker compose up --build
ブラウザーから http://localhost:8080 を開いて phpMyAdmin にアクセスします。
ユーザー名に root、パスワードに example を入力してログインします。
phpMyAdmin を通じてデータベースの制御ができるようになりました。
端末画面から ctrl+c を押下してアプリケーションを停止します。
サービスの自動更新
Compose Watch を利用すると、自分が作成して実行している Compose サービスを自動的に更新できるようになります。 Compose Watch に関する詳細は Use Compose Watch を参照してください。
IDE またはテキストエディターを使って compose.yaml ファイルを開きます。
そして Compose Watch 命令を追加します。
以下は修正した compose.yaml ファイルです。
services:
server:
build:
context: .
ports:
- 9000:80
depends_on:
db:
condition: service_healthy
secrets:
- db-password
environment:
- PASSWORD_FILE_PATH=/run/secrets/db-password
- DB_HOST=db
- DB_NAME=example
- DB_USER=root
develop:
watch:
- action: sync
path: ./src
target: /var/www/html
db:
image: mariadb
restart: always
user: root
secrets:
- db-password
volumes:
- db-data:/var/lib/mysql
environment:
- MARIADB_ROOT_PASSWORD_FILE=/run/secrets/db-password
- MARIADB_DATABASE=example
expose:
- 3306
healthcheck:
test:
[
"CMD",
"/usr/local/bin/healthcheck.sh",
"--su-mysql",
"--connect",
"--innodb_initialized",
]
interval: 10s
timeout: 5s
retries: 5
phpmyadmin:
image: phpmyadmin
ports:
- 8080:80
depends_on:
- db
environment:
- PMA_HOST=db
volumes:
db-data:
secrets:
db-password:
file: db/password.txt以下のコマンドを実行して Compose Watch を利用したアプリケーションを起動します。
$ docker compose watch
ブラウザーを開いて http://localhost:9000/hello.php にアクセスし、アプリケーションが動作していることを確認します。
ローカルマシン上にあるアプリケーションのソースコードを変更したら、その内容は実行中のコンテナーに即座に反映されます。
IDE またはテキストエディターを使って hello.php を開きます。
Hello, world! の文字列を Hello, Docker! に変更します。
hello.php への変更を保存します。
しばらく待つとアプリケーションへの同期が行われます。
http://localhost:9000/hello.php にアクセスしているブラウザーを更新してみると、修正した文字列が確認できます。
端末画面から ctrl+c を押下して Compose Watch を停止します。
そして docker compose down を実行してアプリケーションを停止します。
開発用コンテナーの生成
ここまでは、コンテナー化したアプリケーションの実行時に Compose は開発依存パッケージはインストールしていません。
このイメージは本番環境向けとしては非常に小さくできています。
しかし開発作業を行う際に必要となるツールや依存パッケージは含まれておらず、tests ディレクトリもありません。
そこで同じ Dockerfile 内に開発用と本番用という双方向けのステージをビルドするマルチステージビルドを用いることにします。
詳しくは マルチステージビルド を参照してください。
Dockerfile を以下のように修正します。
depsステージを 2 つのステージに分けます。 1 つは本番環境用 (prod-deps) であり、もう一つは開発依存パッケージ類をインストールするステージ (dev-deps) です。- 共通の
baseステージを作ります。 - 開発用として新たに
developmentステージを作ります。 finalステージを修正して、prod-depsステージから依存パッケージをコピーします。
以下に Dockerfile の編集前と編集後を示します。
# syntax=docker/dockerfile:1
FROM composer:lts as deps
WORKDIR /app
RUN --mount=type=bind,source=composer.json,target=composer.json \
--mount=type=bind,source=composer.lock,target=composer.lock \
--mount=type=cache,target=/tmp/cache \
composer install --no-dev --no-interaction
FROM php:8.2-apache as final
RUN docker-php-ext-install pdo pdo_mysql
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY --from=deps app/vendor/ /var/www/html/vendor
COPY ./src /var/www/html
USER www-data# syntax=docker/dockerfile:1
FROM composer:lts as prod-deps
WORKDIR /app
RUN --mount=type=bind,source=./composer.json,target=composer.json \
--mount=type=bind,source=./composer.lock,target=composer.lock \
--mount=type=cache,target=/tmp/cache \
composer install --no-dev --no-interaction
FROM composer:lts as dev-deps
WORKDIR /app
RUN --mount=type=bind,source=./composer.json,target=composer.json \
--mount=type=bind,source=./composer.lock,target=composer.lock \
--mount=type=cache,target=/tmp/cache \
composer install --no-interaction
FROM php:8.2-apache as base
RUN docker-php-ext-install pdo pdo_mysql
COPY ./src /var/www/html
FROM base as development
COPY ./tests /var/www/html/tests
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
COPY --from=dev-deps app/vendor/ /var/www/html/vendor
FROM base as final
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY --from=prod-deps app/vendor/ /var/www/html/vendor
USER www-datacompose.yaml ファイルに開発ステージをターゲットとする命令を加えます。
以下は compose.yaml ファイルの更新した一部分です。
services:
server:
build:
context: .
target: development
# ...コンテナー化アプリケーションは、このようにして開発依存パッケージをインストールするようになります。
以下のコマンドを実行してアプリケーションを起動します。
$ docker compose up --build
ブラウザーを開いて http://localhost:9000/hello.php にアクセスし、アプリケーションを確認します。 "Hello, Docker!" アプリケーションが今回も表示されます。
端末画面から ctrl+c を押下してアプリケーションを停止します。
アプリケーションの様子は同じであっても、開発依存パッケージを利用する形を作り出しました。 続けて次の節では Docker を使ったテスト実行方法について学びます。
まとめ
この節では Compose ファイルに対してローカルデータベースとそのデータ保存についての設定を見てきました。 またソースコードの更新とともにアプリケーションの自動同期を行う Compose Watch の利用方法についても学びました。 そして開発環境向けに必要となる依存パッケージを含んだ開発コンテナーを生成する方法について学びました。
関連情報
次のステップ
次の節では Docker を使ったユニットテストの実行方法について学びます。