pixelfed/contrib/docker/Dockerfile
2023-12-28 23:46:59 +00:00

321 lines
9.2 KiB
Docker

# syntax=docker/dockerfile:1
# See https://hub.docker.com/r/docker/dockerfile
#######################################################
# Configuration
#######################################################
ARG COMPOSER_VERSION="2.6"
ARG NGINX_VERSION=1.25.3
ARG FOREGO_VERSION=0.17.2
ARG PECL_EXTENSIONS_EXTRA=""
ARG PECL_EXTENSIONS="imagick redis"
ARG PHP_BASE_TYPE="apache"
ARG PHP_DATABASE_EXTENSIONS="pdo_pgsql pdo_mysql"
ARG PHP_DEBIAN_RELEASE="bullseye"
ARG PHP_EXTENSIONS_EXTRA=""
ARG PHP_EXTENSIONS="intl bcmath zip pcntl exif curl gd"
ARG PHP_VERSION="8.1"
ARG APT_PACKAGES_EXTRA=""
# GPG key for nginx apt repository
ARG NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
# GPP key path for nginx apt repository
ARG NGINX_GPGKEY_PATH=/usr/share/keyrings/nginx-archive-keyring.gpg
#######################################################
# Docker "copy from" images
#######################################################
# Composer docker image from Docker Hub
#
# NOTE: Docker will *not* pull this image unless it's referenced (via build target)
FROM composer:${COMPOSER_VERSION} AS composer-image
# nginx webserver from Docker Hub.
# Used to copy some docker-entrypoint files for [nginx-runtime]
#
# NOTE: Docker will *not* pull this image unless it's referenced (via build target)
FROM nginx:${NGINX_VERSION} AS nginx-image
# Forego is a Procfile "runner" that makes it trival to run multiple
# processes under a simple init / PID 1 process.
#
# NOTE: Docker will *not* pull this image unless it's referenced (via build target)
#
# See: https://github.com/nginx-proxy/forego
FROM nginxproxy/forego:${FOREGO_VERSION}-debian AS forego-image
#######################################################
# Base image
#######################################################
FROM php:${PHP_VERSION}-${PHP_BASE_TYPE}-${PHP_DEBIAN_RELEASE} AS base
ARG PHP_VERSION
ARG PHP_DEBIAN_RELEASE
ARG APT_PACKAGES_EXTRA
ARG TARGETPLATFORM
ARG BUILDKIT_SBOM_SCAN_STAGE=true
ENV DEBIAN_FRONTEND=noninteractive
# Ensure we run all scripts through 'bash' rather than 'sh'
SHELL ["/bin/bash", "-c"]
RUN set -ex \
&& mkdir -pv /var/www/ \
&& chown -R 33:33 /var/www
WORKDIR /var/www/
# Install package dependencies
RUN --mount=type=cache,id=pixelfed-apt-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt \
--mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \
<<-SCRIPT
#!/bin/bash
set -ex -o errexit -o nounset -o pipefail
# ensure we keep apt cache around in a Docker environment
rm -f /etc/apt/apt.conf.d/docker-clean
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
# Standard packages
standardPackages=(
apt-utils
ca-certificates
gettext-base
git
gnupg1
gosu
libcurl4-openssl-dev
libzip-dev
locales
locales-all
nano
procps
unzip
zip
)
# Image Optimization
imageOptimization=(
gifsicle
jpegoptim
optipng
pngquant
)
# Image Processing
imageProcessing=(
libjpeg62-turbo-dev
libmagickwand-dev
libpng-dev
)
# Required for GD
gdDependencies=(
libwebp-dev
libwebp6
libxpm-dev
libxpm4
)
# Video Processing
videoProcessing=(
ffmpeg
)
# Database
databaseDependencies=(
libpq-dev
libsqlite3-dev
)
apt-get update
apt-get upgrade -y
apt-get install -y --no-install-recommends \
${standardPackages[*]} \
${imageOptimization[*]} \
${imageProcessing[*]} \
${gdDependencies[*]} \
${videoProcessing[*]} \
${databaseDependencies[*]} \
${APT_PACKAGES_EXTRA}
SCRIPT
# update locales
RUN set -ex \
&& locale-gen \
&& update-locale
#######################################################
# PHP: extensions
#######################################################
FROM base AS php-extensions
ARG PECL_EXTENSIONS
ARG PECL_EXTENSIONS_EXTRA
ARG PHP_DATABASE_EXTENSIONS
ARG PHP_DEBIAN_RELEASE
ARG PHP_EXTENSIONS
ARG PHP_EXTENSIONS_EXTRA
ARG PHP_VERSION
ARG TARGETPLATFORM
RUN --mount=type=cache,id=pixelfed-php-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/usr/src/php/ \
set -ex \
# Grab the PHP source code so we can compile against it
&& docker-php-source extract \
# Install pecl extensions
&& pecl install ${PECL_EXTENSIONS} ${PECL_EXTENSIONS_EXTRA} \
# PHP GD extensions
&& docker-php-ext-configure gd \
--with-freetype \
--with-jpeg \
--with-webp \
--with-xpm \
# PHP extensions (dependencies)
&& docker-php-ext-install -j$(nproc) ${PHP_EXTENSIONS} ${PHP_EXTENSIONS_EXTRA} ${PHP_DATABASE_EXTENSIONS} \
# Enable all extensions
&& docker-php-ext-enable ${PECL_EXTENSIONS} ${PECL_EXTENSIONS_EXTRA} ${PHP_EXTENSIONS} ${PHP_EXTENSIONS_EXTRA} ${PHP_DATABASE_EXTENSIONS}
#######################################################
# PHP: composer and source code
#######################################################
FROM base AS composer-and-src
ARG PHP_VERSION
ARG PHP_DEBIAN_RELEASE
ARG TARGETPLATFORM
# Make sure composer cache is targeting our cache mount later
ENV COMPOSER_CACHE_DIR=/cache/composer
# Don't enforce any memory limits for composer
ENV COMPOSER_MEMORY_LIMIT=-1
# Disable interactvitity from composer
ENV COMPOSER_NO_INTERACTION=1
# Copy composer from https://hub.docker.com/_/composer
COPY --link --from=composer-image /usr/bin/composer /usr/bin/composer
#! Changing user to 33
USER 33:33
# Copy over only composer related files so docker layer cache isn't invalidated on PHP file changes
COPY --link --chown=33:33 composer.json composer.lock /var/www/
# Install composer dependencies
# NOTE: we skip the autoloader generation here since we don't have all files avaliable (yet)
RUN --mount=type=cache,id=pixelfed-composer-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/cache/composer \
set -ex \
&& composer install --prefer-dist --no-autoloader --ignore-platform-reqs
# Copy all other files over
COPY --link --chown=33:33 . /var/www/
# Generate optimized autoloader now that we have all files around
RUN set -ex \
&& composer dump-autoload --optimize
#! Changing back to root
USER root:root
#######################################################
# Runtime: base
#######################################################
FROM base AS shared-runtime
COPY --link --from=php-extensions /usr/local/lib/php/extensions /usr/local/lib/php/extensions
COPY --link --from=php-extensions /usr/local/etc/php /usr/local/etc/php
COPY --link --from=composer-and-src --chown=33:33 /var/www /var/www
COPY --link --from=forego-image /usr/local/bin/forego /usr/local/bin/forego
COPY --link contrib/docker/php.production.ini "$PHP_INI_DIR/php.ini"
# for detail why storage is copied this way, pls refer to https://github.com/pixelfed/pixelfed/pull/2137#discussion_r434468862
RUN set -ex \
&& cp --recursive --link --preserve=all storage storage.skel \
&& rm -rf html && ln -s public html
COPY --link contrib/docker/docker-entrypoint.sh /docker-entrypoint.sh
COPY --link contrib/docker/shared/lib.sh /lib.sh
COPY --link contrib/docker/shared/docker-entrypoint.d /docker-entrypoint.d/
ENTRYPOINT ["/docker-entrypoint.sh"]
VOLUME /var/www/storage /var/www/bootstrap
#######################################################
# Runtime: apache
#######################################################
FROM shared-runtime AS apache-runtime
COPY --link contrib/docker/apache/conf-available/remoteip.conf /etc/apache2/conf-available/remoteip.conf
COPY --link contrib/docker/apache/docker-entrypoint.d /docker-entrypoint.d/
RUN set -ex \
&& a2enmod rewrite remoteip proxy proxy_http \
&& a2enconf remoteip
CMD ["apache2-foreground"]
EXPOSE 80
#######################################################
# Runtime: fpm
#######################################################
FROM shared-runtime AS fpm-runtime
COPY --link contrib/docker/fpm/docker-entrypoint.d /docker-entrypoint.d/
CMD ["php-fpm"]
EXPOSE 9000
#######################################################
# Runtime: nginx
#######################################################
FROM shared-runtime AS nginx-runtime
ARG NGINX_GPGKEY
ARG NGINX_GPGKEY_PATH
ARG NGINX_VERSION
ARG PHP_DEBIAN_RELEASE
ARG PHP_VERSION
ARG TARGETPLATFORM
# Install nginx dependencies
RUN --mount=type=cache,id=pixelfed-apt-lists-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/lib/apt/lists \
--mount=type=cache,id=pixelfed-apt-cache-${PHP_VERSION}-${PHP_DEBIAN_RELEASE}-${TARGETPLATFORM},sharing=locked,target=/var/cache/apt \
set -ex \
&& gpg1 --keyserver "hkp://keyserver.ubuntu.com:80" --keyserver-options timeout=10 --recv-keys "${NGINX_GPGKEY}" \
&& gpg1 --export "$NGINX_GPGKEY" > "$NGINX_GPGKEY_PATH" \
&& echo "deb [signed-by=${NGINX_GPGKEY_PATH}] https://nginx.org/packages/mainline/debian/ ${PHP_DEBIAN_RELEASE} nginx" >> /etc/apt/sources.list.d/nginx.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
nginx=${NGINX_VERSION}*
# copy docker entrypoints from the *real* nginx image directly
COPY --link --from=nginx-image /docker-entrypoint.d /docker-entrypoint.d/
COPY --link contrib/docker/nginx/docker-entrypoint.d /docker-entrypoint.d/
COPY --link contrib/docker/nginx/default-http.conf /etc/nginx/templates/default.conf.template
COPY --link contrib/docker/nginx/Procfile .
EXPOSE 80
STOPSIGNAL SIGQUIT
CMD ["forego", "start", "-r"]