PHP イメージをバージョンアップ

Docker Hub > Official images / php のイメージをバージョンアップするときの確認事項をまとめます。

例として、Dockerfile の FROM を次のように変更するケースを考えます。PHP のバージョン(8.2 → 8.3)と、ベースの OS である Debian のバージョン(11 → 12)が同時に上がります。

- FROM php:8.2-fpm-bullseye
+ FROM php:8.3-fpm-bookworm
コードネーム バージョン リリース日
bullseye Debian 11 2021年8月14日
bookworm Debian 12 2023年6月10日

バージョンアップする理由

  • Debian 11(bullseye)は LTS も含めてサポートが終了しています(2026年8月31日)
  • php:8.3-fpm-bullseye タグは 2025年8月以降更新されておらず、セキュリティ修正が入りません。8.3 に上げるなら bookworm を使います

確認の範囲

ここで扱うのは、パッケージが見つからない、拡張モジュールのコンパイルに失敗するといったインフラ面の互換性だけです。PHP のバージョンアップによるアプリケーションコードの互換性(非推奨になった関数など)は扱いません。

docker build が成功しても、すべてが確認できたわけではありません。インストール方法ごとに、ビルドで分かることと、別に確認が必要なことは次のとおりです。

インストール方法 ビルドの成功で分かること 別に確認が必要なこと
APT(apt-get install) パッケージが見つかり、エラーなくインストールできた 入ったバージョンが想定どおりか
PHP 拡張モジュール(docker-php-ext-install / pecl install) コンパイルが通った PHP の起動時に読み込めるか、php-fpm の設定が正しいか
その他(curl などで直接入れたもの) コマンドがエラーで終わらなかった 正しいファイルが入り、動くか

以降のコマンド例の <イメージ名> は、確認したいイメージの名前に置き換えてください。

APT パッケージ

ビルドの成功で分かること

APT のパッケージは Debian がビルド済みのバイナリ(.deb)なので、インストール時にコンパイルはしません。ビルドが成功すれば、次の処理がすべてエラーなく終わったことが分かります。

  1. ダウンロード
  2. 依存関係の解決
  3. 展開
  4. パッケージ付属のセットアップスクリプトの実行

OS のバージョンアップでパッケージ名がなくなったり変わったりした場合は、apt-get install が失敗するので、ビルドの時点で気づけます。

公式リポジトリのパッケージは、そのリリース向けに依存関係込みで用意されています。そのため「入ったのに動かない」ことはまず起きません。

ビルドでは分からないこと

パッケージ名が同じでも、中身のバージョンは OS ごとに変わります。 ビルドは通るので気づきにくい点です。

パッケージ bullseye bookworm
default-mysql-client MariaDB 10.5 のクライアント MariaDB 10.11 のクライアント
libicu-dev(PHP の intl が使う ICU) ICU 67 ICU 72

default-mysql-client は、名前に反して MySQL ではなく MariaDB のクライアントを入れます。

確認したい場合は、コンテナを起動してバージョンを表示します。

docker run --rm <イメージ名> mysql --version

なお、zlib1g-dev や libicu-dev などの -dev パッケージは、PHP 拡張をコンパイルするための部品です。PHP 拡張のコンパイルが通れば、これらが正しく入ったことも確認できます。

PHP 拡張モジュール(extension)

ビルドの成功で分かること

docker-php-ext-install や pecl install は、イメージの中でソースコードから拡張をコンパイルします。途中の make が失敗すると終了コードが 0 以外になり、ビルドが止まります。

ビルドが成功すれば、拡張がそのイメージの PHP に対してコンパイルできたことが分かります。PHP のバージョンを上げたときに最も壊れやすいのはここなので、ビルドが通ること自体が大きな確認になります。

ビルドでは分からないこと

拡張モジュールを読み込めるか

コンパイルが通っても、PHP の起動時に拡張の .so を読み込めないことがあります(依存ライブラリが足りない、など)。

php -m で確認できますが、読み込みに失敗しても php -m は Warning を出すだけで、終了コードは 0 です。そのため、出力に Warning が含まれていないかを grep で確認します。

output=$(docker run --rm <イメージ名> php -m 2>&1)
echo "${output}"
if echo "${output}" | grep -E 'PHP Warning|PHP Fatal error|Unable to load'; then
  echo "PHP extension failed to load"
  exit 1
fi

この方法では、Dockerfile や php.ini から拡張の記述そのものを消してしまった場合は検出できません。

php-fpm の設定が正しいか

php-fpm -t は php-fpm の設定ファイル(php-fpm.conf と php-fpm.d/*.conf)を読み込んで検証し、そのまま終了します。設定に誤りがあれば、終了コードが 0 以外になります。

docker run --rm <イメージ名> php-fpm -t

php-fpm -t は拡張モジュールの読み込みに失敗しても成功を返します。拡張の確認は php -m で行ってください。

その他(curl などで直接入れたもの)

curl などで直接ダウンロードしてインストールしたものは、ビルドが成功しても正しく入ったとは限りません。Docker のビルドで分かるのは「コマンドがエラーで終わらなかった」ことだけで、ダウンロードしたファイルの中身が正しいかや、実際に動くかまでは確認しないからです。

特に注意が必要なのは次の 2 つです。

  • curl は -f を付けないと、404 などのエラーページが返ってきても成功扱い(終了コード 0)になります。 壊れたファイルを入れたままビルドが通ることがあります
  • RUN で a | b のようにパイプでつなぐと、a が失敗しても b が成功すればビルドは通ります。 RUN は /bin/sh -c で実行され、pipefail が効かないためです

curl などで入れたものは、コンテナを起動してコマンドを実行し、動作を確認してください。

docker run --rm <イメージ名> composer --version

参考