はじめに
年末にひさしぶりにPHPのプロジェクトを作る機会がありました。
いつの間にかPHP7.3がリリースされており、
いつの間にかPHPの公式コンテナも出ていたので、
ノウハウを共有するため、ひととおり本番運用を想定したコンテナイメージの作成方法をまとめました。
長くなったので、実際にプロジェクトとして動かすための手順は以下の記事でまとめました。
dockerでPHP7.3+Laravel環境を15分で作る~2019年版
構築環境のバージョン情報
- MacOS High Siera 10.13.6
- Docker Desktop : Version 2.0.0.0-mac81 (29211)
最終的なDockerfile
2019/01/26 追記
@hokutoasari さんの記事を参考に echo 'opcache.optimization_level=0x7FFFBBFF'
を追加しました。
FROM php:7.3.0-fpm-alpine3.8
RUN apk upgrade --update && \
apk --no-cache add icu-dev autoconf make g++ gcc
RUN docker-php-ext-install -j$(nproc) iconv intl mbstring pdo_mysql opcache && \
pecl install xdebug-2.7.0beta1 && \
docker-php-ext-enable xdebug
RUN { \
echo 'short_open_tag = On'; \
echo 'fastcgi.logging = 1'; \
echo 'opcache.enable=1'; \
echo 'opcache.optimization_level=0x7FFFBBFF' ; \
echo 'opcache.revalidate_freq=0'; \
echo 'opcache.validate_timestamps=1'; \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=60'; \
echo 'opcache.fast_shutdown=1'; \
echo 'xdebug.remote_enable=1'; \
} > /usr/local/etc/php/conf.d/overrides.ini
COPY . /var/www/html
開発環境でデバッグするためにxdebugは入れていますが、本番用のコンテナでは入れないようにしましょう。
解説
ベースとなるコンテナを選択
https://hub.docker.com/_/php/
公式のdockerhubを見ると、いくつか種類があります。
今回は、PHP-FPMがあるものの中から選びます。
将来的に本番でも利用したいので、できるだけ軽量のalpineベースのイメージを利用します。 ※ ベースとなるOSが変わると、パッケージの依存関係の解消が面倒になることがあるので、ベースイメージは本番/開発ともに同じものを利用します。
Image名 | OS | Size |
---|---|---|
php:7.3.0-fpm | Debian | 372MB |
php:7.3.0-fpm-alpine | Alpine | 78MB |
FROM php:7.3.0-fpm-alpine3.8
できる限りバージョンは指定しましょう。
モジュールのインストール
docker-php-ext-xxx について
docker-php-ext-configure
とdocker-php-ext-install
は、コンテナイメージに事前に圧縮されて入っているエクステンションを操作できます。
- configure : 設定をカスタマイズしたいものの設定を行う ex) gd, intl
- install : 解凍してインストール
configureを指定したエクステンションは、のちほどinstallをする必要があります。
docker-php-ext-enable
は、peclで入れたextensionを有効にします。 ※ peclコマンドもコンテナにデフォルトで入っています。
たとえばこんな感じです。
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ && \
docker-php-ext-install -j$(nproc) gd intl mbstring pdo_mysql opcache && \
pecl install xdebug-2.7.0beta1 && \
docker-php-ext-enable xdebug
-j
オプションは、makeに渡す引数です。 並列ではしらせるジョブの上限を指定します。
https://www.gnu.org/software/make/manual/html_node/Parallel.html
利用可能なスレッドの数は環境に応じて変わるので、 $nproc
を入れています。
一応、あとで出来上がったコンテナにの端末で、moduleを確認してみましょう。
$ docker run --rm --interactive --tty {container} sh
> コンテナの端末に接続
/var/www # php -m
[PHP Modules]
Core
ctype
curl
date
dom
fileinfo
filter
ftp
gd
hash
iconv
intl
json
libxml
mbstring
mysqlnd
openssl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
readline
Reflection
session
SimpleXML
sodium
SPL
sqlite3
standard
tokenizer
xdebug
xml
xmlreader
xmlwriter
Zend OPcache
zlib
[Zend Modules]
Xdebug
Zend OPcache
モジュールが認識されていることが確認できました。
利用可能なモジュールの確認
利用できるext-nameは以下の方法で確認するのが確実です。
$ docker run --rm php:7.3.0-fpm-alpine docker-php-ext-install
usage: /usr/local/bin/docker-php-ext-install [-jN] ext-name [ext-name ...]
ie: /usr/local/bin/docker-php-ext-install gd mysqli
/usr/local/bin/docker-php-ext-install pdo pdo_mysql
/usr/local/bin/docker-php-ext-install -j5 gd mbstring mysqli pdo pdo_mysql shmop
if custom ./configure arguments are necessary, see docker-php-ext-configure
Possible values for ext-name:
bcmath bz2 calendar ctype curl dba dom enchant exif fileinfo filter ftp gd gettext gmp hash iconv imap interbase intl json ldap mbstring mysqli oci8 odbc opcache pcntl pdo pdo_dblib pdo_firebird pdo_mysql pdo_oci pdo_odbc pdo_pgsql pdo_sqlite pgsql phar posix pspell readline recode reflection session shmop simplexml snmp soap sockets sodium spl standard sysvmsg sysvsem sysvshm tidy tokenizer wddx xml xmlreader xmlrpc xmlwriter xsl zend_test zip
Some of the above modules are already compiled into PHP; please check
the output of "php -i" to see which modules are already loaded.
Possible values for ext-name 以下に利用可能なモジュールが記載されています。
xdebugの導入
PHP7.3用のxdebugは 2.7.0beta1
です。 (2019/1/3 時点)
https://pecl.php.net/package/xdebug
バージョン指定して pecl install
します。
本番で利用するコンテナにビルドする際は、xdebugが入らないようにしましょう。
php.iniの設定
ファイルを作成して、イメージ内にCOPYしてもいいんですが、Dockerfileだけで済ませたいのでファイルにechoします。
RUN { \
echo 'upload_max_filesize = 100M'; \
echo 'post_max_size = 108M'; \
echo 'short_open_tag = On'; \
echo 'fastcgi.logging = 1'; \
echo 'opcache.enable=1'; \
echo 'opcache.optimization_level=0x7FFFBBFF'; \
echo 'opcache.revalidate_freq=0'; \
echo 'opcache.validate_timestamps=1'; \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=60'; \
echo 'opcache.fast_shutdown=1'; \
echo 'xdebug.remote_enable=1'; \
} > /usr/local/etc/php/conf.d/overrides.ini
補足 : composerの導入
composer用のコンテナを立てて、composerのコマンドはそこで実行するのがベストプラクティスです。これについては後述します。
ただ、あとから取り除いても大きな影響はないので、とりあえず開発を初めたい人はcomposerを直接コンテナにいれてもいいと思います。
RUN php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer && \
apk --no-cache add git zip
パッケージインストール
基本的にはモジュールベースで考えると思うので最後に持ってきました。
それぞれのモジュールに必要なパッケージを入れましょう。
RUN apk upgrade --update && \
apk --no-cache add icu-dev autoconf make g++ gcc
注意点
より小さいコンテナサイズを目指す
本気でコンテナファイルを作成するときは、できるだけコンテナサイズを小さくするためにmulti stage buildをして、本番利用しないファイルはすべてコンテナに入らないよう調整します。
参考記事 : https://qiita.com/minamijoyo/items/711704e85b45ff5d6405
composerは別コンテナで稼働させる
前述しましたが、通常、composerはcomposer専用のコンテナを通して実行することもできます。
たとえば ローカルのディレクトリに、composer installしたvendorファイルを追加したい場合は以下のように行います。
$ docker run --rm --interactive --tty -v $(pwd):/app \
composer composer install
or
$ docker run --rm --interactive --tty -v $(pwd):/app \
composer bash -c "composer install"
本番/開発コンテナの違い
本番/開発コンテナは基本的には分けたほうがいいと考えています。
本番用でビルドする場合は、以下のような違いをつけます。
- xdebugを入れない
-
composer install --no-dev
でパッケージを分ける - 本番には不要なファイル群をコンテナから取り除く
- テストファイルやデータ系ファイルなど
- .dockerignoreやmulti stage buildを利用
最後に
とりあえず PHP7.3で一通り最初のプロジェクト作成で必要な状態にはなりました。
現実で利用できるようなPHP-FPMコンテナは別の記事で~~書きます 。~~書きました。
dockerでPHP7.3+Laravel環境を15分で作る~2019年版