Docker Container の軽量化 あるいはAWS ECS Taskの起動速度改善
以前の記事 でPHP ApplicationのDockerfileを書きましたが Apacheモジュールバージョンではなく fpmで運用したくなったので書き直します。
また、せっかくなのでdebian baseとalpine baseを用意して サイズの比較と、実際にAWS ECSでの起動速度をカジュアルに計測してみます。
debian base
php
Redis Accessを想定したPHP Application
FROM php:7.4-fpm ## config file copy COPY ./config/php/* /tmp/ ## project directory copy COPY . /var/www/html/sample-app RUN apt-get update \ && pecl install redis-5.2.2 \ && docker-php-ext-enable redis \ && mv /tmp/php.ini-development "$PHP_INI_DIR/php.ini-development" \ && mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" \ && mv /tmp/www.conf /usr/local/etc/php-fpm.d/www.conf \ ## directory権限をwww-dataにしてpermission && SGID変更 ## directory -> 770, file -> 660 && chown -R www-data:www-data /var/www/html \ && find /var/www/html -type d -exec chmod 770 {} \; \ && find /var/www/html -type f -exec chmod 660 {} \; \ && chmod -R 2770 /var/www/html \ ## userを作成してwww-data groupに入れる && useradd webdev \ && usermod -g www-data webdev EXPOSE 9000 USER webdev
nginx
FROM nginx:1.19.0 ARG PHP_HOST="127.0.0.1:9000" ## config file copy COPY ./config/nginx/* /tmp/ RUN apt-get update \ # docker-composeとawsでhostの形式を書き換える && sed -i -e "s/127.0.0.1:9000/$PHP_HOST/g" /tmp/default.conf \ && mv /tmp/nginx.conf /etc/nginx/nginx.conf \ && mv /tmp/default.conf /etc/nginx/conf.d/default.conf \ && touch /var/run/nginx.pid \ && chown -R nginx:nginx /var/run/nginx.pid \ && chown -R nginx:nginx /var/cache/nginx USER nginx EXPOSE 8080
alpine base
php
FROM php:7.4-fpm-alpine ## config file copy COPY ./config/php/* /tmp/ ## project directory copy COPY . /var/www/html/sample-app RUN apk update \ && apk add --no-cache --update --virtual .build-deps \ autoconf gcc g++ make \ && pecl channel-update pecl.php.net \ && pecl install redis-5.2.2 \ && docker-php-ext-enable redis \ && mv /tmp/php.ini-development "$PHP_INI_DIR/php.ini-development" \ && mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" \ && mv /tmp/www.conf /usr/local/etc/php-fpm.d/www.conf \ ## directory権限をwww-dataにしてpermission && SGID変更 ## directory -> 770, file -> 660 && chown -R www-data:www-data /var/www/html \ && find /var/www/html -type d -exec chmod 770 {} \; \ && find /var/www/html -type f -exec chmod 660 {} \; \ && chmod -R 2770 /var/www/html \ ## userを作成してwww-data groupに入れる && adduser -D -u 1000 -G www-data webdev \ && apk del .build-deps \ && rm -rf /tmp/* /var/tmp/* EXPOSE 9000 USER webdev
nginx
alpine-baseで containerをnginxで起動した際に unlink() /var/run/nginx.pid failed permission denied
が出るようになったのでcontainer自体はとりあえず root user で起動することにしました。
FROM nginx:1.19.0-alpine ARG PHP_HOST="127.0.0.1:9000" ## config file copy COPY ./config/nginx/* /tmp/ RUN apk update \ && apk add --no-cache --update --virtual .build-deps sed \ # docker-composeとawsでhostの形式を書き換える && sed -i -e "s/127.0.0.1:9000/$PHP_HOST/g" /tmp/default.conf \ && mv /tmp/nginx.conf /etc/nginx/nginx.conf \ && mv /tmp/default.conf /etc/nginx/conf.d/default.conf \ && touch /var/run/nginx.pid \ && chown -R nginx:nginx /var/run/nginx.pid \ && chown -R nginx:nginx /var/cache/nginx \ && apk del .build-deps \ && rm -rf /tmp/* /var/tmp/* EXPOSE 8080
nginx.conf
user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; # https://dev.classmethod.jp/articles/set_keepalivetimeout_on_apache_for_resolve_elb_timeout/ # https://yomon.hatenablog.com/entry/2016/10/08/220338 keepalive_timeout 120; # https://aws.amazon.com/jp/blogs/compute/nginx-reverse-proxy-sidecar-container-on-amazon-ecs/ gzip on; gzip_proxied any; gzip_types application/javascript application/json; gzip_min_length 1000; include /etc/nginx/conf.d/*.conf; }
default.conf
server { listen 8080 default; server_name _; root /var/www/html/sample-app; # code igniter用の redirect location / { try_files $uri $uri/ /public/index.php$request_uri; } location ~ [^/]\.php(/|$) { fastcgi_pass 127.0.0.1:9000; fastcgi_read_timeout 120; fastcgi_split_path_info ^(.+?\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } }
docker-compose.yaml
version: "3.4" services: php: build: context: . environment: - REDIS_HOST=localhost ports: - "9000:9000" volumes: - .:/var/www/html/sample-app nginx: build: context: . dockerfile: Dockerfile-nginx # docker-compose起動のときはdocker container network args: - PHP_HOST=php:9000 ports: - "8080:8080" depends_on: - php
container size
Container | Size |
---|---|
php-debian | 436 MB |
nginx-debian | 150 MB |
php-alpine | 96 MB |
nginx-alpine | 23 MB |
ぜんぜん違う 🧐
ECS (FARGATE) 起動速度
Provisioning 開始から Runningになるまでの秒数で計測
それぞれ3回試して、平均値を取りました。当初もっと試行回数を取ろうと思っていましたが、速度が安定していたので十分と判断しました。
Type | Sec |
---|---|
debian base | 41 |
alpine base | 30 |
alpine baseの方が 10 sec ほど早くなりました。10 secの起動速度差は結構大きいのでは。やはり、軽いは正義。
まとめ
早くなってよかった (konami kan)