# Multi-stage build for Pixelfed - optimized base image FROM php:8.3-fpm-alpine AS builder LABEL org.opencontainers.image.title="Pixelfed Base" \ org.opencontainers.image.description="Shared base image for Pixelfed photo sharing platform" \ org.opencontainers.image.source="https://github.com/pixelfed/pixelfed" \ org.opencontainers.image.vendor="Keyboard Vagabond" # Set environment variables ENV PIXELFED_VERSION=v0.12.6 ENV TZ=UTC ENV APP_ENV=production ENV APP_DEBUG=false # Install build dependencies in a single layer RUN apk add --no-cache \ ca-certificates \ git \ curl \ zip \ unzip \ # Build dependencies for PHP extensions libpng-dev \ oniguruma-dev \ libxml2-dev \ freetype-dev \ libjpeg-turbo-dev \ libzip-dev \ postgresql-dev \ icu-dev \ gettext-dev \ imagemagick-dev \ # Node.js for asset compilation nodejs \ npm \ # Build tools build-base \ autoconf \ pkgconfig \ $PHPIZE_DEPS # Install PHP extensions (done ONCE - will be copied to runtime stage) RUN docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j$(nproc) \ pdo_pgsql \ pgsql \ gd \ zip \ intl \ bcmath \ exif \ pcntl \ opcache \ # Build imagick from source for PHP 8.3 compatibility && git clone https://github.com/Imagick/imagick.git --depth 1 -b master /tmp/imagick \ && cd /tmp/imagick \ && phpize \ && ./configure \ && make \ && make install \ && docker-php-ext-enable imagick \ && rm -rf /tmp/imagick # Install Composer COPY --from=composer:2 /usr/bin/composer /usr/bin/composer # Set working directory WORKDIR /var/www/pixelfed # Create pixelfed user RUN addgroup -g 1000 pixelfed \ && adduser -u 1000 -G pixelfed -s /bin/sh -D pixelfed # Clone Pixelfed source RUN git clone --depth 1 --branch ${PIXELFED_VERSION} https://github.com/pixelfed/pixelfed.git . \ && chown -R pixelfed:pixelfed /var/www/pixelfed # Switch to pixelfed user for dependency installation USER pixelfed # Install PHP dependencies and clear any cached Laravel configuration RUN composer install --no-dev --optimize-autoloader --no-interaction \ && php artisan config:clear || true \ && php artisan route:clear || true \ && php artisan view:clear || true \ && php artisan cache:clear || true \ && rm -f bootstrap/cache/packages.php bootstrap/cache/services.php || true \ && php artisan package:discover --ansi || true # Build frontend assets (skip post-install scripts to avoid node-datachannel compilation) RUN echo "ignore-scripts=true" > .npmrc \ && npm ci \ && npm run production \ && rm -rf node_modules .npmrc # Switch back to root for final setup USER root # ================================ # Runtime stage - optimized final image # ================================ FROM php:8.3-fpm-alpine AS pixelfed-base LABEL org.opencontainers.image.title="Pixelfed Base" \ org.opencontainers.image.description="Shared base image for Pixelfed photo sharing platform" \ org.opencontainers.image.source="https://github.com/pixelfed/pixelfed" \ org.opencontainers.image.vendor="Keyboard Vagabond" # Set environment variables ENV TZ=UTC ENV APP_ENV=production ENV APP_DEBUG=false # Install only runtime dependencies (no -dev packages, no build tools) RUN apk add --no-cache \ ca-certificates \ curl \ su-exec \ dcron \ # Runtime libraries for PHP extensions libpng \ oniguruma \ libxml2 \ freetype \ libjpeg-turbo \ libzip \ libpq \ icu-libs \ gettext \ # ImageMagick runtime libraries imagemagick \ imagemagick-libs \ # Image optimization tools (required by Pixelfed) jpegoptim \ optipng \ pngquant \ gifsicle \ # FFmpeg for video thumbnails (required by Pixelfed) ffmpeg \ && rm -rf /var/cache/apk/* # Copy PHP extensions from builder (KEY OPTIMIZATION - no recompilation!) COPY --from=builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/ COPY --from=builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/ # Create pixelfed user RUN addgroup -g 1000 pixelfed \ && adduser -u 1000 -G pixelfed -s /bin/sh -D pixelfed # Set working directory WORKDIR /var/www/pixelfed # Copy application from builder (source + compiled assets + vendor dependencies) COPY --from=builder --chown=pixelfed:pixelfed /var/www/pixelfed /var/www/pixelfed # Copy custom assets (logo, banners, etc.) to override defaults COPY --chown=pixelfed:pixelfed custom-assets/img/*.svg /var/www/pixelfed/public/img/ # Clear any cached configuration files and set proper permissions RUN rm -rf /var/www/pixelfed/bootstrap/cache/*.php || true \ && chmod -R 755 /var/www/pixelfed/storage \ && chmod -R 755 /var/www/pixelfed/bootstrap/cache \ && chown -R pixelfed:pixelfed /var/www/pixelfed/bootstrap/cache # Configure PHP OPcache for production performance RUN { \ echo "opcache.enable=1"; \ echo "opcache.revalidate_freq=0"; \ echo "opcache.validate_timestamps=0"; \ echo "opcache.max_accelerated_files=10000"; \ echo "opcache.memory_consumption=192"; \ echo "opcache.max_wasted_percentage=10"; \ echo "opcache.interned_strings_buffer=16"; \ echo "opcache.fast_shutdown=1"; \ } >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini # Copy shared entrypoint utilities COPY entrypoint-common.sh /usr/local/bin/entrypoint-common.sh RUN chmod +x /usr/local/bin/entrypoint-common.sh