From 946246519763927a328f469bd1969e9735be6962 Mon Sep 17 00:00:00 2001 From: Antonio Spinelli Date: Mon, 31 May 2021 00:19:29 -0300 Subject: [PATCH] Speed up PHP-fpm container on MacOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Many MacOS users may be facing slow responses from Shop or Admin when running the sylius application in the container. The main reason is how docker was build in the MacOS architecture. The PHP application has thousands of files to be loaded in memory (vendor directory mainly). So, to decrease the page response time, the vendor directory is not synced into the container. It will be ignored by docker-composer.yml using the named volume. Also, was added a health check for the PHP-fpm container to know when it is ready. If you want to check healthiness, just run the command `docker-compose ps` to see the container State. The HEALTHCHECK instruction tells Docker how to test a container to check that it is still working. This can detect cases such as a web server stuck in an infinite loop and unable to handle new connections, even though the server process is still running. The PHP and PHP-FPM configurations received some adjustments to get better support development environment experience using containers. I did pick up these updates from two other contributors that I co-authored in this commit. Co-authored-by: Kévin Dunglas Co-authored-by: arti0090 --- .env | 3 +- Dockerfile | 23 ++++++++++++--- README.md | 48 ++++++++++++++++++++++++++++++++ docker-compose.yml | 24 ++++++++++------ docker/php/docker-entrypoint.sh | 20 +++++-------- docker/php/docker-healthcheck.sh | 12 ++++++++ docker/php/php-cli.ini | 12 +++++--- docker/php/php.ini | 11 ++++++-- docker/php/sylius.conf | 28 +++++++++++++++++++ 9 files changed, 148 insertions(+), 33 deletions(-) create mode 100644 docker/php/docker-healthcheck.sh create mode 100644 docker/php/sylius.conf diff --git a/.env b/.env index 00581e5952..1eaf2d1f14 100644 --- a/.env +++ b/.env @@ -6,13 +6,14 @@ APP_ENV=dev APP_DEBUG=1 APP_SECRET=EDITME +PHP_DATE_TIMEZONE=UTC ###< symfony/framework-bundle ### ###> doctrine/doctrine-bundle ### # Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url # For a sqlite database, use: "sqlite:///%kernel.project_dir%/var/data.db" # Set "serverVersion" to your server version to avoid edge-case exceptions and extra database calls -DATABASE_URL=mysql://root@127.0.0.1/sylius_%kernel.environment% +DATABASE_URL=mysql://root:nopassword@mysql/sylius_${APP_ENV} ###< doctrine/doctrine-bundle ### ###> symfony/swiftmailer-bundle ### diff --git a/Dockerfile b/Dockerfile index 7648fba49c..4922ae8bef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,20 +3,21 @@ ARG PHP_VERSION=7.4 ARG NODE_VERSION=10 -ARG NGINX_VERSION=1.16 +ARG NGINX_VERSION=1.17 FROM php:${PHP_VERSION}-fpm-alpine AS sylius_php # persistent / runtime deps RUN apk add --no-cache \ acl \ + fcgi \ file \ gettext \ git \ mariadb-client \ ; -ARG APCU_VERSION=5.1.17 +ARG APCU_VERSION=5.1.18 RUN set -eux; \ apk add --no-cache --virtual .build-deps \ $PHPIZE_DEPS \ @@ -33,6 +34,7 @@ RUN set -eux; \ ; \ \ docker-php-ext-configure gd --with-jpeg=/usr/include/ --with-webp=/usr/include --with-freetype=/usr/include/; \ + docker-php-ext-configure zip; \ docker-php-ext-install -j$(nproc) \ exif \ gd \ @@ -59,12 +61,18 @@ RUN set -eux; \ \ apk del .build-deps COPY --from=composer:latest /usr/bin/composer /usr/bin/composer -COPY docker/php/php.ini /usr/local/etc/php/php.ini -COPY docker/php/php-cli.ini /usr/local/etc/php/php-cli.ini +COPY docker/php/php.ini /usr/local/etc/php/php.tmp +COPY docker/php/php-cli.ini /usr/local/etc/php/php-cli.tmp + +ARG PHP_DATE_TIMEZONE=UTC +RUN sh -c "envsubst < /usr/local/etc/php/php.tmp > /usr/local/etc/php/php.ini" +RUN sh -c "envsubst < /usr/local/etc/php/php-cli.tmp > /usr/local/etc/php/php-cli.ini" # https://getcomposer.org/doc/03-cli.md#composer-allow-superuser ENV COMPOSER_ALLOW_SUPERUSER=1 +# install Symfony Flex globally to speed up download of Composer packages (parallelized prefetching) RUN set -eux; \ + composer global require "symfony/flex" --prefer-dist --no-progress --classmap-authoritative; \ composer clear-cache ENV PATH="${PATH}:/root/.composer/vendor/bin" @@ -93,6 +101,7 @@ RUN set -eux; \ composer dump-autoload --classmap-authoritative; \ APP_SECRET='' composer run-script post-install-cmd; \ chmod +x bin/console; sync; \ + bin/console assets:install --no-interaction; \ bin/console sylius:install:assets; \ bin/console sylius:theme:assets:install public @@ -100,6 +109,12 @@ VOLUME /srv/sylius/var VOLUME /srv/sylius/public/media +COPY docker/php/docker-healthcheck.sh /usr/local/bin/docker-healthcheck +RUN chmod +x /usr/local/bin/docker-healthcheck + +HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD ["docker-healthcheck"] + +COPY docker/php/sylius.conf /usr/local/etc/php-fpm.d/zzz-sylius.conf COPY docker/php/docker-entrypoint.sh /usr/local/bin/docker-entrypoint RUN chmod +x /usr/local/bin/docker-entrypoint diff --git a/README.md b/README.md index 2d97995530..d4a8196857 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,54 @@ $ php bin/console server:start $ open http://localhost:8000/ ``` +### For Docker installation + +Running the local environment with containers: + +```bash +$ docker-compose up -d +``` + +> You may check if php-fpm is ready executing the command: +> `docker-composer ps`. When it is ready, the State will be +> **Up (healthy)** + +Before open the sylius webpage, you should install and configure your +Shop. + +``` +$ docker-compose run php php bin/console sylius:install +``` + +> follow the installation instructions to setup the application +> database. Also you may add sample data. + +Write the command on terminal or just click on [localhost](http://localhost) +to open the Sylius Shop +``` +$ open http://localhost/ +``` + +or [localhost/admin](http://localhost/admin) to open the Sylius Backoffice +``` +$ open http://localhost/admin +``` + +If the pages not load the assets, just run the below commands: + +```bash +$ docker-compose run nodejs yarn install +$ docker-compose run nodejs yarn build +``` + +If you want to see any php information or run any command from +`bin/console`, you can run one of below commands: +```bash +$ docker-compose run php php -i +$ docker-compose run php php-fpm -tt +$ docker-compose run php php bin/console +``` + Troubleshooting --------------- diff --git a/docker-compose.yml b/docker-compose.yml index 980c582384..b7e1eeac08 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,15 +11,15 @@ services: # - quay.io/sylius/nodejs:latest # - quay.io/sylius/nginx:latest image: php:latest + healthcheck: + interval: 10s + timeout: 3s + retries: 3 + start_period: 30s depends_on: - mysql - environment: - - APP_ENV=dev - - APP_DEBUG=1 - - APP_SECRET=EDITME - - DATABASE_URL=mysql://sylius:nopassword@mysql/sylius - - MAILER_URL=smtp://mailhog:1025 - - PHP_DATE_TIMEZONE=${PHP_DATE_TIMEZONE:-UTC} + env_file: + - .env volumes: - .:/srv/sylius:rw,cached # if you develop on Linux, you may use a bind-mounted host directory instead @@ -28,13 +28,15 @@ services: # if you develop on Linux, you may use a bind-mounted host directory instead # - ./public/media:/srv/sylius/public/media:rw - public-media:/srv/sylius/public/media:rw + - sylius-vendor:/srv/sylius/vendor + - sylius-node_modules:/srv/sylius/node_modules mysql: image: percona:5.7 environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-nopassword} - - MYSQL_DATABASE=sylius - - MYSQL_USER=sylius + - MYSQL_DATABASE=sylius_${APP_ENV} + - MYSQL_USER=${MYSQL_ROOT_PASSWORD:-sylius} - MYSQL_PASSWORD=${MYSQL_PASSWORD:-nopassword} volumes: - mysql-data:/var/lib/mysql:rw @@ -62,6 +64,8 @@ services: volumes: - .:/srv/sylius:rw,cached - ./public:/srv/sylius/public:rw,delegated + - sylius-vendor:/srv/sylius/vendor + - sylius-node_modules:/srv/sylius/node_modules ports: - "35729:35729" @@ -99,3 +103,5 @@ services: volumes: mysql-data: public-media: + sylius-vendor: + sylius-node_modules: diff --git a/docker/php/docker-entrypoint.sh b/docker/php/docker-entrypoint.sh index 5fa0e75316..7134c82f9e 100755 --- a/docker/php/docker-entrypoint.sh +++ b/docker/php/docker-entrypoint.sh @@ -7,20 +7,14 @@ if [ "${1#-}" != "$1" ]; then fi if [ "$1" = 'php-fpm' ] || [ "$1" = 'bin/console' ]; then - mkdir -p var/cache var/log public/media - setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var public/media - setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var public/media + mkdir -p var/cache var/log public/media + setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var public/media + setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var public/media - if [ "$APP_ENV" != 'prod' ]; then - composer install --prefer-dist --no-progress --no-suggest --no-interaction - bin/console assets:install --no-interaction - bin/console sylius:theme:assets:install public --no-interaction - fi - - until bin/console doctrine:query:sql "select 1" >/dev/null 2>&1; do - (>&2 echo "Waiting for MySQL to be ready...") - sleep 1 - done + until bin/console doctrine:query:sql "select 1" >/dev/null 2>&1; do + (>&2 echo "Waiting for MySQL to be ready...") + sleep 1 + done bin/console doctrine:migrations:migrate --no-interaction fi diff --git a/docker/php/docker-healthcheck.sh b/docker/php/docker-healthcheck.sh new file mode 100644 index 0000000000..f121eda8e9 --- /dev/null +++ b/docker/php/docker-healthcheck.sh @@ -0,0 +1,12 @@ +#!/bin/sh +set -e + +export SCRIPT_NAME=/ping +export SCRIPT_FILENAME=/ping +export REQUEST_METHOD=GET + +if cgi-fcgi -bind -connect 127.0.0.1:9000; then + exit 0 +fi + +exit 1 diff --git a/docker/php/php-cli.ini b/docker/php/php-cli.ini index ef77c7330a..bf5735e6de 100644 --- a/docker/php/php-cli.ini +++ b/docker/php/php-cli.ini @@ -1,15 +1,19 @@ apc.enable_cli = 1 date.timezone = ${PHP_DATE_TIMEZONE} -opcache.enable_cli = 1 session.auto_start = Off short_open_tag = Off # http://symfony.com/doc/current/performance.html +opcache.enable=1 +opcache.enable_cli = 1 +opcache.fast_shutdown=1 opcache.interned_strings_buffer = 16 -opcache.max_accelerated_files = 20000 +opcache.max_accelerated_files = 524521 opcache.memory_consumption = 256 -realpath_cache_size = 4096K -realpath_cache_ttl = 600 +opcache.revalidate_freq=0 +opcache.validate_timestamps=0 +opcache.enable_file_override=0 +opcache.error_log=/proc/self/fd/2 memory_limit = 2G post_max_size = 6M diff --git a/docker/php/php.ini b/docker/php/php.ini index dd08e3bda0..d4e07025a6 100644 --- a/docker/php/php.ini +++ b/docker/php/php.ini @@ -1,13 +1,20 @@ apc.enable_cli = 1 date.timezone = ${PHP_DATE_TIMEZONE} -opcache.enable_cli = 1 session.auto_start = Off short_open_tag = Off # http://symfony.com/doc/current/performance.html +opcache.enable=1 +opcache.enable_cli = 1 +opcache.enable_file_override=0 +opcache.error_log=/proc/self/fd/2 +opcache.fast_shutdown=1 opcache.interned_strings_buffer = 16 -opcache.max_accelerated_files = 20000 +opcache.max_accelerated_files = 524521 opcache.memory_consumption = 256 +opcache.revalidate_freq=0 +opcache.validate_timestamps=0 + realpath_cache_size = 4096K realpath_cache_ttl = 600 diff --git a/docker/php/sylius.conf b/docker/php/sylius.conf new file mode 100644 index 0000000000..dc8007f734 --- /dev/null +++ b/docker/php/sylius.conf @@ -0,0 +1,28 @@ +[global] +error_log = /proc/self/fd/2 +log_buffering = yes +log_level = notice + +[www] +user = www-data +group = www-data +listen = 9000 +; check how to tuning you php-fpm +; https://tideways.com/profiler/blog/an-introduction-to-php-fpm-tuning +; +; | Setting | Value | +; | max_children | (Total RAM – Memory used for Linux, DB, etc.) / process size | +; | start_servers | Number of CPU cores x 4 | +; | min_spare_servers | Number of CPU cores x 2 | +; | max_spare_servers | Same as start_servers | + +pm = dynamic +pm.max_children = 16 +pm.start_servers = 16 +pm.min_spare_servers = 8 +pm.max_spare_servers = 16 +pm.max_requests = 200 +pm.status_path = /status + +ping.path = /ping +ping.response = pong