Files
Classeo/backend/Dockerfile
Mathias STRASSER c5e6c1d810 feat: Activation de compte utilisateur avec validation token
L'inscription Classeo se fait via invitation : un admin crée un compte,
l'utilisateur reçoit un lien d'activation par email pour définir son
mot de passe. Ce flow sécurisé évite les inscriptions non autorisées
et garantit que seuls les utilisateurs légitimes accèdent au système.

Points clés de l'implémentation :
- Tokens d'activation à usage unique stockés en cache (Redis/filesystem)
- Validation du consentement parental pour les mineurs < 15 ans (RGPD)
- L'échec d'activation ne consume pas le token (retry possible)
- Users dans un cache séparé sans TTL (pas d'expiration)
- Hot reload en dev (FrankenPHP sans mode worker)

Story: 1.3 - Inscription et activation de compte
2026-01-31 19:34:03 +01:00

146 lines
5.0 KiB
Docker

# syntax=docker/dockerfile:1
# =============================================================================
# PHP 8.5 + FrankenPHP - Backend Classeo
# =============================================================================
FROM dunglas/frankenphp:1-php8.5-alpine AS base
# Install system dependencies
RUN apk add --no-cache \
acl \
fcgi \
file \
gettext \
git \
icu-dev \
libzip-dev \
postgresql-dev \
rabbitmq-c-dev \
linux-headers \
$PHPIZE_DEPS
# Install PHP extensions (opcache is pre-installed in FrankenPHP)
RUN docker-php-ext-install intl pdo_pgsql zip sockets
# Install AMQP extension for RabbitMQ
RUN pecl install amqp && docker-php-ext-enable amqp
# Install Redis extension
RUN pecl install redis && docker-php-ext-enable redis
# Install Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# Set working directory
WORKDIR /app
# Configure PHP for production
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# Custom PHP configuration
RUN echo "opcache.enable=1" >> "$PHP_INI_DIR/conf.d/opcache.ini" \
&& echo "opcache.memory_consumption=256" >> "$PHP_INI_DIR/conf.d/opcache.ini" \
&& echo "opcache.interned_strings_buffer=16" >> "$PHP_INI_DIR/conf.d/opcache.ini" \
&& echo "opcache.max_accelerated_files=20000" >> "$PHP_INI_DIR/conf.d/opcache.ini" \
&& echo "opcache.validate_timestamps=0" >> "$PHP_INI_DIR/conf.d/opcache.ini" \
&& echo "realpath_cache_size=4096K" >> "$PHP_INI_DIR/conf.d/opcache.ini" \
&& echo "realpath_cache_ttl=600" >> "$PHP_INI_DIR/conf.d/opcache.ini"
# =============================================================================
# Development stage
# =============================================================================
FROM base AS dev
# Install gosu for proper user switching
ENV GOSU_VERSION=1.17
RUN set -eux; \
apk add --no-cache --virtual .gosu-deps dpkg gnupg; \
dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
chmod +x /usr/local/bin/gosu; \
gosu --version; \
gosu nobody true; \
apk del --no-network .gosu-deps
# Enable opcache revalidation for dev (zz- prefix loads last alphabetically)
RUN echo "opcache.validate_timestamps=1" >> "$PHP_INI_DIR/conf.d/zz-opcache-dev.ini"
# Enable Xdebug for development
RUN pecl install xdebug && docker-php-ext-enable xdebug
RUN echo "xdebug.mode=develop,debug,coverage" >> "$PHP_INI_DIR/conf.d/xdebug.ini" \
&& echo "xdebug.client_host=host.docker.internal" >> "$PHP_INI_DIR/conf.d/xdebug.ini" \
&& echo "xdebug.start_with_request=trigger" >> "$PHP_INI_DIR/conf.d/xdebug.ini"
# Caddy config for FrankenPHP
ENV SERVER_NAME=:8000
# In dev mode, we do NOT use worker mode to enable automatic file reloading
# Each request loads PHP fresh, so code changes are picked up immediately
# Worker mode is only used in production for performance
ENV FRANKENPHP_CONFIG=""
# Entrypoint: detect host UID/GID and run as matching user
# Uses gosu with UID:GID directly (no need to create user in Dockerfile)
COPY --chmod=755 <<'EOF' /usr/local/bin/docker-entrypoint.sh
#!/bin/sh
set -e
# Detect UID/GID from mounted /app directory
HOST_UID=$(stat -c %u /app)
HOST_GID=$(stat -c %g /app)
# If root owns /app, run as root (CI environment or volume not mounted)
if [ "$HOST_UID" = "0" ]; then
# Install dependencies if not present
if [ ! -f /app/vendor/autoload.php ]; then
echo "Installing Composer dependencies..."
composer install --prefer-dist --no-progress --no-interaction
fi
mkdir -p /app/var/cache /app/var/log
exec "$@"
fi
# Ensure directories exist with correct ownership
mkdir -p /app/var/cache /app/var/log /data /config
chown -R "$HOST_UID:$HOST_GID" /app/var /data /config 2>/dev/null || true
# Install Composer dependencies if not present (as host user)
if [ ! -f /app/vendor/autoload.php ]; then
echo "Installing Composer dependencies..."
gosu "$HOST_UID:$HOST_GID" composer install --prefer-dist --no-progress --no-interaction
fi
# Run command as host user via gosu (using UID:GID directly)
exec gosu "$HOST_UID:$HOST_GID" "$@"
EOF
EXPOSE 8000
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["frankenphp", "run", "--config", "/etc/caddy/Caddyfile"]
# =============================================================================
# Production stage
# =============================================================================
FROM base AS prod
ENV APP_ENV=prod
ENV SERVER_NAME=:8000
ENV FRANKENPHP_CONFIG="worker ./public/index.php"
# Copy application files
COPY . /app
# Install dependencies (prod only, optimized)
RUN composer install --no-dev --prefer-dist --no-progress --no-interaction --optimize-autoloader
# Warmup cache
RUN php bin/console cache:warmup
# Ensure var directory exists with proper permissions
RUN mkdir -p var/cache var/log && chmod -R 755 var
EXPOSE 8000
CMD ["frankenphp", "run", "--config", "/etc/caddy/Caddyfile"]