Docker で Apache + PHP コンテナを作る方法

この記事は最終更新日から 1年以上 が経過しています。

Docker で開発環境を作るのって結構大変です。 構成を気軽に組み替えたりできるため自由度が高いですが、その分必要になる知識も多いですし、必要な作業も多いです。 まずは、XAMPP でおなじみの Apache と PHP を組み合わせた Web サーバーを作るところから始めてみましょう。

Docker で Apache + PHP コンテナを作る

コンテナのイメージは、下記の PHP の公式イメージを使用します。 イメージのバージョン(タグ)はいろいろありますが、今回は Apache と PHP 8.2 が最初からインストールされている 8.2-apache を使用します。 PHP のバージョンを変更したい場合は、別のタグに変更してください(例:PHP 8.1 の場合は 8.1-apache)。

Apache は Web サーバーですので、コンテナ側のポート番号は 80 番です。 ホスト側から Web ブラウザ(Chrome など)で接続できるよう、コンテナ側のポート 80 番へのマッピングを設定しましょう。 ホスト側のポート番号は、他で使用されていないものなら何番でも良いと思います。

ドキュメントルートはデフォルトだと "/var/www/html" になります。 ドキュメントルートにファイルがないと Apache は何も表示できませんので、 ホストのディレクトリとバインドマウントして、 そこに HTML ファイルや PHP ファイルを置いて動作確認してみましょう。 まずは、phpinfo() を表示してみるのが良いと思います。

例:ホストの "./html" を、コンテナの "/var/www/html" にバインドマウントする場合
docker-compose.yml
version: "3.8"
services:

  # Apache コンテナ
  apache:
    image: php:8.2-apache
    ports:
      - 8080:80
    volumes:
      - ./html:/var/www/html

ドキュメントルートを変更する

ドキュメントルートを変更するには、Apache の設定ファイルを書き換える必要がありますので Dockerfile を使用するように変更しましょう。 Dockerfile を下記のような記述にして作成すると、ドキュメントルートを変更できるようになります。 Apache の設定ファイルは "/etc/apache2" ディレクトリ配下にあります。

例:ドキュメントルートを "/path/to/new/root" に変更する場合
./apache-custom/Dockerfile
FROM php:8.2-apache

# ドキュメントルートを変更
ENV APACHE_DOCUMENT_ROOT /path/to/new/root
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
docker-compose.yml
version: "3.8"
services:

  # Apache コンテナ
  apache:
    build: ./apache-custom
    ports:
      - 8080:80
    volumes:
      - ./html:/path/to/new/root

docker-compose.yml からドキュメントルートを変更する

上記の Dockerfile の記述をよく見てもらうとわかると思うのですが、 環境変数 APACHE_DOCUMENT_ROOT を使用してドキュメントルートを変更していますので、 docker-compose.yml ファイルからさらに上書きして変更することもできるようになります。

例:ドキュメントルートを "/path/to/example/root" に変更する場合
docker-compose.yml
version: "3.8"
services:

  # Apache コンテナ
  apache:
    build: ./apache-custom
    ports:
      - 8080:80
    volumes:
      - ./html:/path/to/example/root
    environment:
      APACHE_DOCUMENT_ROOT: /path/to/example/root

Apache のモジュールを有効化する

デフォルトだと mod_rewrite などの Apache のモジュールが有効になっていないので、 必要なモジュールがあれば有効化しましょう。

現在有効な Apache のモジュールの一覧を表示する

現在有効な Apache のモジュールの一覧を表示するには、下記のコマンドをコンテナの中で実行します。

apachectl -M

Apache のモジュールを有効化する

Apache のモジュールを有効化するには、a2enmod コマンドを使用します。 このコマンドは複数のモジュールをまとめて有効化することができます。

例: "mod_deflate"、"mod_expires"、"mod_rewrite" を有効化する場合
Dockerfile
FROM php:8.2-apache

# Apache のモジュールを有効化
RUN a2enmod deflate expires rewrite

PHP のエクステンションをインストールする

デフォルトの PHP だといろいろ困ると思いますので、PHP のエクステンションをインストールしましょう。

ただ、Docker に PHP のエクステンションをインストールするのはかなり大変です。 エクステンションごとに依存しているライブラリが違っていますし、ライブラリのバージョンが違っていれば正しく動きませんし、インストール方法もそれぞれ異なっていたりします。 下手をすると、ライブラリをソースコードからビルドしなければならなくなったりします。 特に PHP 8.1 から追加された AVIF を使用する GD エクステンションを手動でインストールするのはかなり大変です。

そこで、install-php-extensions コマンドを使用すると良いでしょう。 公式でも紹介されている方法なので安心してください。 エクステンションをインストールする際に必要な作業は、このコマンドが全てやってくれます。 ImageMagick や Xdebug などもこのコマンド1つでインストールできるので、かなり便利だと思います。

install-php-extensions コマンドをインストールする

install-php-extensions コマンドをインストールするには、下記のように Dockerfile を変更します。

Dockerfile
FROM php:8.2-apache

# install-php-extensions をインストール
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

PHP のエクステンションをインストールする

次に、先ほどインストールした install-php-extensions コマンドを使用して、 PHP のエクステンションをインストールします。

このコマンドは、複数の PHP のエクステンションをまとめてインストールすることができますが、 インストールするエクステンションによってはかなりの時間がかかりますので注意してください。 特に PHP 8.1 から追加された AVIF を使用する GD エクステンションのインストールはかなり長い時間がかかります。

インストールするエクステンションをあまり変更しない場合は、まとめてインストールしても良いと思いますが、 頻繁に変更する場合は、1つずつ個別にインストールして、レイヤーをキャッシュさせていった方が良いかもしれません。 そうすれば次にビルドした時にキャッシュが使用されて、ビルド時間が短くなります。 ただし、レイヤーが増えればその分イメージのサイズが増えますので、イメージのサイズが気にならない方は検討してみてください。

例:複数のエクステンションをまとめてインストールする場合
Dockerfile
FROM php:8.2-apache

# install-php-extensions をインストール
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

# PHP のエクステンションをインストール
RUN install-php-extensions opcache intl gd exif imagick mysqli pdo_mysql redis xdebug
例:1つずつ個別にエクステンションをインストールする場合
Dockerfile
FROM php:8.2-apache

# install-php-extensions をインストール
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

# PHP のエクステンションをインストール
RUN install-php-extensions opcache
RUN install-php-extensions intl
RUN install-php-extensions gd
RUN install-php-extensions exif
RUN install-php-extensions imagick
RUN install-php-extensions mysqli
RUN install-php-extensions pdo_mysql
RUN install-php-extensions redis
RUN install-php-extensions xdebug

PHP の設定ファイルを使用する

PHP の設定を変更したい場合は、PHP の設定ファイルである php.ini を使用すると良いでしょう。 PHP の設定ファイルの場所は "/usr/local/etc/php/php.ini" になります。

バインドマウントを使用する

PHP の設定ファイルを頻繁に変更するなら、バインドマウントを使用すると良いでしょう。 なお、PHP の設定ファイルを変更した場合は、反映させるためにコンテナの再起動(正確には Apache の再起動)が必要になるので注意してください。

例:ホストの "./php.ini" を、コンテナの "/usr/local/etc/php/php.ini" にバインドマウントする場合
docker-compose.yml
version: "3.8"
services:

  # Apache コンテナ
  apache:
    build: ./apache-custom
    ports:
      - 8080:80
    volumes:
      - ./php.ini:/usr/local/etc/php/php.ini
      - ./html:/var/www/html

Dockerfile を使用する

PHP の設定ファイルをあまり変更しないのなら、バインドマウントではなく Dockerfile を使用すると良いでしょう。 Dockerfile の中で、PHP の設定ファイルをコンテナにコピーします。 ついでに chmod コマンドでパーミッションを設定しておくと良いでしょう。 なお、PHP の設定ファイルを変更した場合は、反映させるためにコンテナをビルドし直す必要があります。

例:ホストの "./apache-custom/php.ini" を、コンテナの "/usr/local/etc/php/php.ini" にコピーする場合
./apache-custom/Dockerfile
FROM php:8.2-apache

# PHP の設定ファイルを配置
COPY ./php.ini /usr/local/etc/php/php.ini
RUN chmod 644 /usr/local/etc/php/php.ini

おまけ:バーチャルホストを使用する

複数のサイトを Docker で動作させたい場合、 1つのサイトごとに1つずつコンテナを作っても良いのですが、 それだと CPU やメモリなどの消費リソースが増えてしまい、 スペックの低い PC だと動作させるのが大変かもしれません。 そういった場合は、Apache のバーチャルホストを使用すると良いでしょう。 バーチャルホストを使用すると複数のサイトを1つのコンテナで動作させることができます。

例として、2つのサイトを使えるようにしてみます。

デフォルトのサイト設定を無効化する

まずはデフォルトのサイト設定が邪魔にならないよう無効化しておきましょう。 無効化しなくても良いと言えば良いのですが、バーチャルホストを使って複数サイトを管理するならおそらく使用しないと思います。

サイトの設定を無効化するには、a2dissite コマンドを使用します。 デフォルトのサイト設定は、設定ファイルが "000-default.conf" という名前になっていますので、 a2dissite 000-default と実行します。

Dockerfile
FROM php:8.2-apache

# デフォルトのサイト設定を無効化
RUN a2dissite 000-default

各サイトの設定を追加して有効化する

次にバーチャルホストを使用したい各サイトの設定ファイルを追加します。

各サイトの設定ファイルを "/etc/apache2/sites-available" ディレクトリの配下に置いて、 a2ensite コマンドで有効化していきます。 a2ensite コマンドを使用せずに、 直接 "/etc/apache2/sites-enabled" ディレクトリの配下に置いても良い気もしますが、 ここでは説明のためにちゃんとした手順を記載しておきます。

サイトの設定ファイルはアルファベット順に読み込まれます。 優先順位を付けたい場合は、ファイルの名前の先頭に番号を付けておくと良いでしょう。 どのサイトのホスト名にも一致しない URL が指定された場合、最初に読み込まれた設定ファイルのサイトが表示されます。 デフォルトのサイト設定のファイルの名前が "000-default.conf" になっているのはそのためです。

例:サイト1の設定ファイル(ホスト名は "site1.localhost")
./apache-custom/001-site1.conf
<VirtualHost *:80>
    ServerName site1.localhost
    DocumentRoot "/path/to/site1/root"
</VirtualHost>

<Directory "/path/to/site1/root">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>
例:サイト2の設定ファイル(ホスト名は "site2.localhost")
./apache-custom/002-site2.conf
<VirtualHost *:80>
    ServerName site2.localhost
    DocumentRoot "/path/to/site2/root"
</VirtualHost>

<Directory "/path/to/site2/root">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>
例:サイト1の設定ファイルと、サイト2の設定ファイルを追加して有効化
./apache-custom/Dockerfile
FROM php:8.2-apache

# デフォルトのサイト設定を無効化
RUN a2dissite 000-default

# サイト1の設定を追加して有効化
COPY ./001-site1.conf /etc/apache2/sites-available/001-site1.conf
RUN a2ensite 001-site1

# サイト2の設定を追加して有効化
COPY ./002-site2.conf /etc/apache2/sites-available/002-site2.conf
RUN a2ensite 002-site2

各サイトのドキュメントルートにファイルを配置する

最後に各サイトのドキュメントルートにバインドマウントして、表示したいファイルを配置します。

例:2つのサイトのドキュメントルートにバインドマウント
docker-compose.yml
version: "3.8"
services:

  # Apache コンテナ
  apache:
    build: ./apache-custom
    ports:
      - 8080:80
    volumes:
      - ./site1_html:/path/to/site1/root
      - ./site2_html:/path/to/site2/root

なお、バーチャルホストで使用する URL のホスト名は hosts ファイルなどで、ローカルホスト(例:"127.0.0.1")に名前解決する必要があるので注意してください。 また、ホスト側のポート番号を 80 番以外にしている場合は、URL にポート番号を付けるのを忘れないようにしましょう。 例えば、上記の例のような設定だと、サイト1にアクセスするURLは "http://site1.localhost:8080/"、サイト2にアクセスするURLは "http://site2.localhost:8080/" のようになります。

参考サイト

関連記事

Docker の PHP コンテナで開発する際に、テスト用のメールサーバーを使用すると便利です。メールを外部に送信せずに、メールの動作確認を行うことができます。Mailpit とは?Mailpit はテスト用に開発されたメールサーバーです。Go 言語で実装されています。本物のメールサーバーのように振舞いながらも、メール ...
ほとんどの Web アプリではデータを保存する際に、データベースを使用しています。XAMPP では、データベースとして MySQL と互換性のある MariaDB が採用されていますが、Docker を使用するのであればせっかくなので MySQL のコンテナを作成してみましょう。Docker で MySQL コンテナを ...
データベースのソフトウェアとしては MySQL(MariaDB)が人気だと思いますが、PostgreSQL を使用しているサービスを見かけることもあるでしょう。Docker で PostgreSQL のコンテナを作成してみましょう。Docker で PostgreSQL コンテナを作るコンテナのイメージは、下記の公式イ ...
近年 Web サーバーは、Apache の代わりに nginx もよく使用されています。お仕事で使用している方も多いのではないでしょうか。nginx から PHP を使用したい場合、FPM(FastCGI Process Manager)版の PHP が必要になります。Docker で nginx + PHP-FPM ...
Docker は、構成を気軽に組み替えたりできるので、とても便利ですよね。Windows で Docker を使って開発している方も多いと思うのですが、個人的にはどうしても気が乗らない理由がありました。それは処理速度です。遅い。遅すぎる。めちゃくちゃ遅い。つらい。耐えられない。。。ということで調査しました。いろいろと調 ...
最近では、アプリケーションの実行環境の構築に Docker を使うことも珍しくなくなりました。Docker は便利ではあるのかもしれませんが、難しく感じて敬遠されている人もいるのではないでしょうか。その感覚はおそらく間違っていません。実際、知れば知るほど奥が深い技術だと感じてしまいます。もはや沼というか深淵を覗いている ...

記事検索

最新記事

人気記事

RSSフィード

お知らせ

フィードバック

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

匿名でフィードバックする
匿名でフィードバックする

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

なお、このフォームから入力された内容について、管理者から返信はできませんので注意してください。 もし、管理者からの返信が必要であれば、X(Twitter) もしくは、お問い合わせより、お願いします。

  • フィードバックの送信が完了しました。