Skip to content

Commit

Permalink
Merge pull request #83 from druidfi/frankenphp-base-image
Browse files Browse the repository at this point in the history
FrankenPHP base image
  • Loading branch information
back-2-95 authored Jan 29, 2025
2 parents 6e43dea + 3ba19f8 commit e942ae4
Show file tree
Hide file tree
Showing 15 changed files with 434 additions and 2 deletions.
34 changes: 34 additions & 0 deletions frankenphp/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
**/*.log
**/*.md
**/*.php~
**/*.dist.php
**/*.dist
**/*.cache
**/._*
**/.dockerignore
**/.DS_Store
**/.git/
**/.gitattributes
**/.gitignore
**/.gitmodules
**/compose.*.yaml
**/compose.*.yml
**/compose.yaml
**/compose.yml
**/docker-compose.*.yaml
**/docker-compose.*.yml
**/docker-compose.yaml
**/docker-compose.yml
**/Dockerfile
**/Thumbs.db
.github/
docs/
public/bundles/
tests/
var/
vendor/
.editorconfig
.env.*.local
.env.local
.env.local.php
.env.test
1 change: 1 addition & 0 deletions frankenphp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.dist**
43 changes: 43 additions & 0 deletions frankenphp/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#syntax=docker/dockerfile:1

# Base FrankenPHP image
FROM frankenphp_upstream AS frankenphp_base

# defaults
ENV APP_ENV=dev XDEBUG_MODE=off

WORKDIR /app

VOLUME /app/var/

# persistent / runtime deps
# hadolint ignore=DL3008
RUN apt-get update && apt-get install -y --no-install-recommends \
acl \
file \
gettext \
git \
&& rm -rf /var/lib/apt/lists/*

RUN set -eux; \
install-php-extensions \
@composer \
apcu \
intl \
opcache \
zip \
;

# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
ENV COMPOSER_ALLOW_SUPERUSER=1
ENV PATH="${PATH}:/root/.composer/vendor/bin"
ENV PHP_INI_SCAN_DIR=":$PHP_INI_DIR/app.conf.d"

COPY --link conf/php/ $PHP_INI_DIR/app.conf.d/
COPY --link conf/caddy/ /etc/caddy/
COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/docker-entrypoint

ENTRYPOINT ["docker-entrypoint"]

HEALTHCHECK --start-period=60s CMD curl -f http://localhost:2019/metrics || exit 1
CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile" ]
29 changes: 29 additions & 0 deletions frankenphp/build.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
BAKE_FLAGS := --pull --no-cache --push

PHONY += frankenphp-bake-all
frankenphp-bake-all: ## Bake all FrankenPHP images
@PHP83_PATCH=$(call get_php_minor,8.3) PHP84_PATCH=$(call get_php_minor,8.4) \
docker buildx bake -f frankenphp/docker-bake.hcl $(BAKE_FLAGS)

PHONY += frankenphp-bake-print
frankenphp-bake-print: BAKE_FLAGS := --print
frankenphp-bake-print: frankenphp-bake-all ## Print bake plan for FrankenPHP images

PHONY += frankenphp-bake-local
frankenphp-bake-local: BAKE_FLAGS := --pull --progress plain --no-cache --load --set *.platform=linux/$(CURRENT_ARCH)
frankenphp-bake-local: frankenphp-bake-all run-frankenphp-tests ## Bake all FrankenPHP images locally

PHONY += frankenphp-bake-test
frankenphp-bake-test: BAKE_FLAGS := --pull --progress plain --no-cache
frankenphp-bake-test: frankenphp-bake-all run-frankenphp-tests ## CI test for FrankenPHP images

PHONY += run-frankenphp-tests
run-frankenphp-tests:
$(call step,Run tests in druidfi/frankenphp:1.4.2-php8.3)
@docker run --rm -t -v $(CURDIR)/tests/scripts:/app/scripts druidfi/frankenphp:1.4.2-php8.3 /app/scripts/tests_symfony.sh
$(call step,Run tests in druidfi/frankenphp:1.4.2-php8.4)
@docker run --rm -t -v $(CURDIR)/tests/scripts:/app/scripts druidfi/frankenphp:1.4.2-php8.4 /app/scripts/tests_symfony.sh

PHONY += frankenphp-update
frankenphp-update:
@frankenphp/update.sh
59 changes: 59 additions & 0 deletions frankenphp/conf/caddy/Caddyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
{$CADDY_GLOBAL_OPTIONS}

frankenphp {
{$FRANKENPHP_CONFIG}
}
}

{$CADDY_EXTRA_CONFIG}

{$SERVER_NAME:localhost} {
log {
{$CADDY_SERVER_LOG_OPTIONS}
# 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

{$CADDY_SERVER_EXTRA_DIRECTIVES}

# Disable Topics tracking if not enabled explicitly: https://github.com/jkarlin/topics
header ?Permissions-Policy "browsing-topics=()"

@phpRoute {
not path /.well-known/mercure*
not file {path}
}
rewrite @phpRoute index.php

@frontController path index.php
php @frontController

file_server {
hide *.php
}
}
4 changes: 4 additions & 0 deletions frankenphp/conf/caddy/worker.Caddyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
worker {
file ./public/index.php
env APP_RUNTIME Runtime\FrankenPhpSymfony\Runtime
}
13 changes: 13 additions & 0 deletions frankenphp/conf/php/10-app.ini
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions frankenphp/conf/php/20-app.dev.ini
Original file line number Diff line number Diff line change
@@ -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 = host.docker.internal
5 changes: 5 additions & 0 deletions frankenphp/conf/php/20-app.prod.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
; https://symfony.com/doc/current/performance.html#use-the-opcache-class-preloading
opcache.preload_user = root
opcache.preload = /app/config/preload.php
; https://symfony.com/doc/current/performance.html#don-t-check-php-files-timestamps
opcache.validate_timestamps = 0
66 changes: 66 additions & 0 deletions frankenphp/docker-bake.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
variable "FRANKENPHP_VERSION" {
default = "1.4.2"
}

variable "REPO_BASE" {
default = "druidfi/frankenphp"
}

variable "PHP83_PATCH" {}
variable "PHP84_PATCH" {}

group "default" {
targets = ["php-variants"]
}

group "php-variants" {
targets = ["php-83", "php-84"]
}

target "common" {
context = "./frankenphp"
platforms = ["linux/amd64", "linux/arm64"]
labels = {
"org.opencontainers.image.url" = "https://github.com/druidfi/docker-images"
"org.opencontainers.image.source" = "https://github.com/druidfi/docker-images"
"org.opencontainers.image.licenses" = "MIT"
"org.opencontainers.image.vendor" = "Druid Oy"
"org.opencontainers.image.created" = "${timestamp()}"
}
}

#
# FRANKENPHP
#

target "php-83" {
inherits = ["common"]
args = {
PHP_VERSION = "8.3"
PHP_SHORT_VERSION = "83"
}
contexts = {
frankenphp_upstream = "docker-image://dunglas/frankenphp:${FRANKENPHP_VERSION}-php${PHP83_PATCH}"
}
tags = [
"${REPO_BASE}:${FRANKENPHP_VERSION}-php8.3",
"${REPO_BASE}:${FRANKENPHP_VERSION}-php${PHP83_PATCH}"
]
}

target "php-84" {
inherits = ["common"]
args = {
PHP_VERSION = "8.4"
PHP_SHORT_VERSION = "84"
}
contexts = {
frankenphp_upstream = "docker-image://dunglas/frankenphp:${FRANKENPHP_VERSION}-php${PHP84_PATCH}"
}
tags = [
"${REPO_BASE}:${FRANKENPHP_VERSION}-php8",
"${REPO_BASE}:${FRANKENPHP_VERSION}-php8.4",
"${REPO_BASE}:${FRANKENPHP_VERSION}-php${PHP84_PATCH}",
"${REPO_BASE}:latest"
]
}
42 changes: 42 additions & 0 deletions frankenphp/docker-entrypoint.dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/sh
set -e

if [ "$1" = 'conf' ] || [ "$1" = 'php' ] || [ "$1" = 'bin/console' ]; then
if [ -z "$(ls -A 'vendor/' 2>/dev/null)" ]; then
composer install --prefer-dist --no-progress --no-interaction
fi

# Display information about the current project
# Or about an error in project initialization
php bin/console -V

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
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

echo 'PHP app development ready!'
fi

exec docker-php-entrypoint "$@"
46 changes: 46 additions & 0 deletions frankenphp/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/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

# Display information about the current project
# Or about an error in project initialization
php bin/console -V

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

echo 'PHP app ready!'
fi

exec docker-php-entrypoint "$@"
Loading

0 comments on commit e942ae4

Please sign in to comment.