diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..e3c86e1 --- /dev/null +++ b/Caddyfile @@ -0,0 +1,36 @@ +{ + log { + level {$CADDY_SERVER_LOG_LEVEL:info} + output stderr + format json { + # This maps the keys to what Google Cloud expects + level_key severity + message_key message + time_format rfc3339 + } + } + + frankenphp { + {$FRANKENPHP_CONFIG} + } +} + +:80 { + root public/ + log { + level {$CADDY_SERVER_HTTP_LOG_LEVEL:info} + output stderr + format json { + # This maps the keys to what Google Cloud expects + level_key severity + message_key message + time_format rfc3339 + } + } + + encode zstd br gzip + {$CADDY_SERVER_EXTRA_DIRECTIVES} + + php_server + file_server +} diff --git a/Makefile b/Makefile index c0e7b54..0c96b14 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,17 @@ .PHONY: test-8.3 test-8.4 -test-8.3: - docker build -f ./test/demo/Dockerfile --build-context 'php=docker-image://trucksnl/frankenphp:1.11-php8.3-alpine' -t frankenphp:8.3 ./test/demo/ - docker run --rm --name frankenphp-test -p 8000:80 -d frankenphp:8.3 +build-base8.3: + docker build -f ./alpine.Dockerfile --build-context 'php=docker-image://dunglas/frankenphp:1.11-php8.3-alpine' -t local/frankenphp:1.11-php8.3-alpine --load ./ + +build8.3: build-base8.3 + docker build -f ./test/demo/Dockerfile --build-context 'php=docker-image://local/frankenphp:1.11-php8.3-alpine' -t local/frankenphp:test-8.3 --load ./test/demo/ + +start8.3: build8.3 + docker stop frankenphp-test || true + docker rm frankenphp-test || true + docker run --name frankenphp-test --tty -p 8000:80 -d -e CADDY_SERVER_HTTP_LOG_LEVEL=info local/frankenphp:test-8.3 + +test-8.3: start8.3 sleep 1 curl localhost:8000 docker stop frankenphp-test || true diff --git a/alpine.Dockerfile b/alpine.Dockerfile index 07433ad..9bfc59c 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -1,9 +1,6 @@ # syntax=docker/dockerfile:1 -FROM php -ENV FRANKENPHP_CONFIG="worker /app/public/index.php" -# We put our apps behind an HTTPS load balancer, so all internal traffic is HTTP port 80 -ENV SERVER_NAME=:80 +FROM php RUN apk add --no-cache \ acl \ @@ -24,8 +21,31 @@ RUN install-php-extensions \ sysvsem \ zip +# https://symfony.com/doc/current/performance.html#configure-the-php-realpath-cache +ENV PHP_REALPATH_CACHE_SIZE="4096K" +ENV PHP_REALPATH_CACHE_TTL=600 + +# https://symfony.com/doc/current/performance.html#configure-opcache-for-maximum-performance +ENV PHP_OPCACHE_MEMORY_CONSUMPTION=256 +ENV PHP_OPCACHE_MAX_ACCELERATED_FILES=32531 +ENV PHP_OPCACHE_MAX_WASTED_PERCENTAGE=5 + +# https://symfony.com/doc/current/performance.html#don-t-check-php-files-timestamps +# Set to "1" in Dev, "0" in Prod +ENV PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 + +ENV PHP_OPCACHE_ENABLE=1 +ENV PHP_OPCACHE_ENABLE_CLI=1 +ENV PHP_OPCACHE_INTERNED_STRINGS_BUFFER=16 +ENV PHP_OPCACHE_PRELOAD="/app/config/preload.php" +ENV PHP_OPCACHE_PRELOAD_USER="www-data" + +COPY ./core.ini ./opcache.ini ./realpath.ini /usr/local/etc/php/conf.d/ +COPY ./Caddyfile /etc/frankenphp/Caddyfile + RUN mkdir -p /root/.ssh/ /app/var/log/ /app/var/cache/ \ && ssh-keyscan bitbucket.org > /root/.ssh/known_hosts -COPY --from=composer/composer:2-bin /composer /usr/local/bin/composer -ENV COMPOSER_ALLOW_SUPERUSER=1 +ENV FRANKENPHP_CONFIG="worker /app/public/index.php" +# We put our apps behind an HTTPS load balancer, so all internal traffic is HTTP port 80 +ENV SERVER_NAME=:80 diff --git a/core.ini b/core.ini new file mode 100644 index 0000000..fce7e46 --- /dev/null +++ b/core.ini @@ -0,0 +1 @@ +expose_php=0 \ No newline at end of file diff --git a/opcache.ini b/opcache.ini new file mode 100644 index 0000000..d40bf9b --- /dev/null +++ b/opcache.ini @@ -0,0 +1,11 @@ +[opcache] +opcache.enable=${PHP_OPCACHE_ENABLE} +opcache.enable_cli=${PHP_OPCACHE_ENABLE_CLI} +opcache.interned_strings_buffer=${PHP_OPCACHE_INTERNED_STRINGS_BUFFER} +opcache.max_accelerated_files=${PHP_OPCACHE_MAX_ACCELERATED_FILES} +opcache.max_wasted_percentage=${PHP_OPCACHE_MAX_WASTED_PERCENTAGE} +opcache.memory_consumption=${PHP_OPCACHE_MEMORY_CONSUMPTION} +opcache.preload=${PHP_OPCACHE_PRELOAD} +opcache.preload_user=${PHP_OPCACHE_PRELOAD_USER} +opcache.revalidate_freq=0 +opcache.validate_timestamps=${PHP_OPCACHE_VALIDATE_TIMESTAMPS} \ No newline at end of file diff --git a/realpath.ini b/realpath.ini new file mode 100644 index 0000000..927a357 --- /dev/null +++ b/realpath.ini @@ -0,0 +1,3 @@ + +realpath_cache_size=${PHP_REALPATH_CACHE_SIZE} +realpath_cache_ttl=${PHP_REALPATH_CACHE_TTL} \ No newline at end of file diff --git a/test/demo/Dockerfile b/test/demo/Dockerfile index 8b38164..92e0d87 100644 --- a/test/demo/Dockerfile +++ b/test/demo/Dockerfile @@ -4,16 +4,20 @@ FROM php WORKDIR /app -COPY --link composer.* symfony.* ./ +COPY composer.* symfony.* ./ -RUN set -eux; \ +RUN --mount=type=bind,from=composer/composer:2-bin,source=/composer,target=/usr/local/bin/composer \ + set -eux; \ + PHP_OPCACHE_PRELOAD="" \ composer install --no-cache --prefer-dist --no-dev --no-autoloader --no-scripts --no-progress COPY . ./ -RUN set -eux; \ +RUN --mount=type=bind,from=composer/composer:2-bin,source=/composer,target=/usr/local/bin/composer \ + set -eux; \ mkdir -p var/cache var/log var/share; \ composer dump-autoload --classmap-authoritative --no-dev; \ composer dump-env prod; \ composer run-script --no-dev post-install-cmd; \ - chmod +x bin/console; sync; + chmod +x bin/console; \ + sync; diff --git a/test/demo/src/Controller/HomeController.php b/test/demo/src/Controller/HomeController.php index 0a0a945..4a043b2 100644 --- a/test/demo/src/Controller/HomeController.php +++ b/test/demo/src/Controller/HomeController.php @@ -4,6 +4,8 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; final class HomeController extends AbstractController @@ -16,4 +18,15 @@ public function index(): JsonResponse 'message' => 'Hello world!', ]); } + + #[Route(path: '/phpinfo', methods: [Request::METHOD_GET])] + public function phpinfo(): Response + { + ob_start(); + phpinfo(); + ob_flush(); + + $content = ob_get_contents(); + return new Response($content); + } }