Docker で Apache + PHP コンテナを作る方法
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()
を表示してみるのが良いと思います。
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" ディレクトリ配下にあります。
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
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 ファイルからさらに上書きして変更することもできるようになります。
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
コマンドを使用します。
このコマンドは複数のモジュールをまとめて有効化することができます。
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 を変更します。
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つずつ個別にインストールして、レイヤーをキャッシュさせていった方が良いかもしれません。 そうすれば次にビルドした時にキャッシュが使用されて、ビルド時間が短くなります。 ただし、レイヤーが増えればその分イメージのサイズが増えますので、イメージのサイズが気にならない方は検討してみてください。
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
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 の再起動)が必要になるので注意してください。
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 の設定ファイルを変更した場合は、反映させるためにコンテナをビルドし直す必要があります。
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
と実行します。
FROM php:8.2-apache # デフォルトのサイト設定を無効化 RUN a2dissite 000-default
各サイトの設定を追加して有効化する
次にバーチャルホストを使用したい各サイトの設定ファイルを追加します。
各サイトの設定ファイルを "/etc/apache2/sites-available" ディレクトリの配下に置いて、
a2ensite
コマンドで有効化していきます。
a2ensite
コマンドを使用せずに、
直接 "/etc/apache2/sites-enabled" ディレクトリの配下に置いても良い気もしますが、
ここでは説明のためにちゃんとした手順を記載しておきます。
サイトの設定ファイルはアルファベット順に読み込まれます。 優先順位を付けたい場合は、ファイルの名前の先頭に番号を付けておくと良いでしょう。 どのサイトのホスト名にも一致しない URL が指定された場合、最初に読み込まれた設定ファイルのサイトが表示されます。 デフォルトのサイト設定のファイルの名前が "000-default.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>
<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>
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
各サイトのドキュメントルートにファイルを配置する
最後に各サイトのドキュメントルートにバインドマウントして、表示したいファイルを配置します。
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/" のようになります。