# Dockerfile für PHP-FPM ARG PHP_VERSION=8.5.0RC4 # Override via --build-arg PHP_VERSION=8.5.0RCX to track upstream releases FROM php:${PHP_VERSION}-fpm AS base # System-Abhängigkeiten: Werden selten geändert, daher ein eigener Layer RUN apt-get update && apt-get install -y \ git \ unzip \ libzip-dev \ zip \ libpng-dev \ libjpeg-dev \ libfreetype6-dev \ libwebp-dev \ libavif-dev \ libxpm-dev \ libsodium-dev \ libpq-dev \ ca-certificates \ curl \ gnupg \ lsb-release \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # Install Docker CLI (for Docker management from within container) RUN install -m 0755 -d /etc/apt/keyrings \ && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \ && chmod a+r /etc/apt/keyrings/docker.gpg \ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \ && apt-get update \ && apt-get install -y docker-cli \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* RUN docker-php-ext-configure gd \ --with-freetype \ --with-jpeg \ --with-webp \ --with-avif \ --with-xpm \ && docker-php-ext-install -j$(nproc) gd # Install PHP extensions RUN docker-php-ext-install -j$(nproc) \ zip \ pdo \ pdo_mysql \ pdo_pgsql \ pcntl \ posix \ shmop \ bcmath # Note: ext-uri is built-in to PHP 8.5+ core, no installation needed # Install PECL extensions (use beta redis for PHP 8.5 compatibility) RUN pecl install apcu redis-6.3.0RC1 \ && docker-php-ext-enable apcu redis 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 # Composer installieren RUN curl -sS https://getcomposer.org/installer | php \ && mv composer.phar /usr/local/bin/composer # Installiere Xdebug nur im Entwicklungsmodus ARG ENV=production RUN if [ "$ENV" = "dev" ]; then \ pecl install xdebug \ && docker-php-ext-enable xdebug; \ fi WORKDIR /var/www/html # Composer Dependencies (für besseres Caching) COPY composer.json ./ COPY composer.lock* ./ RUN composer install --no-scripts --no-autoloader --ignore-platform-reqs || \ (composer install --no-scripts --no-autoloader --no-dev --ignore-platform-reqs || \ echo "Composer install failed, continuing without dependencies") # Kopiere PHP-Konfigurationen COPY docker/php/php.common.ini /usr/local/etc/php/php.common.ini COPY docker/php/php.${ENV}.ini /usr/local/etc/php/php.ini # Kopiere PHP-FPM Pool-Konfiguration COPY docker/php/zz-docker.conf /usr/local/etc/php-fpm.d/zz-docker.conf COPY docker/php/zzzz-override.conf /usr/local/etc/php-fpm.d/zzzz-override.conf # Xdebug-Konfiguration nur wenn dev RUN if [ "$ENV" = "dev" ] && [ -f docker/php/xdebug.ini ]; then \ cp docker/php/xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \ fi # Kopiere den Rest des Projekts COPY . . # Optimiere Autoloader RUN composer dump-autoload --optimize # <<--- ALLE zusätzlichen System-Dateien und chmod noch als root! COPY docker/php/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh RUN chmod +x /usr/local/bin/docker-entrypoint.sh # Remove entire storage directory tree copied from COPY . . # But we MUST create the empty parent directory so Docker can mount subdirectories RUN rm -rf /var/www/html/storage && mkdir -p /var/www/html/storage # CRITICAL: The storage directory must exist as an empty directory in the image # This allows Docker to mount Named Volumes to subdirectories (storage/cache, storage/logs, etc.) # without needing to create the parent directory at runtime (which fails due to read-only overlay) # Create appuser but DON'T switch yet - let entrypoint handle volumes first RUN groupadd -g 1000 appuser && useradd -u 1000 -g appuser -m appuser RUN chown -R appuser:appuser /var/www/html # Install gosu for secure user switching in entrypoint (Debian alternative to su-exec) RUN apt-get update && apt-get install -y gosu && apt-get clean && rm -rf /var/lib/apt/lists/* # Note: USER switch happens in entrypoint AFTER volumes are mounted ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] CMD ["php-fpm"] ############################################# # Production Stages (Extended Build) ############################################# # Stage: Composer Dependencies (Production) FROM base AS composer-deps-production WORKDIR /app # Copy composer files COPY composer.json composer.lock ./ # Install production dependencies only 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 ARG PHP_VERSION=8.5.0RC4 FROM php:${PHP_VERSION}-fpm AS production # Install system dependencies + nginx for production RUN apt-get update && apt-get install -y \ nginx \ curl \ 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 (same as base) 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 # 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"]