Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New docker using symfony/docker template #43

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .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
106 changes: 88 additions & 18 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,28 +1,98 @@
FROM php:8.1-cli
LABEL maintainer Matthias Straka
#syntax=docker/dockerfile:1

RUN apt-get update -y && \
apt-get install -y --no-install-recommends unzip npm
# Versions
FROM dunglas/frankenphp:1-php8.3 AS frankenphp_upstream

RUN pecl install apcu
RUN docker-php-ext-enable apcu
RUN docker-php-ext-install bcmath
# The different stages of this Dockerfile are meant to be built into separate images
# https://docs.docker.com/develop/develop-images/multistage-build/#stop-at-a-specific-build-stage
# https://docs.docker.com/compose/compose-file/#target

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Base FrankenPHP image
FROM frankenphp_upstream AS frankenphp_base

WORKDIR /app
COPY . /app

RUN composer install --no-dev
RUN php bin/console doctrine:schema:create
#RUN php bin/console doctrine:fixtures:load -n --group=seeder
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 \
bcmath \
intl \
opcache \
zip \
;

# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
ENV COMPOSER_ALLOW_SUPERUSER=1

ENV PHP_INI_SCAN_DIR=":$PHP_INI_DIR/app.conf.d"

###> recipes ###
###> doctrine/doctrine-bundle ###
RUN install-php-extensions pdo_pgsql
###< doctrine/doctrine-bundle ###
###< recipes ###

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

ENTRYPOINT ["docker-entrypoint"]

HEALTHCHECK --start-period=60s CMD curl -f http://localhost:2019/metrics || exit 1
CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile" ]

# Dev FrankenPHP image
FROM frankenphp_base AS frankenphp_dev

ENV APP_ENV=dev XDEBUG_MODE=off

RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"

RUN set -eux; \
install-php-extensions \
xdebug \
;

COPY --link frankenphp/conf.d/20-app.dev.ini $PHP_INI_DIR/app.conf.d/

CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile", "--watch" ]

# Prod FrankenPHP image
FROM frankenphp_base AS frankenphp_prod

ENV APP_ENV=prod
ENV FRANKENPHP_CONFIG="import worker.Caddyfile"

RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

VOLUME [ "/app/var" ]
COPY --link frankenphp/conf.d/20-app.prod.ini $PHP_INI_DIR/app.conf.d/
COPY --link frankenphp/worker.Caddyfile /etc/caddy/worker.Caddyfile

# Setup up local environment with dummy secret
RUN echo "APP_SECRET='DockerSecret'" > /app/.env.local
# prevent the reinstallation of vendors at every changes in the source code
COPY --link composer.* symfony.* ./
RUN set -eux; \
composer install --no-cache --prefer-dist --no-dev --no-autoloader --no-scripts --no-progress

EXPOSE 8000
# copy sources
COPY --link . ./
RUN rm -Rf frankenphp/

WORKDIR /app/public
CMD php -S 0.0.0.0:8000
RUN set -eux; \
mkdir -p var/cache var/log; \
composer dump-autoload --classmap-authoritative --no-dev; \
composer dump-env prod; \
composer run-script --no-dev post-install-cmd; \
chmod +x bin/console; sync;
30 changes: 30 additions & 0 deletions compose.override.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Development environment override
services:
php:
build:
context: .
target: frankenphp_dev
volumes:
- ./:/app
- ./frankenphp/Caddyfile:/etc/caddy/Caddyfile:ro
- ./frankenphp/conf.d/20-app.dev.ini:/usr/local/etc/php/app.conf.d/20-app.dev.ini:ro
# If you develop on Mac or Windows you can remove the vendor/ directory
# from the bind-mount for better performance by enabling the next line:
#- /app/vendor
environment:
MERCURE_EXTRA_DIRECTIVES: demo
# See https://xdebug.org/docs/all_settings#mode
XDEBUG_MODE: "${XDEBUG_MODE:-off}"
extra_hosts:
# Ensure that host.docker.internal is correctly defined on Linux
- host.docker.internal:host-gateway
tty: true

###> symfony/mercure-bundle ###
###< symfony/mercure-bundle ###

###> doctrine/doctrine-bundle ###
database:
ports:
- "5432"
###< doctrine/doctrine-bundle ###
10 changes: 10 additions & 0 deletions compose.prod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Production environment override
services:
php:
build:
context: .
target: frankenphp_prod
environment:
APP_SECRET: ${APP_SECRET}
MERCURE_PUBLISHER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET}
MERCURE_SUBSCRIBER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET}
61 changes: 61 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
services:
php:
image: ${IMAGES_PREFIX:-}app-php
restart: unless-stopped
environment:
SERVER_NAME: ${SERVER_NAME:-localhost}, php:80
MERCURE_PUBLISHER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!}
MERCURE_SUBSCRIBER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!}
# Run "composer require symfony/orm-pack" to install and configure Doctrine ORM
DATABASE_URL: postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-!ChangeMe!}@database:5432/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-15}&charset=${POSTGRES_CHARSET:-utf8}
# Run "composer require symfony/mercure-bundle" to install and configure the Mercure integration
MERCURE_URL: ${CADDY_MERCURE_URL:-http://php/.well-known/mercure}
MERCURE_PUBLIC_URL: ${CADDY_MERCURE_PUBLIC_URL:-https://${SERVER_NAME:-localhost}/.well-known/mercure}
MERCURE_JWT_SECRET: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!}
# The two next lines can be removed after initial installation
SYMFONY_VERSION: ${SYMFONY_VERSION:-}
STABILITY: ${STABILITY:-stable}
volumes:
- caddy_data:/data
- caddy_config:/config
ports:
# HTTP
- target: 80
published: ${HTTP_PORT:-80}
protocol: tcp
# HTTPS
- target: 443
published: ${HTTPS_PORT:-443}
protocol: tcp
# HTTP/3
- target: 443
published: ${HTTP3_PORT:-443}
protocol: udp

# Mercure is installed as a Caddy module, prevent the Flex recipe from installing another service
###> symfony/mercure-bundle ###
###< symfony/mercure-bundle ###

###> doctrine/doctrine-bundle ###
database:
image: postgres:${POSTGRES_VERSION:-16}-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB:-app}
# You should definitely change the password in production
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
POSTGRES_USER: ${POSTGRES_USER:-app}
volumes:
- database_data:/var/lib/postgresql/data:rw
# You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
# - ./docker/db/data:/var/lib/postgresql/data:rw
###< doctrine/doctrine-bundle ###

volumes:
caddy_data:
caddy_config:
###> symfony/mercure-bundle ###
###< symfony/mercure-bundle ###

###> doctrine/doctrine-bundle ###
database_data:
###< doctrine/doctrine-bundle ###
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@
"extra": {
"symfony": {
"allow-contrib": false,
"require": "^6.4"
"require": "^6.4",
"docker": true
}
}
}
47 changes: 47 additions & 0 deletions frankenphp/Caddyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
{$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

{$CADDY_SERVER_EXTRA_DIRECTIVES}

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

php_server
}
13 changes: 13 additions & 0 deletions frankenphp/conf.d/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.d/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
2 changes: 2 additions & 0 deletions frankenphp/conf.d/20-app.prod.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
opcache.preload_user = root
opcache.preload = /app/config/preload.php
60 changes: 60 additions & 0 deletions frankenphp/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/sh
set -e

if [ "$1" = 'frankenphp' ] || [ "$1" = 'php' ] || [ "$1" = 'bin/console' ]; then
# Install the project the first time PHP is started
# After the installation, the following block can be deleted
if [ ! -f composer.json ]; then
rm -Rf tmp/
composer create-project "symfony/skeleton $SYMFONY_VERSION" tmp --stability="$STABILITY" --prefer-dist --no-progress --no-interaction --no-install

cd tmp
cp -Rp . ..
cd -
rm -Rf tmp/

composer require "php:>=$PHP_VERSION" runtime/frankenphp-symfony
composer config --json extra.symfony.docker 'true'

if grep -q ^DATABASE_URL= .env; then
echo "To finish the installation please press Ctrl+C to stop Docker Compose and run: docker compose up --build -d --wait"
sleep infinity
fi
fi

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 "$@"
Loading