dockerize portal
This commit is contained in:
parent
cb34a18948
commit
c528407991
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Git files
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.gitattributes
|
||||||
|
|
||||||
|
# IDE files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
README.md
|
||||||
|
*.MD
|
||||||
|
HELPER.MD
|
||||||
|
NOTIFICATION.MD
|
||||||
|
|
||||||
|
# Test files
|
||||||
|
tests
|
||||||
|
phpunit.xml.dist
|
||||||
|
|
||||||
|
# CI/CD
|
||||||
|
.github
|
||||||
|
.gitlab-ci.yml
|
||||||
|
|
||||||
|
# Platform.sh
|
||||||
|
.platform
|
||||||
|
.platform.app.yaml
|
||||||
|
|
||||||
|
# Docker files (don't copy Docker files into the image)
|
||||||
|
Dockerfile
|
||||||
|
docker-compose*.yml
|
||||||
|
compose*.yaml
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# Environment files (will be provided at runtime)
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Development dependencies
|
||||||
|
.php-cs-fixer.cache
|
||||||
|
|
||||||
|
# Cache and logs (will be created at runtime)
|
||||||
|
var/cache/*
|
||||||
|
var/log/*
|
||||||
|
var/sessions/*
|
||||||
|
|
||||||
|
# Vendor (will be installed during build)
|
||||||
|
# vendor is installed during the build process, so we don't ignore it
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
|
||||||
|
variables:
|
||||||
|
# OVH Container Registry URL (without https://)
|
||||||
|
# Image name and tag (format: registry/project/image)
|
||||||
|
IMAGE_NAME: "easyportal"
|
||||||
|
IMAGE_TAG: "${OVH_REGISTRY_URL}/${IMAGE_NAME}:${CI_COMMIT_REF_SLUG}-${CI_PIPELINE_ID}"
|
||||||
|
IMAGE_LATEST: "${OVH_REGISTRY_URL}/${IMAGE_NAME}:latest"
|
||||||
|
|
||||||
|
build:
|
||||||
|
stage: build
|
||||||
|
image: docker:20.10.16
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_BRANCH == "develop"'
|
||||||
|
when: always
|
||||||
|
- when: manual
|
||||||
|
before_script:
|
||||||
|
# Use host Docker daemon via socket
|
||||||
|
- docker info
|
||||||
|
# Login to OVH Container Registry
|
||||||
|
- echo "Logging into OVH Container Registry..."
|
||||||
|
- echo "$OVH_REGISTRY_PASSWORD" | docker login -u "$OVH_REGISTRY_USERNAME" "$OVH_REGISTRY_URL" --password-stdin
|
||||||
|
script:
|
||||||
|
# Build the FrankenPHP image
|
||||||
|
- echo "Building Docker image..."
|
||||||
|
- docker build --build-arg APP_ENV=prod --target frankenphp_prod -t $IMAGE_TAG -t $IMAGE_LATEST .
|
||||||
|
|
||||||
|
# Push both tags to OVH registry
|
||||||
|
- echo "Pushing image to OVH registry..."
|
||||||
|
- docker push $IMAGE_TAG
|
||||||
|
- docker push $IMAGE_LATEST
|
||||||
|
|
||||||
|
# Display image info
|
||||||
|
- echo "Successfully pushed:"
|
||||||
|
- echo " - $IMAGE_TAG"
|
||||||
|
- echo " - $IMAGE_LATEST"
|
||||||
|
after_script:
|
||||||
|
- docker logout $OVH_REGISTRY_URL || true
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
#syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
# Versions
|
||||||
|
FROM dunglas/frankenphp:1-php8.3 AS frankenphp_upstream
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
# Base FrankenPHP image
|
||||||
|
FROM frankenphp_upstream AS frankenphp_base
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# Transport to use by Mercure (default to Bolt)
|
||||||
|
ENV MERCURE_TRANSPORT_URL=bolt:///data/mercure.db
|
||||||
|
|
||||||
|
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.prod /etc/frankenphp/Caddyfile
|
||||||
|
|
||||||
|
ENTRYPOINT ["docker-entrypoint"]
|
||||||
|
|
||||||
|
HEALTHCHECK --start-period=60s CMD curl -f http://localhost:2019/metrics || exit 1
|
||||||
|
CMD [ "frankenphp", "run", "--config", "/etc/frankenphp/Caddyfile" ]
|
||||||
|
|
||||||
|
# Dev FrankenPHP image
|
||||||
|
FROM frankenphp_base AS frankenphp_dev
|
||||||
|
|
||||||
|
ENV APP_ENV=dev
|
||||||
|
ENV XDEBUG_MODE=off
|
||||||
|
ENV FRANKENPHP_WORKER_CONFIG=watch
|
||||||
|
|
||||||
|
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/frankenphp/Caddyfile", "--watch" ]
|
||||||
|
|
||||||
|
# Prod FrankenPHP image
|
||||||
|
FROM frankenphp_base AS frankenphp_prod
|
||||||
|
|
||||||
|
ENV APP_ENV=prod
|
||||||
|
|
||||||
|
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||||
|
|
||||||
|
COPY --link frankenphp/conf.d/20-app.prod.ini $PHP_INI_DIR/app.conf.d/
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# copy sources
|
||||||
|
COPY --link . ./
|
||||||
|
RUN rm -Rf frankenphp/
|
||||||
|
|
||||||
|
RUN set -eux; \
|
||||||
|
mkdir -p var/cache var/log; \
|
||||||
|
composer dump-autoload --classmap-authoritative --no-dev; \
|
||||||
|
composer dump-env prod; \
|
||||||
|
chmod +x bin/console; \
|
||||||
|
# Install JavaScript vendor assets and compile assets for production \
|
||||||
|
php bin/console importmap:install; \
|
||||||
|
php bin/console asset-map:compile; \
|
||||||
|
php bin/console assets:install public; \
|
||||||
|
sync;
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
"symfony/property-access": "7.2.*",
|
"symfony/property-access": "7.2.*",
|
||||||
"symfony/property-info": "7.2.*",
|
"symfony/property-info": "7.2.*",
|
||||||
"symfony/runtime": "7.2.*",
|
"symfony/runtime": "7.2.*",
|
||||||
|
"runtime/frankenphp-symfony": "^0.2.0",
|
||||||
"symfony/security-bundle": "7.2.*",
|
"symfony/security-bundle": "7.2.*",
|
||||||
"symfony/serializer": "7.2.*",
|
"symfony/serializer": "7.2.*",
|
||||||
"symfony/stimulus-bundle": "^2.24",
|
"symfony/stimulus-bundle": "^2.24",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
{
|
||||||
|
skip_install_trust
|
||||||
|
|
||||||
|
{$CADDY_GLOBAL_OPTIONS}
|
||||||
|
|
||||||
|
frankenphp {
|
||||||
|
{$FRANKENPHP_CONFIG}
|
||||||
|
|
||||||
|
worker {
|
||||||
|
file ./public/index.php
|
||||||
|
env APP_RUNTIME Runtime\FrankenPhpSymfony\Runtime
|
||||||
|
{$FRANKENPHP_WORKER_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 {
|
||||||
|
# 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
{
|
||||||
|
# Global options
|
||||||
|
frankenphp {
|
||||||
|
# Number of workers for better performance
|
||||||
|
num_threads {$NUM_THREADS:4}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Order directives properly
|
||||||
|
order mercure after encode
|
||||||
|
order php_server before file_server
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTP - redirect to HTTPS
|
||||||
|
http://{$SERVER_NAME:localhost} {
|
||||||
|
redir https://{host}{uri} permanent
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTPS server
|
||||||
|
https://{$SERVER_NAME:localhost} {
|
||||||
|
# Root directory
|
||||||
|
root * /app/public
|
||||||
|
|
||||||
|
# TLS configuration - Caddy will automatically obtain and renew Let's Encrypt certificates
|
||||||
|
tls {
|
||||||
|
protocols tls1.2 tls1.3
|
||||||
|
}
|
||||||
|
|
||||||
|
# Enable compression
|
||||||
|
encode zstd gzip
|
||||||
|
|
||||||
|
# Mercure hub configuration (built-in)
|
||||||
|
mercure {
|
||||||
|
# Publisher JWT key
|
||||||
|
publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {
|
||||||
|
algorithm hs256
|
||||||
|
}
|
||||||
|
# Subscriber JWT key
|
||||||
|
subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {
|
||||||
|
algorithm hs256
|
||||||
|
}
|
||||||
|
# Allow anonymous subscribers
|
||||||
|
anonymous
|
||||||
|
# Enable subscriptions
|
||||||
|
subscriptions
|
||||||
|
# CORS configuration
|
||||||
|
cors_origins *
|
||||||
|
}
|
||||||
|
|
||||||
|
# Client max body size (for uploads)
|
||||||
|
request_body {
|
||||||
|
max_size 20MB
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security: Deny access to sensitive directories
|
||||||
|
@forbidden {
|
||||||
|
path /bin/* /config/* /src/* /templates/* /tests/* /translations/* /var/* /vendor/*
|
||||||
|
}
|
||||||
|
handle @forbidden {
|
||||||
|
respond "Access Denied" 404
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security: Deny access to dot files (except .well-known for Mercure)
|
||||||
|
@dotfiles {
|
||||||
|
path */.*
|
||||||
|
not path /.well-known/*
|
||||||
|
}
|
||||||
|
handle @dotfiles {
|
||||||
|
respond "Access Denied" 404
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cache static assets (30 days)
|
||||||
|
@static {
|
||||||
|
path *.jpg *.jpeg *.png *.gif *.ico *.css *.js *.svg *.woff *.woff2 *.ttf *.eot *.xlsx *.pdf
|
||||||
|
file
|
||||||
|
}
|
||||||
|
handle @static {
|
||||||
|
header Cache-Control "public, max-age=2592000, no-transform"
|
||||||
|
file_server
|
||||||
|
}
|
||||||
|
|
||||||
|
# Serve files from /assets directory
|
||||||
|
handle /assets/* {
|
||||||
|
root * /app/public
|
||||||
|
file_server
|
||||||
|
}
|
||||||
|
|
||||||
|
# PHP FrankenPHP handler
|
||||||
|
php_server {
|
||||||
|
# Resolve symlinks
|
||||||
|
resolve_root_symlink
|
||||||
|
}
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log {
|
||||||
|
output file /app/var/log/access.log
|
||||||
|
format json
|
||||||
|
# Redact sensitive data
|
||||||
|
format filter {
|
||||||
|
request>uri query {
|
||||||
|
replace authorization REDACTED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/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 --wait'
|
||||||
|
sleep infinity
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
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…
Reference in New Issue