first commit
This commit is contained in:
54
docker/nginx/default.conf
Normal file
54
docker/nginx/default.conf
Normal file
@@ -0,0 +1,54 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
root /var/www/app/public;
|
||||
index index.php;
|
||||
|
||||
# ── En-têtes de sécurité HTTP ────────────────────────────────────────────
|
||||
# Empêche le chargement de la page dans une iframe (clickjacking)
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
# Désactive le sniffing MIME : le navigateur respecte le Content-Type déclaré
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
# Limite les informations transmises dans le Referer aux pages externes
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
# Désactive les fonctionnalités navigateur non utilisées
|
||||
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
|
||||
|
||||
# Fichiers statiques servis directement par Nginx, sans passer par PHP.
|
||||
# expires 1y active le cache navigateur longue durée.
|
||||
location ~* \.(css|js|ico|png|jpg|jpeg|gif|svg|webp|woff2)$ {
|
||||
try_files $uri =404;
|
||||
expires 1y;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Bloquer l'exécution de PHP dans le répertoire des uploads.
|
||||
location ~* /media/.*\.php$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Front controller Slim : toute URL sans fichier correspondant
|
||||
# est renvoyée vers index.php pour être traitée par le routeur.
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
}
|
||||
|
||||
# PHP-FPM via réseau Docker interne (port 9000 par défaut).
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass app:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
|
||||
# Transmet les en-têtes du reverse proxy amont (Caddy hôte, etc.)
|
||||
# pour que l'application connaisse l'IP réelle du client et le protocole.
|
||||
fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
|
||||
fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto;
|
||||
}
|
||||
|
||||
# Bloquer l'accès aux fichiers sensibles.
|
||||
location ~ /\.(env|git|htaccess) {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
44
docker/php/Dockerfile
Normal file
44
docker/php/Dockerfile
Normal file
@@ -0,0 +1,44 @@
|
||||
# ── Stage 1 : compilation des assets ────────────────────────────────────────
|
||||
FROM node:20-slim AS assets
|
||||
|
||||
WORKDIR /build
|
||||
COPY package.json package-lock.json ./
|
||||
# Layer séparé : npm ci n'est relancé que si package-lock.json change.
|
||||
# npm run build est dans un layer distinct : toute modification dans assets/
|
||||
# invalide uniquement ce layer, sans réinstaller les packages.
|
||||
RUN npm ci
|
||||
COPY assets/ assets/
|
||||
RUN npm run build
|
||||
|
||||
# ── Stage 2 : image PHP de production ───────────────────────────────────────
|
||||
FROM php:8.3-fpm
|
||||
|
||||
# Extensions système et PHP dans un seul layer
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libsqlite3-dev libxml2-dev libonig-dev \
|
||||
libpng-dev libjpeg62-turbo-dev libwebp-dev unzip \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& docker-php-ext-configure gd --with-webp --with-jpeg \
|
||||
&& docker-php-ext-install pdo_sqlite mbstring dom fileinfo gd
|
||||
|
||||
COPY docker/php/php.ini /usr/local/etc/php/conf.d/custom.ini
|
||||
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||
|
||||
WORKDIR /var/www/app
|
||||
|
||||
# Dépendances Composer — layer mis en cache tant que les lock files n'ont pas changé
|
||||
COPY composer.json composer.lock ./
|
||||
RUN composer install --no-dev --optimize-autoloader --no-interaction
|
||||
|
||||
# Code source + assets compilés depuis le stage 1
|
||||
COPY . .
|
||||
COPY --from=assets /build/public/assets/ public/assets/
|
||||
|
||||
# Archive les migrations hors du WORKDIR : le bind mount ./data/database/
|
||||
# écrase /var/www/app/database/ au démarrage — l'entrypoint recopie depuis ici.
|
||||
RUN cp -r database /database.baked
|
||||
|
||||
COPY --chmod=755 docker/php/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["entrypoint.sh"]
|
||||
CMD ["php-fpm"]
|
||||
42
docker/php/entrypoint.sh
Normal file
42
docker/php/entrypoint.sh
Normal file
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# public/ → assets compilés, index.php
|
||||
# Synchronisé à chaque démarrage pour déployer les nouveaux assets.
|
||||
# media/ est exclu : c'est un bind mount séparé contenant les uploads
|
||||
# utilisateurs — le copier dans sa propre destination causerait une erreur.
|
||||
for item in /var/www/app/public/*; do
|
||||
name=$(basename "$item")
|
||||
[ "$name" = "media" ] && continue
|
||||
cp -a "$item" /data/public/
|
||||
done
|
||||
|
||||
# database/ → migrations depuis l'archive baked.
|
||||
# /var/www/app/database/ est un bind mount vide au premier démarrage :
|
||||
# les migrations sont copiées depuis /database.baked/ qui n'est pas monté.
|
||||
# cp -rn préserve app.sqlite sur les déploiements suivants.
|
||||
cp -rn /database.baked/. /var/www/app/database/ 2>/dev/null || true
|
||||
|
||||
# Pré-création de public/media/ pour que les permissions soient fixées
|
||||
# ici, en même temps que les autres répertoires persistants, plutôt qu'à
|
||||
# la première requête par Bootstrap::checkDirectories().
|
||||
mkdir -p /var/www/app/public/media
|
||||
|
||||
# Permissions sur les bind mounts : doit s'exécuter en root avant
|
||||
# le démarrage de PHP-FPM. Bootstrap.php crée ensuite les sous-répertoires
|
||||
# (var/cache/twig, var/cache/htmlpurifier, var/logs) à la première requête
|
||||
# avec les bonnes permissions.
|
||||
chown -R www-data:www-data /data /var/www/app/database /var/www/app/var /var/www/app/public/media
|
||||
|
||||
# Invalider les caches compilés à chaque déploiement.
|
||||
# - Twig : les templates compilés peuvent être obsolètes après modification d'une vue
|
||||
# ou d'une extension Twig.
|
||||
# - DI : le container PHP-DI compilé doit être regénéré après tout changement
|
||||
# dans config/container.php. Sans cette ligne, la première requête compile
|
||||
# un container incohérent et toutes les suivantes échouent avec une erreur 500.
|
||||
rm -rf /var/www/app/var/cache/twig/*
|
||||
rm -rf /var/www/app/var/cache/di/*
|
||||
|
||||
# Passe la main à la commande principale (php-fpm) en remplaçant le processus
|
||||
# entrypoint par php-fpm PID 1 — requis pour la gestion des signaux Docker.
|
||||
exec "$@"
|
||||
14
docker/php/php.ini
Normal file
14
docker/php/php.ini
Normal file
@@ -0,0 +1,14 @@
|
||||
; Limites upload — doivent être cohérentes avec UPLOAD_MAX_SIZE dans .env.
|
||||
upload_max_filesize = 6M
|
||||
post_max_size = 8M
|
||||
|
||||
; Ne pas exposer la version PHP dans l'en-tête X-Powered-By
|
||||
expose_php = Off
|
||||
|
||||
; Remonte les erreurs PHP vers Docker
|
||||
log_errors = On
|
||||
error_log = /dev/stderr
|
||||
|
||||
; Renommer le cookie de session pour éviter le fingerprint PHP (PHPSESSID par défaut)
|
||||
; La valeur doit être synchronisée avec session_name() dans public/index.php si modifiée.
|
||||
session.name = sid
|
||||
Reference in New Issue
Block a user