🐳

PHP 開発用の Docker コンテナー

2023/02/26に公開

devcon-php

PHP アプリの開発をするにあたって、環境を用意するのがそこそこ面倒なので、Docker コンテナーで用意しています。そこで、PHP 開発用の Docker コンテナーを手軽に用意できるテンプレートを https://github.com/hiro345g/devcon-php に用意しました。

README.md に、ほぼ同じことを書いてありますが、こちらに紹介記事として公開しておきます。

これは Docker Hub の Official Image をベースとする PHP 用の開発環境を Dev Container 環境として用意したものです。

PHP は phpphp:8.1-apache、DB サーバーは mysqlmysql:8.0.32-debian を使っています。
また、DB サーバーのデータ操作用に admineradminer:4.8.1-standalone も使えるようにしています。

開発するアプリは devcon-php コンテナーの /var/www/html (つまり、devcon-php:/var/www/html)へ置くことを想定しています。
アプリのソースコードの永続化は Docker ボリュームを使う想定にしてあります。コンテナー内で開発をするのでホスト側とバインドマウントで共有化する必要がないからです。また、Docker が推奨していることからもわかるように、そうしておいた方が Windows、macOS、Linux のファイルシステムの差を考慮する必要がなくなり管理が楽になるからです。

必要なもの

devcon-php を動作をさせるには、Docker、Docker Compose、Visual Studio Code (VS Code) 、Dev Containers 拡張機能が必要です。

Docker

これらは Docker Desktop をインストールしてあれば使えます。
Linux では Docker Desktop をインストールしなくても Docker Engine と Docker Compose だけをインストールして使えます。
例えば、Ubuntu を使っているなら Install Docker Engine on Ubuntu を参照してインストールしておいてください。

Visual Studio Code

VS Code の拡張機能である Dev Containers を VS Code へインストールしておく必要があります。

動作確認済みの環境

次の環境で動作確認をしてあります。Windows や macOS でも動作するはずです。

$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.1 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

$ docker version
Client: Docker Engine - Community
 Cloud integration: v1.0.29
 Version:           23.0.1
 API version:       1.42
 Go version:        go1.19.5
 Git commit:        a5ee5b1
 Built:             Thu Feb  9 19:47:01 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          23.0.1
  API version:      1.42 (minimum version 1.12)
  Go version:       go1.19.5
  Git commit:       bc3805a
  Built:            Thu Feb  9 19:47:01 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.18
  GitCommit:        2456e983eb9e37e47538f59ea18f2043c9a73640
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

$ docker compose version
Docker Compose version v2.15.1

ファイルの構成

ファイルの構成は次のようになっています。

devcon-php/
├── .devcontainer/ ... Dev Container 用のディレクトリー
│   └── devcontainer.json
├── README.md ... このファイル
├── build/ ... カスタム Docker イメージのビルド用
│   ├── Dockerfile
│   ├── docker-compose.yml
│   └── sample.env
├── docker-compose.yml ... Dev Container 用 docker-compose.yml
├── sample.env ... Dev Container 用 docker-compose.yml 用 env ファイル
└── workspace/
    ├── share/ ... Dev Container へコピーするファイルを置くためのディレクトリー
    │   ├── htdocs/
    │   │   └── index.php
    │   └── html.code-workspace
    └── usr_local_etc_php/
        └── php.ini ... Dev Container からバインドマウントする php.ini

この後、リポジトリをクローンもしくはアーカイブファイルを展開した devcon-php ディレクトリーのパスを ${REPO_DIR} と表現します。

使用する PHP のバージョンについて

使用する PHP のバージョンについて、切り替えができるように次のタグを用意してあります。

  • php81-mysql80
  • php74-mysql57

そのため、使用する PHP のバージョンを切り替えたい場合は、リポジトリをクローンして、タグを指定してチェックアウトしてください。

少し古い PHP アプリの開発をするときは、PHP 7.4 + MySQL 5.7 にも対応する php74-mysql57のタグを使います。
もとの PHP 8.1 + MySQL 8.0 にするには php81-mysql80 のタグを使います。

使い方

起動の仕方は、次のどちらかを想定しています。

  • Dev Container として開かずに通常のコンテナーとして起動
  • Dev Container として起動

起動したら、devcon-php:/var/www/ ディレクトリーにワークスペースファイル、devcon-php:/var/www/html/ ディレクトリーに PHP ファイルをおいて利用することを想定しています。

慣れないうちは通常のコンテナーとして起動して使ってください。
慣れてきて、PHP の開発専用で使うようになったら Dev Container として起動して使うのが良いです。

通常のコンテナーとして起動

先に「ビルド」を参照して Docker イメージを作成してください。
ビルド時とは別に docker-compose.yml ファイル用の「環境変数」を .env ファイルで指定できます。
必要なら「環境変数」を参考にして .env ファイルを用意してください。

それから、docker-compose.yml を使って devcon-php コンテナーを起動します。

cd ${REPO_DIR}
docker compose up -d

VS Code の Docker 拡張機能画面で devcon-php コンテナーのコンテキストメニューで Attach Visual Studio Code を選択して、アタッチします。
すると devcon-php コンテナー用の VS Code の画面が開いて使えるようになります。

Dev Container として起動

先に「ビルド」を参照して Docker イメージを作成してください。
ビルド時とは別に docker-compose.yml ファイル用の「環境変数」を .env ファイルで指定できます。
必要なら「環境変数」を参考にして .env ファイルを用意してください。

それから、F1 キーを入力して VS Code のコマンドパレットを表示してから、「Dev Containers: Open Folder in Container...」をクリックします。
フォルダーを選択する画面になるので ${REPO_DIR} を指定して開きます。
すると ${REPO_DIR}/.devcontainer/devcontainer.json の指定にしたがって、devcon-php コンテナーが Dev Container として起動します。
このとき、拡張機能なども追加されます。
それから、devcon-php コンテナー用の VS Code の画面となります。

つまり、開いている VS Code の画面が、そのまま devcon-php コンテナー用の VS Code の画面として開き直されます。
devcon-php コンテナーでは Docker ホストのファイルを間違えて操作しないように、${REPO_DIR} は見えないようにしてあります。
慣れないうちは、${REPO_DIR} が見える VS Code の画面もあった方がわかりやすいと思います。
こちらは、慣れてから使うようにすると良いでしょう。

コンテナー内に開発で使うファイルを用意

次に、コンテナー内に開発で使うファイルを用意します。
${REPO_DIR}/workspace/share 内に使うファイルを用意すると、コンテナー内では devcon-php:/workspace/share/ 内のファイルとして見えるようになります。

ここでは、サンプルとして devcon-php:/workspace/share/sample を用意してあるので、それを使います。
devcon-php コンテナーの VS Code のターミナルを使う場合は、次のようにファイルをコピーします。

www-data@devcon-php:~$ cd /var/www
www-data@devcon-php:~$ cp /workspace/share/sample/html.code-workspace .
www-data@devcon-php:~$ cp /workspace/share/sample/htdocs/index.php html/

/var/www/html.code-workspace は VS Code のワークスペースファイルです。
これを開いて、PHP プログラムの開発ができます。

www-data@devcon-php:~$ code /var/www/html.code-workspace

ワークスペースでは VS Code の「実行とデバッグ」画面で下記の3つのデバッグ構成が使えるようにしてあります。

  • Listen for Xdebug
  • Launch currently open script
  • Launch Built-in web server

動作しない場合は ${REPO_DIR}/workspace/user_local_etc_php/php.inixdebug.client_host を見直してください。

Listen for Xdebug

Listen for Xdebug を使う場合は、PHP のソースコードの /var/www/html/index.php にブレイクポイントを設定してから、http://localhost:8080/ へアクセスすると、ブレイクポイントでプログラムが止まります。
Web ブラウザでも curl コマンドでも動作します。

curl コマンドを使う場合は、コンテナー内であれば下記のようにします。

curl http://localhost:8080/

Docker ホストであれば下記のようにします。

curl http://127.0.0.1:8080/

Launch currently open script

Launch currently open script を使うと、エディタで開いている PHP ファイルを対象として、ターミナルで php コマンドがデバッグモードで実行されます。

Launch Built-in web server

Launch Built-in web server を使うと php -S 0.0.0.0:10080 を実行して、PHP ビルトインの Web サーバーを使ってデバッグすることができます。

コンテナー内、Docker ホストで下記でアクセスできます。

curl http://localhost:10080/

localhost でうまく動作しない場合は 127.0.0.1 を使います。
127.0.0.1 ではなく、devcon-php コンテナーをインスペクトすることでわかるコンテナーの IP か ゲートウェイの IP を指定することもできます。

php.ini

${REPO_DIR}/workspace/usr_local_etc_php/php.ini[xdebug] の設定をしてあります。コメントに書いてある通り、デバッガがうまく動作しない場合は、xdebug.client_host の指定を調整する必要があります。

[xdebug]
; デバッガクライアント(VS Code のデバッガ)が動作するホスト。
; 動かない場合は 127.0.0.1 も試してみると良いかもしれません。
; Docker ホストの VS Code を使う場合は host.docker.internal を指定。
; Linux では host.docker.internal は Docker ホストの /etc/hosts へ Docker ホストの IP アドレスを登録しておく必要がある。
xdebug.client_host = localhost
;xdebug.client_host = host.docker.internal
;xdebug.client_host = 127.0.0.1
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.discover_client_host = 0
xdebug.remote_handler = "dbgp"
; デバッガクライアント(VS Code のデバッガ)が待機するポート番号。
; `html.code-workspace` での `"port": 9003` はこれに合わせている。
xdebug.client_port = 9003

データベースサーバー関連

MySQL はポート番号 13306 で Dokcer ホストから接続できるようにしてあります。
Adminer はポート番号 5080 で Dokcer ホストから接続できるようにしてあり、http://localhost:5080 で利用できます。

使用している Docker ボリューム

下記の Docker ボリュームを自動で作成して利用するようになっています。

  • devcon-php-data ... devcon-php:/var/www 用のボリューム
  • devcon-php-vscode-server-extensions ... VS Code の拡張機能のダウンロードしたものを保持するためのボリューム
  • devcon-php-mysql-data ... MySQL データベース用のボリューム

ビルド

最初にビルドが必要です。
Dev Container 環境を起動する度に自動でビルドを実行する必要はないので、ビルド作業を別にしてあります。
実行時用のものと似たような docker-compose.yml を用意することになりますが、こうしておいた方が Docker イメージのタグ名指定が設定ファイルで明示的にわかるようになります。また、意図しない更新も入りにくくなり、利用時に安定します。

なお、macOS を Docker ホストとする場合など、ユーザーの UID と GID を調整したい場合があるでしょう。
.env で指定できるようにしてあります。
sample.env を参考にして .env を作成してからビルドしてください。

ビルドは次のように実行します。

cd ${REPO_DIR}
docker compose -f build/docker-compose.yml build --no-cache

ビルドが成功すると devcon-php-build コンテナーが起動します。次のようにして削除します。

docker compose -f build/docker-compose.yml down

環境変数

.env ファイルを用意すると docker-compose.yml 内の ${変数名} で指定されているものを、.env で指定したものへ変更できます。
具体的な指定方法は sample.env ファイルを参考にしてください。
特にポート番号の衝突を避ける必要がある場合に利用してください。

Listen for Xdebug で使うポート番号は PHP_PORT、Launch Built-in web server で使うポート番号は PHP_BUILT_IN_PORT で変更可能です。
これらを変更した場合は、${REPO_DIR}/workspace/share/html.code-workspace の対応する port: の変更も必要です。

MYSQL_ で始まるものは devcon-php-mysql サービス用です。MySQL が使うポート番号は MYSQL_PORT で指定できます。

ADMINER_PORT は devcon-php-adminer サービス用で、Adminer が使うポート番号を指定できます。

Discussion