# ============================================================================= # Stage 1: Build Frontend # ============================================================================= FROM node:20-alpine AS frontend-builder WORKDIR /app/frontend # Copy frontend package files COPY frontend/package*.json ./ # Install dependencies (including dev for build) RUN npm ci # Copy frontend source COPY frontend/ ./ # Build frontend RUN npm run build # ============================================================================= # Stage 2: Build Backend Dependencies # ============================================================================= FROM php:8.3-fpm-alpine AS backend-builder # Install build dependencies RUN apk add --no-cache \ libpng-dev \ oniguruma-dev \ libxml2-dev \ zip \ unzip # Install PHP extensions RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd opcache # Install Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer WORKDIR /var/www/html # Copy composer files COPY backend/composer.json backend/composer.lock ./ # Install PHP dependencies (production only) RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist # Copy backend source COPY backend/ ./ # Generate optimized autoloader RUN composer dump-autoload --optimize --classmap-authoritative # ============================================================================= # Stage 3: Final Production Image (All-in-One) # ============================================================================= FROM php:8.3-fpm-alpine # Install runtime dependencies RUN apk add --no-cache \ libpng \ oniguruma \ libxml2 \ nginx \ supervisor \ mariadb \ mariadb-client \ redis \ curl \ bash # Copy PHP extensions from backend-builder COPY --from=backend-builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/ COPY --from=backend-builder /usr/local/etc/php/conf.d/docker-php-ext-*.ini /usr/local/etc/php/conf.d/ # Configure PHP for production RUN echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/opcache.ini && \ echo "opcache.memory_consumption=128" >> /usr/local/etc/php/conf.d/opcache.ini && \ echo "opcache.max_accelerated_files=10000" >> /usr/local/etc/php/conf.d/opcache.ini && \ echo "opcache.validate_timestamps=0" >> /usr/local/etc/php/conf.d/opcache.ini && \ echo "expose_php=0" >> /usr/local/etc/php/conf.d/security.ini && \ echo "display_errors=0" >> /usr/local/etc/php/conf.d/security.ini && \ echo "log_errors=1" >> /usr/local/etc/php/conf.d/security.ini # Create application user RUN addgroup -g 1000 appuser && \ adduser -D -u 1000 -G appuser appuser && \ mkdir -p /var/www/html /usr/share/nginx/html && \ chown -R appuser:appuser /var/www/html /usr/share/nginx/html # Create necessary directories for services RUN mkdir -p /run/nginx /run/mysqld /var/lib/mysql /var/log/supervisor /data/redis && \ chown -R appuser:appuser /run/nginx /usr/share/nginx/html && \ chown -R mysql:mysql /run/mysqld /var/lib/mysql && \ chown -R redis:redis /data/redis # Copy backend from builder WORKDIR /var/www/html COPY --from=backend-builder --chown=appuser:appuser /var/www/html ./ # Create Laravel required directories RUN mkdir -p storage/framework/{sessions,views,cache} \ storage/logs \ bootstrap/cache && \ chown -R appuser:appuser storage bootstrap/cache && \ chmod -R 775 storage bootstrap/cache # Copy frontend built assets COPY --from=frontend-builder --chown=appuser:appuser /app/frontend/dist /usr/share/nginx/html # Copy nginx configurations COPY docker/nginx/production.conf /etc/nginx/http.d/default.conf # Copy supervisor configuration COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf # Initialize MariaDB data directory RUN mysql_install_db --user=mysql --datadir=/var/lib/mysql # Copy entrypoint script COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ CMD curl -f http://localhost/up || exit 1 # Expose HTTP port EXPOSE 80 # Set entrypoint ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] # Start supervisor CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]