Merge branch 'dockerize-portal' into 'develop'
Dockerize portal See merge request easy-solutions/apps/easyportal!2
This commit is contained in:
commit
64ebaa4e05
|
|
@ -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
|
||||
8
.env
8
.env
|
|
@ -17,6 +17,7 @@
|
|||
###> symfony/framework-bundle ###
|
||||
APP_ENV=prod
|
||||
APP_SECRET='kjuusshgvk35434judshfgvkusd224444hvg'
|
||||
APPLICATION=EasyPortal
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
|
|
@ -43,8 +44,8 @@ MAILER_DSN=null://null
|
|||
TRUSTED_PROXY='185.116.130.121','10.8.34.21'
|
||||
|
||||
###> league/oauth2-server-bundle ###
|
||||
OAUTH_PRIVATE_KEY=%kernel.project_dir%/config/jwt/private.pem
|
||||
OAUTH_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
|
||||
OAUTH_PRIVATE_KEY=%kernel.project_dir%/config/jwt/private.key
|
||||
OAUTH_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.key
|
||||
OAUTH_PASSPHRASE=8170ea18d2e3e05b5c7ae0672a754bf4
|
||||
OAUTH_ENCRYPTION_KEY=f1b7c279f7992205a0df45e295d07066
|
||||
###< league/oauth2-server-bundle ###
|
||||
|
|
@ -66,4 +67,7 @@ MERCURE_JWT_SECRET="!ChangeThisMercureHubJWTSecretKey!"
|
|||
###> aws/aws-sdk-php-symfony ###
|
||||
AWS_KEY=not-a-real-key
|
||||
AWS_SECRET=@@not-a-real-secret
|
||||
AWS_REGION=us-east-1
|
||||
AWS_ENDPOINT=https://s3.amazonaws.com
|
||||
AWS_S3_PORTAL_URL=https://s3.amazonaws.com/portal
|
||||
###< aws/aws-sdk-php-symfony ###
|
||||
|
|
|
|||
|
|
@ -0,0 +1,302 @@
|
|||
stages:
|
||||
- build
|
||||
- deploy
|
||||
- notify
|
||||
|
||||
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
|
||||
|
||||
deploy:
|
||||
stage: deploy
|
||||
image: alpine:latest
|
||||
needs:
|
||||
- build
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH == "develop"'
|
||||
when: on_success
|
||||
- when: manual
|
||||
before_script:
|
||||
- apk add --no-cache openssh-client
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
- echo "Host *\n StrictHostKeyChecking no\n UserKnownHostsFile=/dev/null" > ~/.ssh/config
|
||||
- chmod 600 ~/.ssh/config
|
||||
- ssh-keyscan -H $SERVER_IP >> ~/.ssh/known_hosts || true
|
||||
script:
|
||||
- |
|
||||
ssh $SSH_USER@$SERVER_IP << ENDSSH
|
||||
set -e
|
||||
cd /mnt/external-disk/easy-monitor/easyportal
|
||||
|
||||
# ===== PRE-DEPLOYMENT DOCKER CLEANUP =====
|
||||
echo '===== Starting pre-deployment Docker cleanup ====='
|
||||
|
||||
# Show current Docker space usage
|
||||
echo 'Current Docker space usage:'
|
||||
docker system df
|
||||
|
||||
# Clean build cache
|
||||
echo 'Cleaning Docker build cache...'
|
||||
docker builder prune -f || true
|
||||
|
||||
# Clean stopped containers
|
||||
echo 'Cleaning stopped containers...'
|
||||
docker container prune -f || true
|
||||
|
||||
# Clean unused networks
|
||||
echo 'Cleaning unused networks...'
|
||||
docker network prune -f || true
|
||||
|
||||
# Show space usage after cleanup
|
||||
echo 'Docker space usage after initial cleanup:'
|
||||
docker system df
|
||||
|
||||
# Login to OVH registry
|
||||
echo "$OVH_REGISTRY_PASSWORD" | docker login -u "$OVH_REGISTRY_USERNAME" "$OVH_REGISTRY_URL" --password-stdin
|
||||
|
||||
# Pull latest image
|
||||
echo 'Pulling latest image...'
|
||||
docker pull $IMAGE_LATEST
|
||||
|
||||
# Clean unused images before deployment
|
||||
echo 'Cleaning unused Docker images...'
|
||||
docker image prune -f || true
|
||||
|
||||
# Update .env.compose with new image tag
|
||||
echo 'Updating .env.compose with new image...'
|
||||
echo "EASYPORTAL_IMAGE=$IMAGE_LATEST" > .env.compose
|
||||
|
||||
# Recreate php and messenger containers with new image
|
||||
echo 'Restarting EasyPortal services with new image...'
|
||||
docker compose --env-file .env.compose up -d --force-recreate --no-deps php messenger
|
||||
|
||||
# Wait for service to be ready
|
||||
sleep 15
|
||||
|
||||
# Run migrations
|
||||
echo 'Running database migrations...'
|
||||
docker compose --env-file .env.compose exec -T php php bin/console doctrine:migrations:migrate --no-interaction
|
||||
|
||||
# Clear cache
|
||||
echo 'Clearing Symfony cache...'
|
||||
docker compose --env-file .env.compose exec -T php php bin/console cache:clear --env=prod --no-debug
|
||||
|
||||
# ===== POST-DEPLOYMENT CLEANUP =====
|
||||
echo '===== Final Docker cleanup ====='
|
||||
|
||||
docker builder prune -f || true
|
||||
docker container prune -f || true
|
||||
|
||||
# Keep last 3 image versions
|
||||
echo 'Cleaning old image versions (keeping last 3)...'
|
||||
docker images --format 'table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedAt}}' | grep -v REPOSITORY | sort -k1,1 -k4,4r | awk '
|
||||
{
|
||||
repo_tag = \$1":" \$2
|
||||
if (repo_count[\$1]++ >= 3 && \$2 != "latest" && \$1 != "<none>") {
|
||||
print \$3
|
||||
}
|
||||
}' | xargs -r docker rmi -f || true
|
||||
|
||||
echo 'Final Docker space usage:'
|
||||
docker system df
|
||||
|
||||
echo '===== Deployment completed successfully! ====='
|
||||
ENDSSH
|
||||
after_script:
|
||||
- rm -f ~/.ssh/id_rsa
|
||||
environment:
|
||||
name: production
|
||||
url: https://testportail.solutions-easy.com
|
||||
|
||||
notify_success:
|
||||
stage: notify
|
||||
image: curlimages/curl:latest
|
||||
needs:
|
||||
- deploy
|
||||
rules:
|
||||
- when: on_success
|
||||
- when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- |
|
||||
COMMIT_SHORT_SHA=$(echo $CI_COMMIT_SHA | cut -c1-8)
|
||||
DEPLOYMENT_TYPE="Déploiement Beta"
|
||||
|
||||
if [ "$CI_COMMIT_BRANCH" != "develop" ]; then
|
||||
DEPLOYMENT_TYPE="Déploiement Beta"
|
||||
fi
|
||||
|
||||
curl -H "Content-Type: application/json" -d "{
|
||||
\"type\": \"message\",
|
||||
\"attachments\": [
|
||||
{
|
||||
\"contentType\": \"application/vnd.microsoft.card.adaptive\",
|
||||
\"content\": {
|
||||
\"type\": \"AdaptiveCard\",
|
||||
\"body\": [
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"$DEPLOYMENT_TYPE\",
|
||||
\"weight\": \"Bolder\",
|
||||
\"size\": \"Large\"
|
||||
},
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"**App:** EasyPortal\",
|
||||
\"wrap\": true
|
||||
},
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"**Version:** [$CI_COMMIT_REF_NAME - $COMMIT_SHORT_SHA]($CI_PROJECT_URL/-/commit/$CI_COMMIT_SHA)\",
|
||||
\"wrap\": true,
|
||||
\"markdown\": true
|
||||
},
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"**Pipeline:** [Voir le pipeline]($CI_PIPELINE_URL)\",
|
||||
\"wrap\": true,
|
||||
\"markdown\": true
|
||||
},
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"**Auteur:** $GITLAB_USER_LOGIN\",
|
||||
\"wrap\": true
|
||||
},
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"**Statut:** Succès ✓\",
|
||||
\"wrap\": true,
|
||||
\"color\": \"Good\"
|
||||
}
|
||||
],
|
||||
\"actions\": [
|
||||
{
|
||||
\"type\": \"Action.OpenUrl\",
|
||||
\"title\": \"Voir le pipeline\",
|
||||
\"url\": \"$CI_PIPELINE_URL\"
|
||||
},
|
||||
{
|
||||
\"type\": \"Action.OpenUrl\",
|
||||
\"title\": \"Voir le commit\",
|
||||
\"url\": \"$CI_PROJECT_URL/-/commit/$CI_COMMIT_SHA\"
|
||||
}
|
||||
],
|
||||
\"\$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",
|
||||
\"version\": \"1.0\"
|
||||
}
|
||||
}
|
||||
]
|
||||
}" "$TEAMS_WEBHOOK_URL"
|
||||
|
||||
notify_failure:
|
||||
stage: notify
|
||||
image: curlimages/curl:latest
|
||||
needs:
|
||||
- deploy
|
||||
rules:
|
||||
- when: on_failure
|
||||
script:
|
||||
- |
|
||||
COMMIT_SHORT_SHA=$(echo $CI_COMMIT_SHA | cut -c1-8)
|
||||
DEPLOYMENT_TYPE="Déploiement Beta"
|
||||
|
||||
if [ "$CI_COMMIT_BRANCH" != "develop" ]; then
|
||||
DEPLOYMENT_TYPE="Déploiement Beta"
|
||||
fi
|
||||
|
||||
curl -H "Content-Type: application/json" -d "{
|
||||
\"type\": \"message\",
|
||||
\"attachments\": [
|
||||
{
|
||||
\"contentType\": \"application/vnd.microsoft.card.adaptive\",
|
||||
\"content\": {
|
||||
\"type\": \"AdaptiveCard\",
|
||||
\"body\": [
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"$DEPLOYMENT_TYPE\",
|
||||
\"weight\": \"Bolder\",
|
||||
\"size\": \"Large\"
|
||||
},
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"**App:** EasyPortal\",
|
||||
\"wrap\": true
|
||||
},
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"**Version:** [$CI_COMMIT_REF_NAME - $COMMIT_SHORT_SHA]($CI_PROJECT_URL/-/commit/$CI_COMMIT_SHA)\",
|
||||
\"wrap\": true,
|
||||
\"markdown\": true
|
||||
},
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"**Pipeline:** [Voir le pipeline]($CI_PIPELINE_URL)\",
|
||||
\"wrap\": true,
|
||||
\"markdown\": true
|
||||
},
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"**Auteur:** $GITLAB_USER_LOGIN\",
|
||||
\"wrap\": true
|
||||
},
|
||||
{
|
||||
\"type\": \"TextBlock\",
|
||||
\"text\": \"**Statut:** Échec ✗\",
|
||||
\"wrap\": true,
|
||||
\"color\": \"Attention\"
|
||||
}
|
||||
],
|
||||
\"actions\": [
|
||||
{
|
||||
\"type\": \"Action.OpenUrl\",
|
||||
\"title\": \"Voir le pipeline\",
|
||||
\"url\": \"$CI_PIPELINE_URL\"
|
||||
},
|
||||
{
|
||||
\"type\": \"Action.OpenUrl\",
|
||||
\"title\": \"Voir le commit\",
|
||||
\"url\": \"$CI_PROJECT_URL/-/commit/$CI_COMMIT_SHA\"
|
||||
}
|
||||
],
|
||||
\"\$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",
|
||||
\"version\": \"1.0\"
|
||||
}
|
||||
}
|
||||
]
|
||||
}" "$TEAMS_WEBHOOK_URL"
|
||||
|
|
@ -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;
|
||||
|
|
@ -41,6 +41,7 @@
|
|||
"symfony/property-info": "7.2.*",
|
||||
"symfony/rate-limiter": "7.2.*",
|
||||
"symfony/runtime": "7.2.*",
|
||||
"runtime/frankenphp-symfony": "^0.2.0",
|
||||
"symfony/security-bundle": "7.2.*",
|
||||
"symfony/serializer": "7.2.*",
|
||||
"symfony/stimulus-bundle": "^2.24",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "9c6693b9e0508ab0c1ff3ee95823be7d",
|
||||
"content-hash": "8868acbf6d26a43a2ba21777976b0844",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aws/aws-crt-php",
|
||||
|
|
@ -3765,6 +3765,58 @@
|
|||
},
|
||||
"time": "2019-03-08T08:55:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "runtime/frankenphp-symfony",
|
||||
"version": "0.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-runtime/frankenphp-symfony.git",
|
||||
"reference": "56822c3631d9522a3136a4c33082d006bdfe4bad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-runtime/frankenphp-symfony/zipball/56822c3631d9522a3136a4c33082d006bdfe4bad",
|
||||
"reference": "56822c3631d9522a3136a4c33082d006bdfe4bad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/runtime": "^5.4 || ^6.0 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Runtime\\FrankenPhpSymfony\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kévin Dunglas",
|
||||
"email": "kevin@dunglas.dev"
|
||||
}
|
||||
],
|
||||
"description": "FrankenPHP runtime for Symfony",
|
||||
"support": {
|
||||
"issues": "https://github.com/php-runtime/frankenphp-symfony/issues",
|
||||
"source": "https://github.com/php-runtime/frankenphp-symfony/tree/0.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/nyholm",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-12T12:06:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/asset",
|
||||
"version": "v7.2.0",
|
||||
|
|
@ -6972,7 +7024,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.32.0",
|
||||
"version": "v1.33.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
|
|
@ -7035,7 +7087,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -7046,6 +7098,10 @@
|
|||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
|
|
@ -7055,7 +7111,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.32.0",
|
||||
"version": "v1.33.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
|
|
@ -7116,7 +7172,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -7127,6 +7183,10 @@
|
|||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
|
|
@ -7136,7 +7196,7 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.32.0",
|
||||
"version": "v1.33.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
|
|
@ -7197,7 +7257,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -7208,6 +7268,10 @@
|
|||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
|
|
@ -7217,16 +7281,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php83",
|
||||
"version": "v1.32.0",
|
||||
"version": "v1.33.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php83.git",
|
||||
"reference": "2fb86d65e2d424369ad2905e83b236a8805ba491"
|
||||
"reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491",
|
||||
"reference": "2fb86d65e2d424369ad2905e83b236a8805ba491",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5",
|
||||
"reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -7273,7 +7337,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0"
|
||||
"source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -7284,12 +7348,16 @@
|
|||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
"time": "2025-07-08T02:45:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php84",
|
||||
|
|
@ -8389,16 +8457,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
"version": "v3.6.0",
|
||||
"version": "v3.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/service-contracts.git",
|
||||
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4"
|
||||
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
|
||||
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43",
|
||||
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -8452,7 +8520,7 @@
|
|||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.6.0"
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.6.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -8463,12 +8531,16 @@
|
|||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-04-25T09:37:31+00:00"
|
||||
"time": "2025-07-15T11:30:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/stimulus-bundle",
|
||||
|
|
@ -12444,7 +12516,7 @@
|
|||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {},
|
||||
"prefer-stable": true,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
|
@ -12453,6 +12525,6 @@
|
|||
"ext-iconv": "*",
|
||||
"ext-openssl": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
# 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 server - HTTPS is handled by caddy-proxy
|
||||
{$SERVER_NAME:80} {
|
||||
# Root directory
|
||||
root * /app/public
|
||||
|
||||
# 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
|
||||
# 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
|
||||
}
|
||||
handle @static {
|
||||
header Cache-Control "public, max-age=2592000, no-transform"
|
||||
file_server
|
||||
}
|
||||
|
||||
# PHP FrankenPHP handler
|
||||
php_server {
|
||||
# Resolve symlinks
|
||||
resolve_root_symlink
|
||||
}
|
||||
|
||||
# Logging
|
||||
log {
|
||||
output file /var/log/caddy/access.log
|
||||
format json
|
||||
}
|
||||
}
|
||||
|
|
@ -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