開発環境だけアプリがめちゃくちゃ重い
新しいチームに配属されて最初の感想です。
本番ではめちゃめちゃ早いのに開発環境がむちゃくちゃに遅い。
DXが最悪だったので原因を調査したところAlpineからCentOSに乗り換えたら3倍ぐらい早くなったという話です。
ベンチマーク
長々した説明は置いといて、結論から言うと「よくわからないがdockerで動かしているphpが異常に重い」ということだけがわかった。
これアプリケーションコードが重いというわけではなく、Alpine Linux on Docker で動いているLaravelが全体的に処理が遅いという体感があったので実際に計測してみた。
以下のPHPコードをAlpineとCentOSで動かして比較してみる。CentOSのDockerfileはPHP入れる処理だけなので省略。
<?php
ini_set('memory_limit', '-1');
function benchmark($i) {
if($i ==! 0) {
benchmark($i - 1);
}
function() { return sha1("test${i}");};
function() { return md5("test${i}");};
}
$time_start = microtime(true);
foreach (range(1, 10000) as $i) {
benchmark($i);
}
$time = microtime(true) - $time_start;
echo "{$time} sec";
コードの内容は至って簡単で、メモリ上限を無くし再帰的処理でハッシュを取得していくだけ。
/t/test docker run --rm -v /tmp/test/test.php:/test.php centos-php php /test.php
8.2858350276947 sec
/t/test docker run --rm -v /tmp/test/test.php:/test.php centos-php php /test.php
8.2832388877869 sec
/t/test docker run --rm -v /tmp/test/test.php:/test.php centos-php php /test.php
8.2994618415833 sec
/t/test docker run --rm -v /tmp/test/test.php:/test.php php:7.4.1-fpm-alpine php /test.php
8.1350269317627 sec
/t/test docker run --rm -v /tmp/test/test.php:/test.php php:7.4.1-fpm-alpine php /test.php
8.0924451351166 sec
/t/test docker run --rm -v /tmp/test/test.php:/test.php php:7.4.1-fpm-alpine php /test.php
8.0950059890747 sec
これは特に問題なさそう(むしろAlpineの方が早い
Laravelでのベンチマーク
実際にLaravelで測定した時の結果を貼っていく
用意が面倒だったので開発環境での弊社サービスのLPページを測定対象とする
alpineでのdockerfileは以下の通り
FROM php:7.3-fpm-alpine
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php
RUN apk --no-cache update \
&& apk add --no-cache $PHPIZE_DEPS postgresql-dev libpng-dev libjpeg-turbo-dev icu-dev \
&& docker-php-ext-configure gd --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ \
&& docker-php-ext-configure intl --enable-intl \
&& docker-php-ext-install exif pdo_pgsql gd intl opcache pcntl
RUN pecl install xdebug \
&& docker-php-ext-enable xdebug
WORKDIR /var/www/html
対してCentOSベースのDockerfileは以下の通り
FROM centos:7.5.1804
#locale 追加
RUN sed -i -e '/override_install_langs/s/$/,ja_JP.utf8/g' /etc/yum.conf
RUN curl -sL https://rpm.nodesource.com/setup_10.x | bash - \
&& yum install -y http://rpms.famillecollet.com/enterprise/remi-release-7.rpm \
https://s3-ap-northeast-1.amazonaws.com/sen-infra/rpms/centos/7/x86_64/pgdg-centos10-10-2.noarch.rpm \
&& yum install -y postgresql10 \
nodejs \
zlib-devel \
glibc-common \
make \
libpng-devel \
cronie \
&& yum install -y --enablerepo=remi,remi-php73 \
php \
php-opcache \
php-mbstring \
php-pdo \
php-pecl-memcache \
php-pecl-memcached \
php-pecl-redis \
php-pecl-imagick \
php-mcrypt \
php-mysqlnd \
php-xml \
php-gd \
php-devel \
php-pgsql \
php-pecl-ssh2 \
php-process \
php-intl \
php-pear \
php-pecl-apcu \
php-pecl-apcu-bc \
php-pecl-zip \
php-fpm \
&& rm -rf /var/cache/yum/* \
&& yum clean all
COPY ./php-fpm.conf /etc/php-fpm.conf
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin \
&& mv /usr/local/bin/composer.phar /usr/local/bin/composer \
&& composer global require hirak/prestissimo
WORKDIR /var/www/html
CMD ["/usr/sbin/php-fpm","-F","-y","/etc/php-fpm.conf"]
LPページなのでミドルウェアもプロパイダーも挟んではいない(はず
まずはAlpineから
yoshiken@yskn:~/Git/sen/album$ time curl localhost
real 0m0.392s
user 0m0.013s
sys 0m0.004s
yoshiken@yskn:~/Git/sen/album$ time curl localhost
real 0m0.392s
user 0m0.013s
sys 0m0.000s
yoshiken@yskn:~/Git/sen/album$ time curl localhost
real 0m0.409s
user 0m0.012s
sys 0m0.004s
平均して約0.4sec
対してCentOSベースでは
yoshiken@yskn:~/Git/sen/album$ time curl localhost
real 0m0.064s
user 0m0.007s
sys 0m0.007s
yoshiken@yskn:~/Git/sen/album$ time curl localhost
real 0m0.062s
user 0m0.003s
sys 0m0.012s
yoshiken@yskn:~/Git/sen/album$ time curl localhost
real 0m0.052s
user 0m0.014s
sys 0m0.000s
平均して0.06sec前後といったところ。
よくわからん
ここまで書いていてなんだが、何故PHPとしてのパフォーマンスが上のAlpineがLaravelを介すると急激に遅くなるかわかっていない。
調べた感じAlpineだと遅いという点では色々困ってる人が見当たってるが、具体的な解決策、根本原因は未だ解明されていない。
[5.2] Slow response times running within a php-7 Docker container · Issue #12228 · laravel/framework
php - PHP7 + Laravel +Nginx is terribly slow on Docker - Stack Overflow
AlpineでPythonが遅くなるのはAlpineの独自パッケージによる差分が原因とされているが、PHPでは最初のベンチマークの時点では大きな乖離がなかった。
https://superuser.com/questions/1219609/why-is-the-alpine-docker-image-over-50-slower-than-the-ubuntu-image
言いたいこと
いろんな記事で「DockerとAlpine使って爆速で環境構築!!!」という文章を見かけるが、一旦待ってほしい。
ローカル環境では急速なスケールをする必要もないのでイメージが大きかろうが特に問題は無いわけであって、重要なのは使うフレームワークや言語に最適化された環境である。
もし、本番環境でコンテナ運用して開発と同じイメージ(特にAlpineLinux)を使用しているという状況であれば、まず一旦そのイメージの妥当性を確認すべきなのかなと。
他のディストリビューションをベースにした場合との速度計測をして正しい技術選定を行った方がよいのではと思う次第。