Skip to content

Commit

Permalink
Speed up PHP-fpm container on MacOS
Browse files Browse the repository at this point in the history
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 <[email protected]>
Co-authored-by: arti0090 <[email protected]>
  • Loading branch information
3 people committed Jun 3, 2021
1 parent 1a8f97a commit 4de48ed
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 48 deletions.
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -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 ###
Expand Down
23 changes: 19 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -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 \
Expand All @@ -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"

Expand Down Expand Up @@ -93,13 +101,20 @@ 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

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

Expand Down
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
---------------

Expand Down
39 changes: 15 additions & 24 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,16 @@ services:
build:
context: .
target: sylius_php
# Quay does not work, should be replaced in future with f.e. ghcr.io
# cache_from:
# - quay.io/sylius/php:latest
# - 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
Expand All @@ -28,13 +23,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
Expand All @@ -47,11 +44,6 @@ services:
build:
context: .
target: sylius_node
# Quay does not work, should be replaced in future with f.e. ghcr.io
# cache_from:
# - quay.io/sylius/php:latest
# - quay.io/sylius/nodejs:latest
# - quay.io/sylius/nginx:latest
image: node:latest
depends_on:
- php
Expand All @@ -62,6 +54,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"

Expand All @@ -70,11 +64,6 @@ services:
context: .
target: sylius_nginx
image: nginx:latest
# Quay does not work, should be replaced in future with f.e. ghcr.io
# cache_from:
# - quay.io/sylius/php:latest
# - quay.io/sylius/nodejs:latest
# - quay.io/sylius/nginx:latest
depends_on:
- php
- node # to ensure correct build order
Expand All @@ -99,3 +88,5 @@ services:
volumes:
mysql-data:
public-media:
sylius-vendor:
sylius-node_modules:
20 changes: 7 additions & 13 deletions docker/php/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions docker/php/docker-healthcheck.sh
Original file line number Diff line number Diff line change
@@ -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
12 changes: 8 additions & 4 deletions docker/php/php-cli.ini
Original file line number Diff line number Diff line change
@@ -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
Expand Down
11 changes: 9 additions & 2 deletions docker/php/php.ini
Original file line number Diff line number Diff line change
@@ -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

Expand Down
28 changes: 28 additions & 0 deletions docker/php/sylius.conf
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 4de48ed

Please sign in to comment.