The coffeylabs theme brings coffeylabs.org's palette, type and blueprint grid to Mastodon. It loads the stock stylesheet and then overrides Mastodon's color tokens for both color schemes, adds Bricolage Grotesque and JetBrains Mono (OFL, served from the instance), and replaces the navigation wordmark. The default theme stays available to users. Small upstream changes, each with a modification notice: themes.yml registers the theme, themes.rb sets the dark browser-bar color, and the Dockerfile takes SOURCE_BASE_URL and SOURCE_TAG so "View source code" points at this repository, as the AGPL expects. Upstream's GitHub workflows are removed. .gitea/workflows/ci.yml builds the image on every change and publishes it, with a release, from tags named v<upstream>-coffeylabs.<n>. COFFEYLABS.md lists every change.
426 lines
14 KiB
Docker
426 lines
14 KiB
Docker
# syntax=docker/dockerfile:1.18
|
|
|
|
# Modified by Coffey Labs, 2026-10-06: SOURCE_BASE_URL and SOURCE_TAG build
|
|
# arguments, so the "View source code" link points at this fork (see
|
|
# COFFEYLABS.md).
|
|
|
|
# This file is designed for production server deployment, not local development work
|
|
# For a containerized local dev environment, see: https://github.com/mastodon/mastodon/blob/main/docs/DEVELOPMENT.md#docker
|
|
|
|
# Please see https://docs.docker.com/engine/reference/builder for information about
|
|
# the extended buildx capabilities used in this file.
|
|
# Make sure multiarch TARGETPLATFORM is available for interpolation
|
|
# See: https://docs.docker.com/build/building/multi-platform/
|
|
ARG TARGETPLATFORM=${TARGETPLATFORM}
|
|
ARG BUILDPLATFORM=${BUILDPLATFORM}
|
|
ARG BASE_REGISTRY="docker.io"
|
|
|
|
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="4.0.x"]
|
|
# renovate: datasource=docker depName=docker.io/ruby
|
|
ARG RUBY_VERSION="4.0.6"
|
|
# # Node.js version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="22"]
|
|
# renovate: datasource=node-version depName=node
|
|
ARG NODE_MAJOR_VERSION="24"
|
|
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="trixie"]
|
|
ARG DEBIAN_VERSION="trixie"
|
|
# Node.js image to use for base image based on combined variables (ex: 20-trixie-slim)
|
|
FROM ${BASE_REGISTRY}/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node
|
|
# Ruby image to use for base image based on combined variables (ex: 3.4.x-slim-trixie)
|
|
FROM ${BASE_REGISTRY}/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby
|
|
|
|
# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
|
|
# Example: v4.3.0-nightly.2023-11-09+pr-123456
|
|
# Overwrite existence of 'alpha.X' in version.rb [--build-arg MASTODON_VERSION_PRERELEASE="nightly.2023-11-09"]
|
|
ARG MASTODON_VERSION_PRERELEASE=""
|
|
# Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="pr-123456"]
|
|
ARG MASTODON_VERSION_METADATA=""
|
|
# Will be available as Mastodon::Version.source_commit
|
|
ARG SOURCE_COMMIT=""
|
|
# Where "View source code" points: the fork's repository and its tag
|
|
ARG SOURCE_BASE_URL=""
|
|
ARG SOURCE_TAG=""
|
|
|
|
# Allow Ruby on Rails to serve static files
|
|
# See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files
|
|
ARG RAILS_SERVE_STATIC_FILES="true"
|
|
# Allow to use YJIT compiler
|
|
# See: https://github.com/ruby/ruby/blob/v3_2_4/doc/yjit/yjit.md
|
|
ARG RUBY_YJIT_ENABLE="1"
|
|
# Timezone used by the Docker container and runtime, change with [--build-arg TZ=Europe/Berlin]
|
|
ARG TZ="Etc/UTC"
|
|
# Linux UID (user id) for the mastodon user, change with [--build-arg UID=1234]
|
|
ARG UID="991"
|
|
# Linux GID (group id) for the mastodon user, change with [--build-arg GID=1234]
|
|
ARG GID="991"
|
|
|
|
# Apply Mastodon build options based on options above
|
|
ENV \
|
|
MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \
|
|
MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \
|
|
SOURCE_COMMIT="${SOURCE_COMMIT}" \
|
|
SOURCE_BASE_URL="${SOURCE_BASE_URL}" \
|
|
SOURCE_TAG="${SOURCE_TAG}" \
|
|
RAILS_SERVE_STATIC_FILES="${RAILS_SERVE_STATIC_FILES}" \
|
|
RUBY_YJIT_ENABLE="${RUBY_YJIT_ENABLE}" \
|
|
TZ="${TZ}"
|
|
|
|
# Configure runtime environment
|
|
# BIND: IP to bind Mastodon to when serving traffic
|
|
# NODE_ENV/RAILS_ENV: production settings for Node.js and Ruby on Rails
|
|
# DEBIAN_FRONTEND: suppress interactive prompts
|
|
# PATH: add Ruby and Mastodon installation directories
|
|
# MALLOC_CONF: optimize jemalloc 5.x performance
|
|
# MASTODON_SIDEKIQ_READY_FILENAME: Sidekiq readiness check filename for Kubernetes
|
|
ENV \
|
|
BIND="0.0.0.0" \
|
|
NODE_ENV="production" \
|
|
RAILS_ENV="production" \
|
|
DEBIAN_FRONTEND="noninteractive" \
|
|
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" \
|
|
MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" \
|
|
MASTODON_SIDEKIQ_READY_FILENAME=sidekiq_process_has_started_and_will_begin_processing_jobs
|
|
|
|
# Set default shell used for running commands
|
|
SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"]
|
|
|
|
ARG TARGETPLATFORM
|
|
|
|
RUN echo "Target platform is $TARGETPLATFORM"
|
|
|
|
RUN \
|
|
# Remove automatic apt cache Docker cleanup scripts
|
|
rm -f /etc/apt/apt.conf.d/docker-clean; \
|
|
# Sets timezone
|
|
echo "${TZ}" > /etc/localtime; \
|
|
# Creates mastodon user/group and sets home directory
|
|
groupadd -g "${GID}" mastodon; \
|
|
useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon; \
|
|
# Creates /mastodon symlink to /opt/mastodon
|
|
ln -s /opt/mastodon /mastodon;
|
|
|
|
# Set /opt/mastodon as working directory
|
|
WORKDIR /opt/mastodon
|
|
|
|
# hadolint ignore=DL3008,DL3005
|
|
RUN \
|
|
# Mount Apt cache and lib directories from Docker buildx caches
|
|
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
|
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
|
# Update package list and upgrade system packages
|
|
apt-get update; \
|
|
apt-get dist-upgrade -yq; \
|
|
# Install jemalloc and other necessary components
|
|
apt-get install -y --no-install-recommends \
|
|
curl \
|
|
file \
|
|
libjemalloc2 \
|
|
patchelf \
|
|
procps \
|
|
tini \
|
|
tzdata \
|
|
wget \
|
|
# Mastodon components
|
|
libexpat1 \
|
|
libglib2.0-0t64 \
|
|
libicu76 \
|
|
libidn12 \
|
|
libpq5 \
|
|
libreadline8t64 \
|
|
libssl3t64 \
|
|
libyaml-0-2 \
|
|
# libvips components
|
|
libcgif0 \
|
|
libexif12 \
|
|
libheif1 \
|
|
libhwy1t64 \
|
|
libimagequant0 \
|
|
libjpeg62-turbo \
|
|
liblcms2-2 \
|
|
libspng0 \
|
|
libtiff6 \
|
|
libwebp7 \
|
|
libwebpdemux2 \
|
|
libwebpmux3 \
|
|
# ffmpeg components
|
|
libdav1d7 \
|
|
libmp3lame0 \
|
|
libopencore-amrnb0 \
|
|
libopencore-amrwb0 \
|
|
libopus0 \
|
|
libsnappy1v5 \
|
|
libtheora0 \
|
|
libvorbis0a \
|
|
libvorbisenc2 \
|
|
libvorbisfile3 \
|
|
libvpx9 \
|
|
libx264-164 \
|
|
libx265-215 \
|
|
; \
|
|
# Patch Ruby to use jemalloc
|
|
patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \
|
|
# Discard patchelf after use
|
|
apt-get purge -y \
|
|
patchelf \
|
|
;
|
|
|
|
# Build stage for media libraries (libvips, ffmpeg)
|
|
FROM ${BASE_REGISTRY}/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS media-build
|
|
|
|
ARG TARGETPLATFORM
|
|
|
|
# Set default shell used for running commands
|
|
SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"]
|
|
|
|
# hadolint ignore=DL3008
|
|
RUN \
|
|
--mount=type=cache,id=apt-native-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
|
--mount=type=cache,id=apt-native-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
|
# Remove automatic apt cache Docker cleanup scripts
|
|
rm -f /etc/apt/apt.conf.d/docker-clean; \
|
|
# Install build tools for native libraries
|
|
apt-get update; \
|
|
apt-get install -y --no-install-recommends \
|
|
autoconf \
|
|
automake \
|
|
build-essential \
|
|
libtool \
|
|
meson \
|
|
nasm \
|
|
pkg-config \
|
|
xz-utils \
|
|
# libvips components
|
|
libcgif-dev \
|
|
libexif-dev \
|
|
libexpat1-dev \
|
|
libgirepository1.0-dev \
|
|
libglib2.0-dev \
|
|
libheif-dev \
|
|
libhwy-dev \
|
|
libimagequant-dev \
|
|
libjpeg62-turbo-dev \
|
|
liblcms2-dev \
|
|
libspng-dev \
|
|
libtiff-dev \
|
|
libwebp-dev \
|
|
# ffmpeg components
|
|
libdav1d-dev \
|
|
liblzma-dev \
|
|
libmp3lame-dev \
|
|
libopus-dev \
|
|
libsnappy-dev \
|
|
libvorbis-dev \
|
|
libvpx-dev \
|
|
libx264-dev \
|
|
libx265-dev \
|
|
;
|
|
|
|
# Create temporary libvips specific build layer
|
|
FROM media-build AS libvips
|
|
|
|
# libvips version to compile, change with [--build-arg VIPS_VERSION="8.15.2"]
|
|
# renovate: datasource=github-releases depName=libvips packageName=libvips/libvips
|
|
ARG VIPS_VERSION=8.18.5
|
|
# libvips download URL, change with [--build-arg VIPS_URL="https://github.com/libvips/libvips/releases/download"]
|
|
ARG VIPS_URL=https://github.com/libvips/libvips/releases/download
|
|
|
|
WORKDIR /usr/local/libvips/src
|
|
# Download and extract libvips source code
|
|
ADD ${VIPS_URL}/v${VIPS_VERSION}/vips-${VIPS_VERSION}.tar.xz /usr/local/libvips/src/
|
|
RUN tar xf vips-${VIPS_VERSION}.tar.xz;
|
|
|
|
WORKDIR /usr/local/libvips/src/vips-${VIPS_VERSION}
|
|
|
|
# Configure libvips
|
|
RUN meson setup build --prefix /usr/local/libvips --libdir=lib -Ddeprecated=false -Dintrospection=disabled -Dmodules=disabled -Dexamples=false
|
|
|
|
WORKDIR /usr/local/libvips/src/vips-${VIPS_VERSION}/build
|
|
|
|
# Compile and install libvips
|
|
RUN ninja && ninja install
|
|
|
|
# Create temporary ffmpeg specific build layer
|
|
FROM media-build AS ffmpeg
|
|
|
|
# ffmpeg version to compile, change with [--build-arg FFMPEG_VERSION="7.0.x"]
|
|
# renovate: datasource=github-tags depName=FFmpeg/FFmpeg extractVersion=^n(?<version>\d+\.\d+(\.\d+)?)$
|
|
ARG FFMPEG_VERSION=9.0.2
|
|
# ffmpeg download URL, change with [--build-arg FFMPEG_URL="https://ffmpeg.org/releases"]
|
|
ARG FFMPEG_URL=https://github.com/FFmpeg/FFmpeg/archive/refs/tags
|
|
|
|
WORKDIR /usr/local/ffmpeg/src
|
|
# Download and extract ffmpeg source code
|
|
ADD ${FFMPEG_URL}/n${FFMPEG_VERSION}.tar.gz /usr/local/ffmpeg/src/
|
|
RUN tar xf n${FFMPEG_VERSION}.tar.gz && mv FFmpeg-n${FFMPEG_VERSION} ffmpeg-${FFMPEG_VERSION};
|
|
|
|
WORKDIR /usr/local/ffmpeg/src/ffmpeg-${FFMPEG_VERSION}
|
|
|
|
# Configure and compile ffmpeg
|
|
RUN \
|
|
./configure \
|
|
--prefix=/usr/local/ffmpeg \
|
|
--toolchain=hardened \
|
|
--disable-debug \
|
|
--disable-devices \
|
|
--disable-doc \
|
|
--disable-ffplay \
|
|
--disable-network \
|
|
--disable-static \
|
|
--enable-ffmpeg \
|
|
--enable-ffprobe \
|
|
--enable-gpl \
|
|
--enable-libdav1d \
|
|
--enable-libmp3lame \
|
|
--enable-libopus \
|
|
--enable-libsnappy \
|
|
--enable-libvorbis \
|
|
--enable-libvpx \
|
|
--enable-libwebp \
|
|
--enable-libx264 \
|
|
--enable-libx265 \
|
|
--enable-shared \
|
|
--enable-version3 \
|
|
; \
|
|
make -j"$(nproc)"; \
|
|
make install;
|
|
|
|
# Create temporary build layer from base image for Ruby dependencies
|
|
FROM ruby AS ruby-build
|
|
|
|
ARG TARGETPLATFORM
|
|
|
|
# hadolint ignore=DL3008
|
|
RUN \
|
|
# Mount Apt cache and lib directories from Docker buildx caches
|
|
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
|
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
|
# Install build tools and bundler dependencies from APT
|
|
apt-get install -y --no-install-recommends \
|
|
build-essential \
|
|
git \
|
|
libgdbm-dev \
|
|
libgmp-dev \
|
|
libicu-dev \
|
|
libidn-dev \
|
|
libpq-dev \
|
|
libssl-dev \
|
|
libyaml-dev \
|
|
shared-mime-info \
|
|
zlib1g-dev \
|
|
;
|
|
|
|
# Create temporary bundler specific build layer from build layer
|
|
FROM ruby-build AS bundler
|
|
|
|
ARG TARGETPLATFORM
|
|
|
|
# Copy Gemfile config into working directory
|
|
COPY Gemfile* /opt/mastodon/
|
|
|
|
# Copy libvips for gems that need it during install
|
|
COPY --from=libvips /usr/local/libvips/lib /usr/local/lib
|
|
COPY --from=libvips /usr/local/libvips/include /usr/local/include
|
|
|
|
RUN ldconfig
|
|
|
|
RUN \
|
|
# Mount Ruby Gem caches
|
|
--mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \
|
|
# Configure bundle to prevent changes to Gemfile and Gemfile.lock
|
|
bundle config set --global frozen "true"; \
|
|
# Configure bundle to not cache downloaded Gems
|
|
bundle config set --global cache_all "false"; \
|
|
# Configure bundle to only process production Gems
|
|
bundle config set --local without "development test"; \
|
|
# Configure bundle to not warn about root user
|
|
bundle config set silence_root_warning "true"; \
|
|
# Download and install required Gems
|
|
bundle install -j"$(nproc)";
|
|
|
|
# Create temporary assets build layer from build layer
|
|
FROM ruby-build AS precompiler
|
|
|
|
ARG TARGETPLATFORM
|
|
|
|
# Copy Mastodon sources into layer
|
|
COPY . /opt/mastodon/
|
|
|
|
# Copy Node.js binaries/libraries into layer
|
|
COPY --from=node /usr/local/bin /usr/local/bin
|
|
COPY --from=node /usr/local/lib /usr/local/lib
|
|
|
|
RUN \
|
|
# Mount local Corepack and Yarn caches from Docker buildx caches
|
|
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
|
|
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
|
|
# Remove pre-installed Yarn binaries (only present on Node <26)
|
|
rm -f /usr/local/bin/yarn*; \
|
|
# Install Corepack
|
|
npm i -g corepack;
|
|
|
|
# hadolint ignore=DL3008
|
|
RUN \
|
|
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
|
|
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
|
|
# Install Node.js packages
|
|
yarn workspaces focus --production @mastodon/mastodon;
|
|
|
|
# Copy libvips components into layer for precompiler
|
|
COPY --from=libvips /usr/local/libvips/bin /usr/local/bin
|
|
COPY --from=libvips /usr/local/libvips/lib /usr/local/lib
|
|
# Copy bundler packages into layer for precompiler
|
|
COPY --from=bundler /opt/mastodon /opt/mastodon/
|
|
COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
|
|
|
|
RUN \
|
|
ldconfig; \
|
|
# Use Ruby on Rails to create Mastodon assets
|
|
SECRET_KEY_BASE_DUMMY=1 \
|
|
bundle exec rails assets:precompile; \
|
|
# Cleanup temporary files
|
|
rm -fr /opt/mastodon/tmp;
|
|
|
|
# Prep final Mastodon Ruby layer
|
|
FROM ruby AS mastodon
|
|
|
|
ARG TARGETPLATFORM
|
|
|
|
# Copy Mastodon sources into final layer
|
|
COPY . /opt/mastodon/
|
|
|
|
# Copy compiled assets to layer
|
|
COPY --from=precompiler /opt/mastodon/public/packs /opt/mastodon/public/packs
|
|
COPY --from=precompiler /opt/mastodon/public/assets /opt/mastodon/public/assets
|
|
# Copy bundler components to layer
|
|
COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
|
|
# Copy libvips components to layer
|
|
COPY --from=libvips /usr/local/libvips/bin /usr/local/bin
|
|
COPY --from=libvips /usr/local/libvips/lib /usr/local/lib
|
|
# Copy ffpmeg components to layer
|
|
COPY --from=ffmpeg /usr/local/ffmpeg/bin /usr/local/bin
|
|
COPY --from=ffmpeg /usr/local/ffmpeg/lib /usr/local/lib
|
|
|
|
RUN \
|
|
ldconfig; \
|
|
# Smoketest media processors
|
|
vips -v; \
|
|
ffmpeg -version; \
|
|
ffprobe -version;
|
|
|
|
RUN \
|
|
# Precompile bootsnap code for faster Rails startup
|
|
bundle exec bootsnap precompile --gemfile app/ lib/ config/;
|
|
|
|
RUN \
|
|
# Pre-create and chown system volume to Mastodon user
|
|
mkdir -p /opt/mastodon/public/system; \
|
|
chown mastodon:mastodon /opt/mastodon/public/system; \
|
|
# Set Mastodon user as owner of tmp folder
|
|
chown -R mastodon:mastodon /opt/mastodon/tmp;
|
|
|
|
# Set the running user for resulting container
|
|
USER mastodon
|
|
# Expose default Puma ports
|
|
EXPOSE 3000
|
|
# Set container tini as default entry point
|
|
ENTRYPOINT ["/usr/bin/tini", "--"]
|