# ----------------------------------------------------------------------------- # Base PHP-FPM with Composer + Symfony-friendly extensions # ----------------------------------------------------------------------------- FROM php:8.2-fpm-alpine AS base ARG APP_ENV=dev ENV APP_ENV=${APP_ENV} WORKDIR /var/www/html # System dependencies shared across images RUN apk add --no-cache \ bash \ git \ unzip \ icu-dev \ libpng-dev \ libjpeg-turbo-dev \ libwebp-dev \ libzip-dev \ oniguruma-dev \ libxml2-dev \ postgresql-dev \ sqlite-dev \ zlib-dev \ su-exec # PHP extensions commonly used by Symfony (plus both Postgres + SQLite) RUN docker-php-ext-configure gd --with-jpeg --with-webp \ && docker-php-ext-install -j"$(nproc)" \ intl \ gd \ pdo_pgsql \ pdo_sqlite \ opcache \ mbstring \ zip \ xml # Composer available in every stage (dev + prod) COPY --from=composer:2.7 /usr/bin/composer /usr/bin/composer # Recommended PHP settings (tweak as needed) RUN { \ echo "memory_limit=512M"; \ echo "upload_max_filesize=50M"; \ echo "post_max_size=50M"; \ echo "date.timezone=UTC"; \ } > /usr/local/etc/php/conf.d/php-recommended.ini \ && { \ echo "opcache.enable=1"; \ echo "opcache.enable_cli=1"; \ echo "opcache.memory_consumption=256"; \ echo "opcache.interned_strings_buffer=16"; \ echo "opcache.max_accelerated_files=20000"; \ echo "opcache.validate_timestamps=0"; \ echo "opcache.jit=tracing"; \ echo "opcache.jit_buffer_size=128M"; \ } > /usr/local/etc/php/conf.d/opcache-recommended.ini # Small healthcheck file for HTTP probes RUN mkdir -p public && printf "OK" > public/healthz # Ensure unprivileged app user exists RUN addgroup -g 1000 app && adduser -D -G app -u 1000 app \ && chown -R www-data:www-data /var/www # ----------------------------------------------------------------------------- # Development image (mount your code via docker-compose volumes) # ----------------------------------------------------------------------------- FROM base AS dev ARG APP_ENV=dev ENV APP_ENV=${APP_ENV} ENV APP_DEBUG=1 # Optional: enable Xdebug by uncommenting below # RUN apk add --no-cache $PHPIZE_DEPS \ # && pecl install xdebug \ # && docker-php-ext-enable xdebug \ # && { \ # echo "xdebug.mode=debug,develop"; \ # echo "xdebug.client_host=host.docker.internal"; \ # } > /usr/local/etc/php/conf.d/xdebug.ini ENV COMPOSER_CACHE_DIR=/tmp/composer CMD ["php-fpm"] # ----------------------------------------------------------------------------- # Production image (copies your app + installs deps + warms cache) # ----------------------------------------------------------------------------- FROM base AS prod ARG APP_ENV=prod ARG BUILD_APP_SECRET=build-secret ENV APP_ENV=${APP_ENV} ENV APP_DEBUG=0 \ DATABASE_DRIVER=sqlite \ DATABASE_SQLITE_PATH=/var/www/html/var/data/database.sqlite \ RUN_MIGRATIONS_ON_START=1 # Copy only composer manifests for layer caching COPY composer.json composer.lock* symfony.lock* ./ # Install vendors (cached) RUN --mount=type=cache,target=/tmp/composer \ if [ -f composer.json ]; then \ composer install --no-dev --prefer-dist --no-interaction --no-progress --no-scripts; \ fi # Copy the rest of the app COPY . /var/www/html # Finalize install & warm cache RUN if [ -f bin/console ]; then \ set -ex; \ export APP_SECRET="${BUILD_APP_SECRET}"; \ composer dump-autoload --no-dev --optimize; \ php bin/console cache:clear --no-warmup; \ php bin/console cache:warmup; \ mkdir -p var var/data public/uploads; \ chown -R www-data:www-data var public/uploads; \ fi # Runtime web stack (nginx + supervisor) for a single immutable container RUN apk add --no-cache nginx supervisor curl COPY docker/prod/nginx.conf /etc/nginx/http.d/default.conf COPY docker/prod/supervisord.conf /etc/supervisor/conf.d/app.conf COPY docker/prod/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh \ && mkdir -p /run/nginx /var/log/supervisor \ && chown -R www-data:www-data /var/www/html EXPOSE 8080 ENTRYPOINT ["/entrypoint.sh"] CMD ["supervisord", "-c", "/etc/supervisor/conf.d/app.conf"]