0Pricing
PHP Academy · レッスン

PHPアプリケーションのコンテナ化

本番環境向けのPHP Dockerfileを作成します。

「PHPアプリケーションのコンテナ化」はCoddyKit上の無料PHP Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPHP Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 PHP Academyコースには全4レッスンが含まれています。

PHPをコンテナ化する理由

PHPを再現性のある形でデプロイするには、コードとともに正確なインタープリターのバージョン、拡張機能、OSライブラリを固定する必要があります。Dockerイメージを使えば、ノートPC、CI、本番環境のすべてで同じphp -vと同じext-*のセットを使用できます。

このレッスンでは、本番環境で使用できるイメージを構築します。PHP-FPM、必要な拡張機能だけ、調整済みの設定、非rootユーザー、ヘルスチェックを含めます。

FPMとApacheのベースイメージ

公式のPHPイメージには複数の種類があります。nginx/traefikの背後で動かす本番Webアプリケーションには、php:8.3-fpm-alpine(小容量)またはphp:8.3-fpm(Debian、glibcを使用し、ネイティブライブラリで問題が起きにくい)を推奨します。

  • cli — ワーカー、キュー、cron
  • fpm — FastCGIプロセスマネージャー。nginxと組み合わせます
  • apache — Apacheを内蔵。便利ですが、より重くなります

マイナーバージョンを固定してください。本番環境では決して:latestを使用しないでください。

# Base image choice in your Dockerfile
FROM php:8.3-fpm-alpine AS base

# Why alpine? ~30MB base vs ~140MB Debian.
# Tradeoff: musl libc, occasional native-extension friction.

拡張機能をインストールする

これらのイメージ内でapt install php-xxxを実行してはいけません。組み込みのヘルパーであるdocker-php-ext-install、docker-php-ext-configure、peclを使用してください。install-php-extensionsスクリプト(mlocati)は、必要な開発用ヘッダーを自動的に取得してくれる、事実上のショートカットです。

FROM php:8.3-fpm-alpine

# Grab the helper that resolves build deps automatically
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/

RUN chmod +x /usr/local/bin/install-php-extensions && \
    install-php-extensions \
        pdo_mysql \
        opcache \
        intl \
        zip \
        redis \
        bcmath

イメージ内のComposer

インストーラーをcurlするのではなく、公式イメージからComposerのバイナリをコピーしてください。本番環境では--no-devと--optimize-autoloaderを付けてcomposer installを実行します。また、ソースの変更とは独立して依存関係のレイヤーをキャッシュできるよう、最初にcomposer.json/composer.lockだけをコピーしてください。

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /app

# Cache-friendly: deps layer invalidates only when lock changes
COPY composer.json composer.lock ./
RUN composer install \
        --no-dev \
        --no-scripts \
        --no-autoloader \
        --prefer-dist

COPY . .
RUN composer dump-autoload --optimize --classmap-authoritative

php.iniを調整する

ベースイメージにはphp.ini-productionとphp.ini-developmentのテンプレートが含まれています。本番用のテンプレートを有効にしてから、独自の上書き設定をconf.dに配置してください。このディレクトリは最後にマージされるため、設定が優先されます。

本番環境で重要な値は、opcache.enable=1、opcache.validate_timestamps=0(イメージ内のコードが不変であるため)、適切なmemory_limitです。

# Activate production ini
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

# Custom overrides win because conf.d loads last
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/zz-app.ini

OPcacheの上書きファイル

これは本番環境で最も大きな効果をもたらす設定です。validate_timestamps=0にすると、PHPはリクエストごとにファイルの状態を確認しません。ただし、変更をデプロイするにはイメージを必ず再ビルドする必要があります。これは、不変コンテナにとってまさに望ましい動作です。

; docker/php/zz-app.ini
memory_limit = 256M
expose_php = Off

opcache.enable = 1
opcache.enable_cli = 0
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0
opcache.preload = /app/preload.php
opcache.preload_user = www-data

非rootで実行する

このイメージにはすでにwww-dataが定義されています。FPMをrootで実行すると、攻撃対象領域が不必要に広がります。書き込み可能なパス(キャッシュ、ログ)の所有権を設定し、CMDの前にUSERでユーザーを切り替えてください。

FPMのマスタープロセスは特権ポートで待ち受ける必要があるでしょうか。いいえ。FPMは9000番ポート(非特権ポート)で待ち受けるため、非rootで簡単に実行できます。

# Make runtime-writable dirs owned by the runtime user
RUN chown -R www-data:www-data /app/var /app/storage 2>/dev/null || true

USER www-data

EXPOSE 9000
CMD ["php-fpm"]

ヘルスチェック

オーケストレーターには、プロセスが存在するだけでなく、FPMが実際に稼働していることを示すシグナルが必要です。cgi-fcgiを使うと、FPMの/statusまたは/pingエンドポイントにpingを送信できます。まずFPMのプールでpm.status_pathとping.pathを有効にしてください。

# In www.conf pool config:
;   ping.path = /ping
;   ping.response = pong

# Dockerfile HEALTHCHECK using cgi-fcgi
RUN install-php-extensions @composer >/dev/null 2>&1 || true

HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
  CMD SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET \
      cgi-fcgi -bind -connect 127.0.0.1:9000 || exit 1

Dockerfileを組み立てる

ここでは、一貫性のある単一ステージの本番用Dockerfileを示します。次のレッスンでは、ビルドツールを取り除くためにマルチステージに分割します。順序に注目してください。依存関係 → 設定 → ソース → オートロード → ユーザー切り替え。

FROM php:8.3-fpm-alpine

ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
    install-php-extensions pdo_mysql opcache intl zip redis

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /app

RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/

COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
COPY . .
RUN composer dump-autoload --optimize --classmap-authoritative && \
    chown -R www-data:www-data /app/var

USER www-data
EXPOSE 9000
CMD ["php-fpm"]

ビルドを検証する

ビルド後は、実際にイメージに含まれたものを簡単に確認します。PHPのバージョン、読み込まれた拡張機能、そしてOPcacheの検証が無効になっていることを確認します。短いCLIスクリプトで、アプリが依存する実行環境の契約を確認できます。

<?php
// Run inside the container: php verify.php
echo 'PHP ' . PHP_VERSION . PHP_EOL;

$required = ['pdo_mysql', 'opcache', 'intl', 'zip'];
foreach ($required as $ext) {
    printf("%-12s %s\n", $ext, extension_loaded($ext) ? 'OK' : 'MISSING');
}

var_dump((bool) ini_get('opcache.enable'));
?>

ビルドコンテキストを整理する

.dockerignoreを使うとビルドコンテキストを小さく保ち、シークレットやvendorの肥大化がイメージに入り込んだり、キャッシュを無効化したりするのを防げます。vendor、VCS、envファイル、ローカル用ツールを除外してください。

# .dockerignore
.git
.gitignore
vendor/
node_modules/
.env
.env.*
tests/
*.md
docker-compose*.yml
storage/logs/*
var/cache/*

確認

本番用イメージでopcache.validate_timestamps=0を設定するのはなぜですか?

まとめ

本番用のPHP-FPMイメージを構築しました。8.3-fpm-alpineベースのバージョンを固定し、インストーラースクリプトで必要な拡張機能だけをインストールし、Composerとキャッシュ済みの依存関係をそれぞれ専用レイヤーにコピーし、OPcacheのオーバーライドを含む本番用php.iniを有効にし、www-dataに切り替え、FPMのヘルスチェックを追加しました。

重要な習慣: バージョンを固定する、依存関係のレイヤーをキャッシュする、非rootユーザーで実行する、タイムスタンプ検証を無効にする、そして.dockerignoreでビルドコンテキストをスリムに保つことです。

よくある質問

「PHPアプリケーションのコンテナ化」レッスンは無料ですか?

はい。「PHPアプリケーションのコンテナ化」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、PHP Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 PHP Academyコースには全4レッスンが含まれています。

「PHPアプリケーションのコンテナ化」で何を学びますか?

本番環境向けのPHP Dockerfileを作成します。 ブラウザで直接実行するハンズオンコードでPHP Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

PHP Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPHP Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「PHPアプリケーションのコンテナ化」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPHP Academyレッスンでコードを書いて実行できますか?

はい。すべてのPHP Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. PHPアプリケーションのコンテナ化
  2. マルチステージビルドと最適化
  3. ローカル環境向けDocker Compose
  4. GitHub ActionsによるCI/CD
← PHP Academyに戻る