From 680bbfc01fd00ac6c374391b0e07a66db10fb868 Mon Sep 17 00:00:00 2001 From: eliot lauger Date: Fri, 29 Nov 2024 18:14:41 +0100 Subject: [PATCH 1/6] feat: frankenphp implementation --- .env | 2 +- Dockerfile | 90 +++++-------------------- compose.yml | 62 ++--------------- composer.json | 1 + docker/frankenphp/Caddyfile | 62 +++++++++++++++++ docker/frankenphp/conf.d/app.dev.ini | 5 ++ docker/frankenphp/conf.d/app.ini | 13 ++++ docker/frankenphp/conf.d/app.prod.ini | 2 + docker/frankenphp/docker-entrypoint.dev | 40 +++++++++++ docker/frankenphp/worker.Caddyfile | 4 ++ 10 files changed, 152 insertions(+), 129 deletions(-) create mode 100644 docker/frankenphp/Caddyfile create mode 100644 docker/frankenphp/conf.d/app.dev.ini create mode 100644 docker/frankenphp/conf.d/app.ini create mode 100644 docker/frankenphp/conf.d/app.prod.ini create mode 100644 docker/frankenphp/docker-entrypoint.dev create mode 100644 docker/frankenphp/worker.Caddyfile diff --git a/.env b/.env index 71b55c7d..ba3e65b7 100644 --- a/.env +++ b/.env @@ -86,7 +86,7 @@ REDIS_DSN=redis://redis # # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" # DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7&charset=utf8mb4" -DATABASE_URL="mysql://db_user:db_password@db/db_name?serverVersion=8.0.38&charset=utf8mb4" +DATABASE_URL="mysql://db_user:db_password@db/db_name?serverVersion=8.0.40&charset=utf8mb4" #DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=13&charset=utf8" ###< doctrine/doctrine-bundle ### diff --git a/Dockerfile b/Dockerfile index 7959c70b..51202746 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,6 @@ ARG UID=1000 ARG GID=${UID} ARG PHP_VERSION=8.3.14 -ARG VARNISH_VERSION=7.6.1 ARG NGINX_VERSION=1.27.2 ARG MYSQL_VERSION=8.0.40 ARG MARIADB_VERSION=10.11.9 @@ -71,23 +70,11 @@ usermod -u ${UID} mysql groupmod -g ${GID} mysql EOF - -########### -# Varnish # -########### - -FROM varnish:${VARNISH_VERSION} AS varnish - -LABEL org.opencontainers.image.authors="ambroise@rezo-zero.com" - -COPY --link docker/varnish/default.vcl /etc/varnish/ - - ####### # PHP # ####### -FROM php:${PHP_VERSION}-fpm-bookworm AS php +FROM dunglas/frankenphp:php${PHP_VERSION}-bookworm AS php LABEL org.opencontainers.image.authors="ambroise@rezo-zero.com" @@ -101,12 +88,15 @@ ARG PHP_EXTENSION_REDIS_VERSION=6.1.0 SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"] ENV APP_FFMPEG_PATH=/usr/bin/ffmpeg +ENV APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime +ENV FRANKENPHP_CONFIG="worker ./public/index.php" RUN < /etc/sudoers.d/php install --verbose --owner php --group php --mode 0755 --directory /app # Php extensions -curl -sSLf https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions \ - --output /usr/local/bin/install-php-extensions -chmod +x /usr/local/bin/install-php-extensions install-php-extensions \ @composer-${COMPOSER_VERSION} \ fileinfo \ @@ -141,10 +128,18 @@ install-php-extensions \ xsl \ zip \ redis-${PHP_EXTENSION_REDIS_VERSION} + +setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/frankenphp +chown -R ${UID}:${GID} /data/caddy && chown -R ${UID}:${GID} /config/caddy EOF -WORKDIR /app +COPY --link docker/frankenphp/conf.d/app.ini ${PHP_INI_DIR}/conf.d/ +COPY --link --chmod=755 docker/frankenphp/docker-entrypoint.dev /usr/local/bin/docker-entrypoint +COPY --link docker/frankenphp/Caddyfile /etc/caddy/Caddyfile +ENTRYPOINT ["docker-entrypoint"] + +WORKDIR /app ############# # Php - Dev # @@ -152,18 +147,13 @@ WORKDIR /app FROM php AS php-dev -# Configs -RUN ln -sf ${PHP_INI_DIR}/php.ini-development ${PHP_INI_DIR}/php.ini -COPY --link docker/php/conf.d/app.dev.ini ${PHP_INI_DIR}/conf.d/zz-app.ini -COPY --link docker/php/fpm.d/www.dev.conf ${PHP_INI_DIR}-fpm.d/zz-www.conf +ENV APP_ENV=dev XDEBUG_MODE=off -# Entrypoint -COPY --link --chmod=755 docker/php/docker-entrypoint.dev /usr/local/bin/docker-entrypoint -ENTRYPOINT ["docker-entrypoint"] -CMD ["php-fpm"] +COPY --link docker/frankenphp/conf.d/app.dev.ini ${PHP_INI_DIR}/conf.d/ -USER php +CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile", "--watch" ] +USER php ############## # Cron - Dev # @@ -189,49 +179,3 @@ COPY --link --chmod=755 docker/cron/docker-cron-entrypoint.dev /usr/local/bin/do ENTRYPOINT ["docker-entrypoint"] USER root - - -######### -# Nginx # -######### - -FROM nginx:${NGINX_VERSION}-bookworm AS nginx - -LABEL org.opencontainers.image.authors="ambroise@rezo-zero.com" - -ARG UID -ARG GID - -SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"] - -RUN < /etc/sudoers.d/nginx - -# App -install --verbose --owner nginx --group nginx --mode 0755 --directory /app -EOF - -WORKDIR /app - -############### -# Nginx - Dev # -############### - -FROM nginx AS nginx-dev - -# Config -COPY --link docker/nginx/nginx.conf /etc/nginx/nginx.conf -COPY --link docker/nginx/conf.d/_gzip.conf /etc/nginx/conf.d/_gzip.conf -COPY --link docker/nginx/conf.d/_security.conf /etc/nginx/conf.d/_security.conf -COPY --link docker/nginx/conf.d/default.dev.conf /etc/nginx/conf.d/default.conf diff --git a/compose.yml b/compose.yml index 7b30b6d4..58be4197 100644 --- a/compose.yml +++ b/compose.yml @@ -86,8 +86,6 @@ services: app: &app_template hostname: app - # Need to pass all vars to docker env for Crontab and supervisor scripts - env_file: "./.env.local" build: target: php-dev args: @@ -98,12 +96,17 @@ services: - redis volumes: - ./:/app:cached + - ./docker/frankenphp/Caddyfile:/etc/caddy/Caddyfile:ro + - ./docker/frankenphp/conf.d/app.dev.ini:/usr/local/etc/php/conf.d/app.dev.ini:ro + - caddy_data:/data + - caddy_config:/config networks: - default environment: TRUSTED_PROXIES: ${TRUSTED_PROXIES} UID: ${UID} DEFAULT_GATEWAY: ${DEFAULT_GATEWAY} + DATABASE_URL: ${DATABASE_URL} worker: <<: *app_template @@ -121,59 +124,6 @@ services: hostname: app-cron restart: unless-stopped - nginx: - build: - target: nginx-dev - args: - UID: ${UID:-1000} - depends_on: - - app - links: - - app:app - volumes: - # Need to share all app files for relative symlink to work in development - - ./:/app - networks: - - default - - frontproxynet - labels: - - "traefik.enable=true" - - "traefik.http.services.${APP_NAMESPACE}.loadbalancer.server.scheme=http" - - "traefik.http.services.${APP_NAMESPACE}.loadbalancer.server.port=80" - - "traefik.http.services.${APP_NAMESPACE}.loadbalancer.passhostheader=true" - # Listen HTTP - - "traefik.http.routers.${APP_NAMESPACE}.entrypoints=http" - - "traefik.http.routers.${APP_NAMESPACE}.rule=Host(${HOSTNAME})" - - "traefik.http.routers.${APP_NAMESPACE}.service=${APP_NAMESPACE}" - # Listen HTTPS - - "traefik.http.routers.${APP_NAMESPACE}_secure.entrypoints=https" - - "traefik.http.routers.${APP_NAMESPACE}_secure.rule=Host(${HOSTNAME})" - - "traefik.http.routers.${APP_NAMESPACE}_secure.tls=true" - - "traefik.http.routers.${APP_NAMESPACE}_secure.service=${APP_NAMESPACE}" - - varnish: - build: - target: varnish - networks: - - default - - frontproxynet - depends_on: - - nginx - labels: - - "traefik.enable=true" - - "traefik.http.services.${APP_NAMESPACE}_varnish.loadbalancer.server.scheme=http" - - "traefik.http.services.${APP_NAMESPACE}_varnish.loadbalancer.server.port=80" - - "traefik.http.services.${APP_NAMESPACE}_varnish.loadbalancer.passhostheader=true" - # Listen HTTP - - "traefik.http.routers.${APP_NAMESPACE}_varnish.entrypoints=http" - - "traefik.http.routers.${APP_NAMESPACE}_varnish.rule=Host(${HOSTNAME_VARNISH})" - - "traefik.http.routers.${APP_NAMESPACE}_varnish.service=${APP_NAMESPACE}_varnish" - # Listen HTTPS - - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.entrypoints=https" - - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.rule=Host(${HOSTNAME_VARNISH})" - - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.tls=true" - - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.service=${APP_NAMESPACE}_varnish" - mailer: hostname: mailer image: axllent/mailpit @@ -204,3 +154,5 @@ networks: volumes: redis: solr_data: + caddy_data: + caddy_config: diff --git a/composer.json b/composer.json index b51b4012..a8c6b0c0 100644 --- a/composer.json +++ b/composer.json @@ -73,6 +73,7 @@ "roadiz/nodetype-contracts": "~1.1.2", "rollerworks/password-common-list": "^0.2.0", "rollerworks/password-strength-bundle": "^2.2", + "runtime/frankenphp-symfony": "^0.2.0", "scheb/2fa-backup-code": "^7.5", "scheb/2fa-bundle": "^7.5", "scheb/2fa-google-authenticator": "^7.5", diff --git a/docker/frankenphp/Caddyfile b/docker/frankenphp/Caddyfile new file mode 100644 index 00000000..6ec82e19 --- /dev/null +++ b/docker/frankenphp/Caddyfile @@ -0,0 +1,62 @@ +{ + {$CADDY_GLOBAL_OPTIONS} + + frankenphp { + {$FRANKENPHP_CONFIG} + } +} + +{$CADDY_EXTRA_CONFIG} + +{$SERVER_NAME:localhost} { + log { + # Redact the authorization query parameter that can be set by Mercure + format filter { + request>uri query { + replace authorization REDACTED + } + } + } + + root * /app/public + encode zstd br gzip + + mercure { + # Transport to use (default to Bolt) + transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db} + # Publisher JWT key + publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG} + # Subscriber JWT key + subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG} + # Allow anonymous subscribers (double-check that it's what you want) + anonymous + # Enable the subscription API (double-check that it's what you want) + subscriptions + # Extra directives + {$MERCURE_EXTRA_DIRECTIVES} + } + + vulcain + + # Add links to the API docs and to the Mercure Hub if not set explicitly (e.g. the PWA) + header ?Link `; rel="http://www.w3.org/ns/hydra/core#apiDocumentation", ; rel="mercure"` + # Disable Topics tracking if not enabled explicitly: https://github.com/jkarlin/topics + header ?Permissions-Policy "browsing-topics=()" + + # Matches requests for HTML documents, for static files and for Next.js files, + # except for known API paths and paths with extensions handled by API Platform + @pwa expression `( + header({'Accept': '*text/html*'}) + && !path( + '/docs*', '/graphql*', '/bundles*', '/contexts*', '/_profiler*', '/_wdt*', + '*.json*', '*.html', '*.csv', '*.yml', '*.yaml', '*.xml' + ) + ) + || path('/favicon.ico', '/manifest.json', '/robots.txt', '/sitemap*', '/_next*', '/__next*') + || query({'_rsc': '*'})` + + # Comment the following line if you don't want Next.js to catch requests for HTML documents. + # In this case, they will be handled by the PHP app. + + php_server +} diff --git a/docker/frankenphp/conf.d/app.dev.ini b/docker/frankenphp/conf.d/app.dev.ini new file mode 100644 index 00000000..52bcb297 --- /dev/null +++ b/docker/frankenphp/conf.d/app.dev.ini @@ -0,0 +1,5 @@ +; See https://docs.docker.com/desktop/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host +; See https://github.com/docker/for-linux/issues/264 +; The `client_host` below may optionally be replaced with `discover_client_host=yes` +; Add `start_with_request=yes` to start debug session on each request +xdebug.client_host = xdebug://gateway diff --git a/docker/frankenphp/conf.d/app.ini b/docker/frankenphp/conf.d/app.ini new file mode 100644 index 00000000..79a17dd8 --- /dev/null +++ b/docker/frankenphp/conf.d/app.ini @@ -0,0 +1,13 @@ +expose_php = 0 +date.timezone = UTC +apc.enable_cli = 1 +session.use_strict_mode = 1 +zend.detect_unicode = 0 + +; https://symfony.com/doc/current/performance.html +realpath_cache_size = 4096K +realpath_cache_ttl = 600 +opcache.interned_strings_buffer = 16 +opcache.max_accelerated_files = 20000 +opcache.memory_consumption = 256 +opcache.enable_file_override = 1 diff --git a/docker/frankenphp/conf.d/app.prod.ini b/docker/frankenphp/conf.d/app.prod.ini new file mode 100644 index 00000000..3bcaa71e --- /dev/null +++ b/docker/frankenphp/conf.d/app.prod.ini @@ -0,0 +1,2 @@ +opcache.preload_user = root +opcache.preload = /app/config/preload.php diff --git a/docker/frankenphp/docker-entrypoint.dev b/docker/frankenphp/docker-entrypoint.dev new file mode 100644 index 00000000..35d063a4 --- /dev/null +++ b/docker/frankenphp/docker-entrypoint.dev @@ -0,0 +1,40 @@ +#!/bin/sh +set -e + +#if [ "$1" = 'frankenphp' ] || [ "$1" = 'php' ] || [ "$1" = 'bin/console' ]; then +# if [ -z "$(ls -A 'vendor/' 2>/dev/null)" ]; then +# composer install --prefer-dist --no-progress --no-interaction +# fi +# +# if grep -q ^DATABASE_URL= .env; then +# echo "Waiting for database to be ready..." +# ATTEMPTS_LEFT_TO_REACH_DATABASE=60 +# until [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ] || DATABASE_ERROR=$(php bin/console dbal:run-sql -q "SELECT 1" 2>&1); do +# if [ $? -eq 255 ]; then +# # If the Doctrine command exits with 255, an unrecoverable error occurred +# ATTEMPTS_LEFT_TO_REACH_DATABASE=0 +# break +# fi +# sleep 1 +# ATTEMPTS_LEFT_TO_REACH_DATABASE=$((ATTEMPTS_LEFT_TO_REACH_DATABASE - 1)) +# echo "Still waiting for database to be ready... Or maybe the database is not reachable. $ATTEMPTS_LEFT_TO_REACH_DATABASE attempts left." +# done +# +# if [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ]; then +# echo "The database is not up or not reachable:" +# echo "$DATABASE_ERROR" +# exit 1 +# else +# echo "The database is now ready and reachable" +# fi +# +# if [ "$( find ./migrations -iname '*.php' -print -quit )" ]; then +# php bin/console doctrine:migrations:migrate --no-interaction --all-or-nothing +# fi +# fi +# +# setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var +# setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var +#fi + +exec docker-php-entrypoint "$@" diff --git a/docker/frankenphp/worker.Caddyfile b/docker/frankenphp/worker.Caddyfile new file mode 100644 index 00000000..d384ae4c --- /dev/null +++ b/docker/frankenphp/worker.Caddyfile @@ -0,0 +1,4 @@ +worker { + file ./public/index.php + env APP_RUNTIME Runtime\FrankenPhpSymfony\Runtime +} From 5988cffaeb4c6294c85183aded940dcc11c3203e Mon Sep 17 00:00:00 2001 From: eliot lauger Date: Mon, 2 Dec 2024 13:44:03 +0100 Subject: [PATCH 2/6] feat: add user root for run --- .env | 5 ++++- Dockerfile | 9 ++++++--- .../environments/Local Dev - FrankenPHP.bru | 8 ++++++++ compose.yml | 2 ++ 4 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 bruno/Roadiz development app/environments/Local Dev - FrankenPHP.bru diff --git a/.env b/.env index ba3e65b7..78603f76 100644 --- a/.env +++ b/.env @@ -29,7 +29,7 @@ SOLR_PORT=8983 SOLR_CORE_NAME=roadiz PUBLIC_APP_PORT=8681 -PUBLIC_VARNISH_PORT=8682 +PUBLIC_APP_HTTPS_PORT=4431 PUBLIC_PMA_PORT=8686 PUBLIC_SOLR_PORT=8684 PUBLIC_MAILER_PORT=8625 @@ -116,3 +116,6 @@ SCALEWAY_STORAGE_REGION= # postgresql+advisory://db_user:db_password@localhost/db_name LOCK_DSN=flock ###< symfony/lock ### + +MERCURE_PUBLISHER_JWT_KEY=${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!} +MERCURE_SUBSCRIBER_JWT_KEY=${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!} diff --git a/Dockerfile b/Dockerfile index 51202746..2de3aee1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -81,6 +81,8 @@ LABEL org.opencontainers.image.authors="ambroise@rezo-zero.com" ARG UID ARG GID +USER root + ARG COMPOSER_VERSION=2.8.1 ARG PHP_EXTENSION_INSTALLER_VERSION=2.6.0 ARG PHP_EXTENSION_REDIS_VERSION=6.1.0 @@ -129,8 +131,6 @@ install-php-extensions \ zip \ redis-${PHP_EXTENSION_REDIS_VERSION} -setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/frankenphp -chown -R ${UID}:${GID} /data/caddy && chown -R ${UID}:${GID} /config/caddy EOF COPY --link docker/frankenphp/conf.d/app.ini ${PHP_INI_DIR}/conf.d/ @@ -148,12 +148,15 @@ WORKDIR /app FROM php AS php-dev ENV APP_ENV=dev XDEBUG_MODE=off +USER root + + +RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" COPY --link docker/frankenphp/conf.d/app.dev.ini ${PHP_INI_DIR}/conf.d/ CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile", "--watch" ] -USER php ############## # Cron - Dev # diff --git a/bruno/Roadiz development app/environments/Local Dev - FrankenPHP.bru b/bruno/Roadiz development app/environments/Local Dev - FrankenPHP.bru new file mode 100644 index 00000000..ad9841c3 --- /dev/null +++ b/bruno/Roadiz development app/environments/Local Dev - FrankenPHP.bru @@ -0,0 +1,8 @@ +vars { + baseUrl: https://localhost:4431 +} +vars:secret [ + access_token, + username, + password +] diff --git a/compose.yml b/compose.yml index 58be4197..5fe6bfdb 100644 --- a/compose.yml +++ b/compose.yml @@ -107,6 +107,8 @@ services: UID: ${UID} DEFAULT_GATEWAY: ${DEFAULT_GATEWAY} DATABASE_URL: ${DATABASE_URL} + MERCURE_PUBLISHER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!} + MERCURE_SUBSCRIBER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!} worker: <<: *app_template From 91ee56fb63f32da4437b8480885916bb5b8241b5 Mon Sep 17 00:00:00 2001 From: eliot lauger Date: Mon, 2 Dec 2024 17:43:18 +0100 Subject: [PATCH 3/6] feat: clean code, leave the choice in use frankenphp --- .env | 4 +- README.md | 10 ++++ compose.override.yml.dist | 49 +++++++++++++++++-- compose.yml | 64 +++++++++++++++++++++---- composer.json | 2 +- docker/frankenphp/conf.d/app.prod.ini | 2 - docker/frankenphp/docker-entrypoint.dev | 36 -------------- 7 files changed, 113 insertions(+), 54 deletions(-) delete mode 100644 docker/frankenphp/conf.d/app.prod.ini diff --git a/.env b/.env index 78603f76..58ef6d26 100644 --- a/.env +++ b/.env @@ -29,6 +29,7 @@ SOLR_PORT=8983 SOLR_CORE_NAME=roadiz PUBLIC_APP_PORT=8681 +PUBLIC_VARNISH_PORT=8682 PUBLIC_APP_HTTPS_PORT=4431 PUBLIC_PMA_PORT=8686 PUBLIC_SOLR_PORT=8684 @@ -116,6 +117,3 @@ SCALEWAY_STORAGE_REGION= # postgresql+advisory://db_user:db_password@localhost/db_name LOCK_DSN=flock ###< symfony/lock ### - -MERCURE_PUBLISHER_JWT_KEY=${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!} -MERCURE_SUBSCRIBER_JWT_KEY=${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!} diff --git a/README.md b/README.md index ada7efab..064d2954 100644 --- a/README.md +++ b/README.md @@ -63,3 +63,13 @@ Roadiz development env uses: https://github.com/symplify/monorepo-builder - `vendor/bin/monorepo-builder merge`: Makes sure all your packages deps are in development repository and - `vendor/bin/monorepo-builder validate`: Make sure all your packages use the same version - `vendor/bin/monorepo-builder release patch --dry-run`: List all steps to do when release a new tag (do not actually perform this when using GitFlow) + + +### Use Frankenphp + +Roadiz can be run with frankenphp for use it you need to override services `app`, `nginx` and `varnish` in `compose.override.yml` + +You need to use the target `php-dev-franken` present in the `Dockerfile`. +We use `dunglas/frankenphp` image with the tag of your version of php and the tag bookworm + +If you use frankenphp you can remove `docker/varnish` and `docker/nginx` folders diff --git a/compose.override.yml.dist b/compose.override.yml.dist index ad95d381..922243a0 100644 --- a/compose.override.yml.dist +++ b/compose.override.yml.dist @@ -8,10 +8,53 @@ services: solr: ports: - "${PUBLIC_SOLR_PORT}:8983/tcp" - nginx: - ports: - - ${PUBLIC_APP_PORT}:80/tcp + + # Override app service if you use frankenphp +# app: +# build: +# target: php-dev-franken +# args: +# UID: ${UID:-1000} +# ports: +# - ${PUBLIC_APP_PORT}:80/tcp +# # HTTPS +# - target: 443 +# published: ${PUBLIC_APP_HTTPS_PORT:-443} +# protocol: tcp +# tty: true +# volumes: +# - ./:/app:cached +# - ./docker/frankenphp/Caddyfile:/etc/caddy/Caddyfile:ro +# - ./docker/frankenphp/conf.d/app.dev.ini:/usr/local/etc/php/conf.d/app.dev.ini:ro +# - caddy_data:/data +# - caddy_config:/config +# environment: +# PHP_CS_FIXER_IGNORE_ENV: 1 +# TRUSTED_PROXIES: ${TRUSTED_PROXIES} +# UID: ${UID} +# DEFAULT_GATEWAY: ${DEFAULT_GATEWAY} +# DATABASE_URL: ${DATABASE_URL} + + # Uncomment next line if you use Frankenphp +# varnish: +# entrypoint: ["echo", "Service varnish disabled"] + +# nginx: + # Uncomment ports if you use nginx +# ports: +# - ${PUBLIC_APP_PORT}:80/tcp + # Comment ports and uncomment next line if you use Frankenphp +# entrypoint: ["echo", "Service nginx disabled"] + + mailer: ports: - ${PUBLIC_MAILER_PORT}:8025/tcp - ${SMTP_MAILER_PORT}:1025/tcp + +volumes: + redis: + solr_data: + # Declare caddy_data and caddy_config volumes if you use Frankenphp +# caddy_data: +# caddy_config: diff --git a/compose.yml b/compose.yml index 0524bd7f..66d5076c 100644 --- a/compose.yml +++ b/compose.yml @@ -86,6 +86,8 @@ services: app: &app_template hostname: app + # Need to pass all vars to docker env for Crontab and supervisor scripts + env_file: "./.env.local" build: target: php-dev args: @@ -96,10 +98,6 @@ services: - redis volumes: - ./:/app:cached - - ./docker/frankenphp/Caddyfile:/etc/caddy/Caddyfile:ro - - ./docker/frankenphp/conf.d/app.dev.ini:/usr/local/etc/php/conf.d/app.dev.ini:ro - - caddy_data:/data - - caddy_config:/config networks: - default environment: @@ -107,9 +105,6 @@ services: TRUSTED_PROXIES: ${TRUSTED_PROXIES} UID: ${UID} DEFAULT_GATEWAY: ${DEFAULT_GATEWAY} - DATABASE_URL: ${DATABASE_URL} - MERCURE_PUBLISHER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!} - MERCURE_SUBSCRIBER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!} worker: <<: *app_template @@ -127,6 +122,59 @@ services: hostname: app-cron restart: unless-stopped + nginx: + build: + target: nginx-dev + args: + UID: ${UID:-1000} + depends_on: + - app + links: + - app:app + volumes: + # Need to share all app files for relative symlink to work in development + - ./:/app + networks: + - default + - frontproxynet + labels: + - "traefik.enable=true" + - "traefik.http.services.${APP_NAMESPACE}.loadbalancer.server.scheme=http" + - "traefik.http.services.${APP_NAMESPACE}.loadbalancer.server.port=80" + - "traefik.http.services.${APP_NAMESPACE}.loadbalancer.passhostheader=true" + # Listen HTTP + - "traefik.http.routers.${APP_NAMESPACE}.entrypoints=http" + - "traefik.http.routers.${APP_NAMESPACE}.rule=Host(${HOSTNAME})" + - "traefik.http.routers.${APP_NAMESPACE}.service=${APP_NAMESPACE}" + # Listen HTTPS + - "traefik.http.routers.${APP_NAMESPACE}_secure.entrypoints=https" + - "traefik.http.routers.${APP_NAMESPACE}_secure.rule=Host(${HOSTNAME})" + - "traefik.http.routers.${APP_NAMESPACE}_secure.tls=true" + - "traefik.http.routers.${APP_NAMESPACE}_secure.service=${APP_NAMESPACE}" + + varnish: + build: + target: varnish + networks: + - default + - frontproxynet + depends_on: + - nginx + labels: + - "traefik.enable=true" + - "traefik.http.services.${APP_NAMESPACE}_varnish.loadbalancer.server.scheme=http" + - "traefik.http.services.${APP_NAMESPACE}_varnish.loadbalancer.server.port=80" + - "traefik.http.services.${APP_NAMESPACE}_varnish.loadbalancer.passhostheader=true" + # Listen HTTP + - "traefik.http.routers.${APP_NAMESPACE}_varnish.entrypoints=http" + - "traefik.http.routers.${APP_NAMESPACE}_varnish.rule=Host(${HOSTNAME_VARNISH})" + - "traefik.http.routers.${APP_NAMESPACE}_varnish.service=${APP_NAMESPACE}_varnish" + # Listen HTTPS + - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.entrypoints=https" + - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.rule=Host(${HOSTNAME_VARNISH})" + - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.tls=true" + - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.service=${APP_NAMESPACE}_varnish" + mailer: hostname: mailer image: axllent/mailpit @@ -157,5 +205,3 @@ networks: volumes: redis: solr_data: - caddy_data: - caddy_config: diff --git a/composer.json b/composer.json index 1465231e..4fa0005e 100644 --- a/composer.json +++ b/composer.json @@ -71,7 +71,6 @@ "roadiz/nodetype-contracts": "~1.1.2", "rollerworks/password-common-list": "^0.2.0", "rollerworks/password-strength-bundle": "^2.2", - "runtime/frankenphp-symfony": "^0.2.0", "scheb/2fa-backup-code": "^7.5", "scheb/2fa-bundle": "^7.5", "scheb/2fa-google-authenticator": "^7.5", @@ -149,6 +148,7 @@ "phpstan/phpstan-symfony": "^1.1.8", "phpunit/phpunit": "^9.5", "rector/rector": "^0.14.5", + "runtime/frankenphp-symfony": "^0.2.0", "symfony/browser-kit": "6.4.*", "symfony/css-selector": "6.4.*", "symfony/debug-bundle": "6.4.*", diff --git a/docker/frankenphp/conf.d/app.prod.ini b/docker/frankenphp/conf.d/app.prod.ini deleted file mode 100644 index 3bcaa71e..00000000 --- a/docker/frankenphp/conf.d/app.prod.ini +++ /dev/null @@ -1,2 +0,0 @@ -opcache.preload_user = root -opcache.preload = /app/config/preload.php diff --git a/docker/frankenphp/docker-entrypoint.dev b/docker/frankenphp/docker-entrypoint.dev index 35d063a4..692e4e59 100644 --- a/docker/frankenphp/docker-entrypoint.dev +++ b/docker/frankenphp/docker-entrypoint.dev @@ -1,40 +1,4 @@ #!/bin/sh set -e -#if [ "$1" = 'frankenphp' ] || [ "$1" = 'php' ] || [ "$1" = 'bin/console' ]; then -# if [ -z "$(ls -A 'vendor/' 2>/dev/null)" ]; then -# composer install --prefer-dist --no-progress --no-interaction -# fi -# -# if grep -q ^DATABASE_URL= .env; then -# echo "Waiting for database to be ready..." -# ATTEMPTS_LEFT_TO_REACH_DATABASE=60 -# until [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ] || DATABASE_ERROR=$(php bin/console dbal:run-sql -q "SELECT 1" 2>&1); do -# if [ $? -eq 255 ]; then -# # If the Doctrine command exits with 255, an unrecoverable error occurred -# ATTEMPTS_LEFT_TO_REACH_DATABASE=0 -# break -# fi -# sleep 1 -# ATTEMPTS_LEFT_TO_REACH_DATABASE=$((ATTEMPTS_LEFT_TO_REACH_DATABASE - 1)) -# echo "Still waiting for database to be ready... Or maybe the database is not reachable. $ATTEMPTS_LEFT_TO_REACH_DATABASE attempts left." -# done -# -# if [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ]; then -# echo "The database is not up or not reachable:" -# echo "$DATABASE_ERROR" -# exit 1 -# else -# echo "The database is now ready and reachable" -# fi -# -# if [ "$( find ./migrations -iname '*.php' -print -quit )" ]; then -# php bin/console doctrine:migrations:migrate --no-interaction --all-or-nothing -# fi -# fi -# -# setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var -# setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var -#fi - exec docker-php-entrypoint "$@" From c8f2a9224a5fa9672929a53a5ebe5836a8e9a0d9 Mon Sep 17 00:00:00 2001 From: eliot lauger Date: Tue, 3 Dec 2024 09:45:46 +0100 Subject: [PATCH 4/6] chore: fix threads --- Dockerfile | 2 +- README.md | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7c788c48..233445ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -149,7 +149,7 @@ WORKDIR /app FROM dunglas/frankenphp:php${PHP_VERSION}-bookworm AS php-franken -LABEL org.opencontainers.image.authors="ambroise@rezo-zero.com" +LABEL org.opencontainers.image.authors="ambroise@rezo-zero.com, eliot@rezo-zero.com" ARG UID ARG GID diff --git a/README.md b/README.md index 064d2954..9d1a3be1 100644 --- a/README.md +++ b/README.md @@ -67,9 +67,10 @@ Roadiz development env uses: https://github.com/symplify/monorepo-builder ### Use Frankenphp -Roadiz can be run with frankenphp for use it you need to override services `app`, `nginx` and `varnish` in `compose.override.yml` +Roadiz can be run with [*frankenphp*](https://frankenphp.dev) instead of PHP-FPM + Nginx. If you want to give it a try, override services `app`, `nginx` and `varnish` in your `compose.override.yml` -You need to use the target `php-dev-franken` present in the `Dockerfile`. -We use `dunglas/frankenphp` image with the tag of your version of php and the tag bookworm +Use the target `php-dev-franken` instead of `php-dev`. -If you use frankenphp you can remove `docker/varnish` and `docker/nginx` folders +We use [`dunglas/frankenphp`](https://hub.docker.com/r/dunglas/frankenphp) image with the tag of your PHP version and Debian Bookworm. + +Using frankenphp allows you to remove `docker/varnish` and `docker/nginx` folders in your project. From 328606ec67d93d9d7a8eebc0234f14f454967045 Mon Sep 17 00:00:00 2001 From: eliot lauger Date: Wed, 4 Dec 2024 13:38:16 +0100 Subject: [PATCH 5/6] feat: Use port 80 with HTTP for run app --- compose.override.yml.dist | 7 ++----- docker/frankenphp/Caddyfile | 4 ++++ docker/frankenphp/conf.d/app.ini | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compose.override.yml.dist b/compose.override.yml.dist index 922243a0..e39540bc 100644 --- a/compose.override.yml.dist +++ b/compose.override.yml.dist @@ -17,13 +17,9 @@ services: # UID: ${UID:-1000} # ports: # - ${PUBLIC_APP_PORT}:80/tcp -# # HTTPS -# - target: 443 -# published: ${PUBLIC_APP_HTTPS_PORT:-443} -# protocol: tcp # tty: true # volumes: -# - ./:/app:cached +# - ./:/app # - ./docker/frankenphp/Caddyfile:/etc/caddy/Caddyfile:ro # - ./docker/frankenphp/conf.d/app.dev.ini:/usr/local/etc/php/conf.d/app.dev.ini:ro # - caddy_data:/data @@ -34,6 +30,7 @@ services: # UID: ${UID} # DEFAULT_GATEWAY: ${DEFAULT_GATEWAY} # DATABASE_URL: ${DATABASE_URL} +# SERVER_NAME: :80 # Uncomment next line if you use Frankenphp # varnish: diff --git a/docker/frankenphp/Caddyfile b/docker/frankenphp/Caddyfile index cecc253c..5789364c 100644 --- a/docker/frankenphp/Caddyfile +++ b/docker/frankenphp/Caddyfile @@ -1,6 +1,10 @@ { {$CADDY_GLOBAL_OPTIONS} + servers { + trusted_proxies static 0.0.0.0/0 + } + frankenphp { {$FRANKENPHP_CONFIG} } diff --git a/docker/frankenphp/conf.d/app.ini b/docker/frankenphp/conf.d/app.ini index 79a17dd8..ab11e97c 100644 --- a/docker/frankenphp/conf.d/app.ini +++ b/docker/frankenphp/conf.d/app.ini @@ -1,5 +1,5 @@ expose_php = 0 -date.timezone = UTC +date.timezone = Europe/Paris apc.enable_cli = 1 session.use_strict_mode = 1 zend.detect_unicode = 0 From 0b643c9e47eec23c2789d7c40cb996e5f3a02771 Mon Sep 17 00:00:00 2001 From: eliot lauger Date: Wed, 4 Dec 2024 14:50:43 +0100 Subject: [PATCH 6/6] feat: Update ini file and delete useless environment --- .../environments/Local Dev - FrankenPHP.bru | 8 ----- docker/frankenphp/conf.d/app.dev.ini | 29 +++++++++++++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) delete mode 100644 bruno/Roadiz development app/environments/Local Dev - FrankenPHP.bru diff --git a/bruno/Roadiz development app/environments/Local Dev - FrankenPHP.bru b/bruno/Roadiz development app/environments/Local Dev - FrankenPHP.bru deleted file mode 100644 index ad9841c3..00000000 --- a/bruno/Roadiz development app/environments/Local Dev - FrankenPHP.bru +++ /dev/null @@ -1,8 +0,0 @@ -vars { - baseUrl: https://localhost:4431 -} -vars:secret [ - access_token, - username, - password -] diff --git a/docker/frankenphp/conf.d/app.dev.ini b/docker/frankenphp/conf.d/app.dev.ini index 52bcb297..d13f7cad 100644 --- a/docker/frankenphp/conf.d/app.dev.ini +++ b/docker/frankenphp/conf.d/app.dev.ini @@ -3,3 +3,32 @@ ; The `client_host` below may optionally be replaced with `discover_client_host=yes` ; Add `start_with_request=yes` to start debug session on each request xdebug.client_host = xdebug://gateway + +date.timezone = Europe/Paris +session.auto_start = Off +; Session ID cannot be passed through URLs +session.use_only_cookies = On +; Uses a secure connection (HTTPS) if possible +; session.cookie_secure = On +; Do not accept uninitialized session ID +session.use_strict_mode = On +; Do not make session cookie available to JS +session.cookie_httponly = On +short_open_tag = Off + +; http://symfony.com/doc/current/performance.html +; Configure OPcache for Maximum Performance +opcache.revalidate_freq = 0 +opcache.memory_consumption = 256 +opcache.max_accelerated_files = 20000 +opcache.interned_strings_buffer = 16 + +; Configure the PHP realpath Cache +realpath_cache_size = 4096K +realpath_cache_ttl = 600 + +memory_limit = 512M +post_max_size = 128M +upload_max_filesize = 64M +expose_php = On +display_errors = On