# Multi-stage build for Pixelfed - optimized base image FROM php:8.3-fpm-alpine AS builder # Set environment variables ENV PIXELFED_VERSION=v0.12.6 ENV TZ=UTC ENV APP_ENV=production ENV APP_DEBUG=false # Use HTTP repositories and install build dependencies RUN echo "http://dl-cdn.alpinelinux.org/alpine/v3.22/main" > /etc/apk/repositories \ && echo "http://dl-cdn.alpinelinux.org/alpine/v3.22/community" >> /etc/apk/repositories \ && apk update \ && 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 and build tools for asset compilation nodejs \ npm \ # Compilation tools for native modules build-base \ python3 \ make \ # Additional build tools for PECL extensions autoconf \ pkgconfig \ $PHPIZE_DEPS # Install PHP extensions 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 \ # Install ImageMagick PHP extension via PECL && pecl install imagick \ && docker-php-ext-enable 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 # Install Node.js and build assets (skip post-install scripts to avoid node-datachannel compilation) USER root RUN apk add --no-cache nodejs npm USER pixelfed 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 # 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 echo "http://dl-cdn.alpinelinux.org/alpine/v3.22/main" > /etc/apk/repositories \ && echo "http://dl-cdn.alpinelinux.org/alpine/v3.22/community" >> /etc/apk/repositories \ && apk update \ && apk add --no-cache \ ca-certificates \ curl \ su-exec \ dcron \ # Runtime libraries for PHP extensions (no -dev versions) libpng \ oniguruma \ libxml2 \ freetype \ libjpeg-turbo \ libzip \ libpq \ icu \ gettext \ # Image optimization tools (runtime only) jpegoptim \ optipng \ pngquant \ gifsicle \ imagemagick \ ffmpeg \ && rm -rf /var/cache/apk/* # Re-install PHP extensions in runtime stage (this ensures compatibility) RUN apk add --no-cache --virtual .build-deps \ libpng-dev \ oniguruma-dev \ libxml2-dev \ freetype-dev \ libjpeg-turbo-dev \ libzip-dev \ postgresql-dev \ icu-dev \ gettext-dev \ imagemagick-dev \ # Additional build tools for PECL extensions autoconf \ pkgconfig \ git \ $PHPIZE_DEPS \ && 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 \ # Install ImageMagick PHP extension from source (PHP 8.3 compatibility) && git clone https://github.com/Imagick/imagick.git --depth 1 /tmp/imagick \ && cd /tmp/imagick \ && git fetch origin master \ && git switch master \ && phpize \ && ./configure \ && make \ && make install \ && docker-php-ext-enable imagick \ && rm -rf /tmp/imagick \ && apk del .build-deps \ && rm -rf /var/cache/apk/* # 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. Doesn't override the png versions. 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 for better performance RUN echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini \ && echo "opcache.revalidate_freq=0" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini \ && echo "opcache.validate_timestamps=0" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini \ && echo "opcache.max_accelerated_files=10000" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini \ && echo "opcache.memory_consumption=192" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini \ && echo "opcache.max_wasted_percentage=10" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini \ && echo "opcache.interned_strings_buffer=16" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini \ && 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