# Production Dockerfile - Multi-Stage Build # Stage: Composer Dependencies (Production) FROM php:8.5.0RC3-fpm AS composer-deps-production WORKDIR /app # Copy composer files COPY composer.json composer.lock ./ # Install system dependencies for Composer RUN apt-get update && apt-get install -y \ git \ unzip \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # Install Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer RUN composer install \ --no-dev \ --no-scripts \ --no-autoloader \ --ignore-platform-reqs \ --prefer-dist # Copy application code COPY . . # Generate optimized autoloader RUN composer dump-autoload --optimize --classmap-authoritative # Stage: Frontend Build FROM node:20-alpine AS frontend-build WORKDIR /app # Copy package files COPY package.json package-lock.json ./ # Install npm dependencies RUN npm ci --production=false # Copy source files needed for build COPY resources ./resources COPY vite.config.js ./ COPY tsconfig.json ./ # Build production assets RUN npm run build # Stage: Production Runtime FROM php:8.5.0RC3-fpm AS production # Install system dependencies + nginx for production RUN apt-get update && apt-get install -y \ nginx \ curl \ git \ unzip \ libzip-dev \ libpng-dev \ libjpeg-dev \ libfreetype6-dev \ libwebp-dev \ libavif-dev \ libxpm-dev \ libsodium-dev \ libpq-dev \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # Install PHP extensions RUN docker-php-ext-configure gd \ --with-freetype \ --with-jpeg \ --with-webp \ --with-avif \ --with-xpm \ && docker-php-ext-install -j$(nproc) gd RUN docker-php-ext-install -j$(nproc) \ zip \ pdo \ pdo_mysql \ pdo_pgsql \ pcntl \ posix \ shmop \ bcmath \ sodium # Install PECL extensions RUN pecl install apcu redis-6.3.0RC1 \ && docker-php-ext-enable apcu redis # Configure APCu RUN echo "apc.enable_cli=1" >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini \ && echo "apc.shm_size=128M" >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini # Install Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer # Set working directory WORKDIR /var/www/html # Configure PHP for production COPY docker/php/php.production.ini /usr/local/etc/php/conf.d/zzz-custom.ini COPY docker/php/opcache.ini /usr/local/etc/php/conf.d/opcache.ini # Configure PHP-FPM (clear_env = no for Docker secrets) COPY docker/php/www.production.conf /usr/local/etc/php-fpm.d/www.conf # Configure Nginx for Traefik integration COPY docker/nginx/nginx.production.conf /etc/nginx/nginx.conf COPY docker/nginx/default.traefik.conf /etc/nginx/sites-available/default RUN ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default # Copy application code and dependencies COPY --chown=www-data:www-data . . COPY --from=composer-deps-production --chown=www-data:www-data /app/vendor ./vendor COPY --from=frontend-build --chown=www-data:www-data /app/public/assets ./public/assets COPY --from=frontend-build --chown=www-data:www-data /app/public/.vite ./public/.vite # Create required directories RUN mkdir -p storage/logs storage/cache storage/uploads \ && chown -R www-data:www-data storage \ && chmod -R 775 storage # Copy entrypoint script for production COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh # Healthcheck HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \ CMD curl -f http://localhost/health || exit 1 # Expose HTTP only (Traefik handles HTTPS) EXPOSE 80 # Use production entrypoint ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] CMD ["nginx-php-fpm"]