2024-10-01 11:29:38 +02:00
# syntax=docker/dockerfile:1.10
2019-02-24 16:32:40 +01:00
2024-06-06 01:54:59 +02:00
# 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/README.md#docker
2023-11-28 11:04:40 +01:00
# 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 }
2019-02-24 16:32:40 +01:00
2024-06-03 11:16:11 +02:00
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.3.x"]
2024-06-10 16:47:59 +02:00
# renovate: datasource=docker depName=docker.io/ruby
2024-09-05 13:06:05 +02:00
ARG RUBY_VERSION = "3.3.5"
2023-11-28 11:04:40 +01:00
# # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
2024-06-10 16:47:59 +02:00
# renovate: datasource=node-version depName=node
2024-10-31 11:42:18 +01:00
ARG NODE_MAJOR_VERSION = "22"
2023-11-28 11:04:40 +01:00
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
ARG DEBIAN_VERSION = "bookworm"
# Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
2024-06-21 22:26:39 +02:00
FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node
2024-06-03 11:16:11 +02:00
# Ruby image to use for base image based on combined variables (ex: 3.3.x-slim-bookworm)
2024-06-21 22:26:39 +02:00
FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby
2019-02-24 16:32:40 +01:00
2023-11-28 11:04:40 +01:00
# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
2024-06-18 16:51:51 +02:00
# 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"]
2023-11-28 11:04:40 +01:00
ARG MASTODON_VERSION_PRERELEASE = ""
2024-06-18 16:51:51 +02:00
# Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="pr-123456"]
2023-11-28 11:04:40 +01:00
ARG MASTODON_VERSION_METADATA = ""
# 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
2024-04-24 10:21:05 +02:00
# See: https://github.com/ruby/ruby/blob/v3_2_4/doc/yjit/yjit.md
2023-11-28 11:04:40 +01:00
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 \
# Apply Mastodon version information
MASTODON_VERSION_PRERELEASE = " ${ MASTODON_VERSION_PRERELEASE } " \
MASTODON_VERSION_METADATA = " ${ MASTODON_VERSION_METADATA } " \
# Apply Mastodon static files and YJIT options
RAILS_SERVE_STATIC_FILES = ${ RAILS_SERVE_STATIC_FILES } \
RUBY_YJIT_ENABLE = ${ RUBY_YJIT_ENABLE } \
# Apply timezone
TZ = ${ TZ }
ENV \
# Configure the IP to bind Mastodon to when serving traffic
BIND = "0.0.0.0" \
# Use production settings for Yarn, Node and related nodejs based tools
NODE_ENV = "production" \
# Use production settings for Ruby on Rails
RAILS_ENV = "production" \
# Add Ruby and Mastodon installation to the PATH
DEBIAN_FRONTEND = "noninteractive" \
PATH = " ${ PATH } :/opt/ruby/bin:/opt/mastodon/bin " \
# Optimize jemalloc 5.x performance
2024-06-13 17:58:34 +02:00
MALLOC_CONF = "narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" \
# Enable libvips, should not be changed
2024-07-10 14:57:25 +02:00
MASTODON_USE_LIBVIPS = true \
# Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes
MASTODON_SIDEKIQ_READY_FILENAME = sidekiq_process_has_started_and_will_begin_processing_jobs
2023-11-28 11:04:40 +01:00
# Set default shell used for running commands
SHELL [ "/bin/bash" , "-o" , "pipefail" , "-o" , "errexit" , "-c" ]
ARG TARGETPLATFORM
RUN echo " Target platform is $TARGETPLATFORM "
2019-02-24 16:32:40 +01:00
2023-11-28 11:04:40 +01:00
RUN \
2023-11-28 23:23:44 +01:00
# Remove automatic apt cache Docker cleanup scripts
rm -f /etc/apt/apt.conf.d/docker-clean; \
2023-11-28 11:04:40 +01:00
# 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;
2022-11-17 12:56:14 +01:00
2023-11-28 11:04:40 +01:00
# Set /opt/mastodon as working directory
2022-11-17 12:56:14 +01:00
WORKDIR /opt/mastodon
2019-02-24 16:32:40 +01:00
2023-11-28 11:04:40 +01:00
# 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 \
# Apt update & upgrade to check for security updates to Debian image
apt-get update; \
apt-get dist-upgrade -yq; \
# Install jemalloc, curl and other necessary components
apt-get install -y --no-install-recommends \
curl \
file \
libjemalloc2 \
patchelf \
procps \
tini \
tzdata \
2024-01-02 09:47:38 +01:00
wget \
2023-11-28 11:04:40 +01:00
; \
# Patch Ruby to use jemalloc
patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \
# Discard patchelf after use
apt-get purge -y \
patchelf \
;
# Create temporary build layer from base image
2024-06-21 22:26:39 +02:00
FROM ruby AS build
2023-11-28 11:04:40 +01:00
# Copy Node package configuration files into working directory
COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
COPY .yarn /opt/mastodon/.yarn
COPY --from= node /usr/local/bin /usr/local/bin
COPY --from= node /usr/local/lib /usr/local/lib
ARG TARGETPLATFORM
2022-12-15 15:57:17 +01:00
# hadolint ignore=DL3008
2023-11-28 11:04:40 +01:00
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 \
2024-06-18 16:51:51 +02:00
autoconf \
automake \
2024-06-13 17:58:34 +02:00
build-essential \
2024-06-18 16:51:51 +02:00
cmake \
2023-11-28 11:04:40 +01:00
git \
libgdbm-dev \
2024-06-13 17:58:34 +02:00
libglib2.0-dev \
2023-11-28 11:04:40 +01:00
libgmp-dev \
libicu-dev \
libidn-dev \
libpq-dev \
libssl-dev \
2024-06-18 16:51:51 +02:00
libtool \
2024-06-13 17:58:34 +02:00
meson \
2024-06-18 16:51:51 +02:00
nasm \
2024-06-13 17:58:34 +02:00
pkg-config \
2023-11-28 11:04:40 +01:00
shared-mime-info \
2024-06-18 16:51:51 +02:00
xz-utils \
2024-06-13 17:58:34 +02:00
# libvips components
libcgif-dev \
libexif-dev \
libexpat1-dev \
libgirepository1.0-dev \
libheif-dev \
libimagequant-dev \
libjpeg62-turbo-dev \
liblcms2-dev \
liborc-dev \
libspng-dev \
libtiff-dev \
libwebp-dev \
2024-06-18 16:51:51 +02:00
# ffmpeg components
libdav1d-dev \
liblzma-dev \
libmp3lame-dev \
libopus-dev \
libsnappy-dev \
libvorbis-dev \
libvpx-dev \
libx264-dev \
libx265-dev \
2023-11-28 11:04:40 +01:00
;
RUN \
# Configure Corepack
rm /usr/local/bin/yarn*; \
corepack enable; \
corepack prepare --activate;
2024-06-13 17:58:34 +02:00
# Create temporary libvips specific build layer from build layer
2024-06-21 22:26:39 +02:00
FROM build AS libvips
2024-06-13 17:58:34 +02:00
# libvips version to compile, change with [--build-arg VIPS_VERSION="8.15.2"]
# renovate: datasource=github-releases depName=libvips packageName=libvips/libvips
2024-10-30 09:40:49 +01:00
ARG VIPS_VERSION = 8 .16.0
2024-06-13 17:58:34 +02:00
# 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
2024-08-19 21:44:28 +02:00
# 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;
2024-06-13 17:58:34 +02:00
2024-08-19 21:44:28 +02:00
WORKDIR /usr/local/libvips/src/vips-${VIPS_VERSION}
# Configure and compile libvips
2024-06-13 17:58:34 +02:00
RUN \
meson setup build --prefix /usr/local/libvips --libdir= lib -Ddeprecated= false -Dintrospection= disabled -Dmodules= disabled -Dexamples= false; \
cd build; \
ninja; \
ninja install;
2024-06-18 16:51:51 +02:00
# Create temporary ffmpeg specific build layer from build layer
2024-06-21 22:26:39 +02:00
FROM build AS ffmpeg
2024-06-18 16:51:51 +02:00
# ffmpeg version to compile, change with [--build-arg FFMPEG_VERSION="7.0.x"]
# renovate: datasource=repology depName=ffmpeg packageName=openpkg_current/ffmpeg
2024-10-04 09:18:38 +02:00
ARG FFMPEG_VERSION = 7 .1
2024-06-18 16:51:51 +02:00
# ffmpeg download URL, change with [--build-arg FFMPEG_URL="https://ffmpeg.org/releases"]
ARG FFMPEG_URL = https://ffmpeg.org/releases
WORKDIR /usr/local/ffmpeg/src
2024-08-19 21:44:28 +02:00
# Download and extract ffmpeg source code
ADD ${ FFMPEG_URL } /ffmpeg-${ FFMPEG_VERSION } .tar.xz /usr/local/ffmpeg/src/
RUN tar xf ffmpeg-${ FFMPEG_VERSION } .tar.xz;
WORKDIR /usr/local/ffmpeg/src/ffmpeg-${FFMPEG_VERSION}
2024-06-18 16:51:51 +02:00
2024-08-19 21:44:28 +02:00
# Configure and compile ffmpeg
2024-06-18 16:51:51 +02:00
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;
2023-11-28 11:04:40 +01:00
# Create temporary bundler specific build layer from build layer
2024-06-21 22:26:39 +02:00
FROM build AS bundler
2023-11-28 11:04:40 +01:00
ARG TARGETPLATFORM
# Copy Gemfile config into working directory
COPY Gemfile* /opt/mastodon/
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 node specific build layer from build layer
2024-06-21 22:26:39 +02:00
FROM build AS yarn
2023-11-28 11:04:40 +01:00
ARG TARGETPLATFORM
# Copy Node package configuration files into working directory
2023-11-28 21:44:04 +01:00
COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
2023-11-18 11:14:51 +01:00
COPY streaming/package.json /opt/mastodon/streaming/
2023-11-08 11:57:21 +01:00
COPY .yarn /opt/mastodon/.yarn
2023-11-28 11:04:40 +01:00
# 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 packages
yarn workspaces focus --production @mastodon/mastodon;
2023-11-08 11:57:21 +01:00
2023-11-28 11:04:40 +01:00
# Create temporary assets build layer from build layer
2024-06-21 22:26:39 +02:00
FROM build AS precompiler
2022-11-17 12:56:14 +01:00
2023-11-28 11:04:40 +01:00
# Copy Mastodon sources into precompiler layer
COPY . /opt/mastodon/
2022-11-17 12:56:14 +01:00
2023-11-28 11:04:40 +01:00
# Copy bundler and node packages from build layer to container
COPY --from= yarn /opt/mastodon /opt/mastodon/
COPY --from= bundler /opt/mastodon /opt/mastodon/
COPY --from= bundler /usr/local/bundle/ /usr/local/bundle/
2024-06-13 17:58:34 +02:00
# Copy libvips components to layer for precompiler
COPY --from= libvips /usr/local/libvips/bin /usr/local/bin
COPY --from= libvips /usr/local/libvips/lib /usr/local/lib
2023-05-04 21:33:32 +02:00
2023-11-28 11:04:40 +01:00
ARG TARGETPLATFORM
2022-11-17 12:56:14 +01:00
2023-11-28 11:04:40 +01:00
RUN \
2024-06-13 17:58:34 +02:00
ldconfig; \
2023-11-28 11:04:40 +01:00
# Use Ruby on Rails to create Mastodon assets
2024-06-10 22:08:04 +02:00
SECRET_KEY_BASE_DUMMY = 1 \
2024-04-17 11:19:02 +02:00
bundle exec rails assets:precompile; \
2023-11-28 11:04:40 +01:00
# Cleanup temporary files
rm -fr /opt/mastodon/tmp;
2019-02-24 16:32:40 +01:00
2023-11-28 11:04:40 +01:00
# Prep final Mastodon Ruby layer
2024-06-21 22:26:39 +02:00
FROM ruby AS mastodon
2022-11-17 12:56:14 +01:00
2023-11-28 11:04:40 +01:00
ARG TARGETPLATFORM
2022-11-17 12:56:14 +01:00
2023-11-28 11:04:40 +01:00
# 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 \
# Mount 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 \
# Apt update install non-dev versions of necessary components
apt-get install -y --no-install-recommends \
2024-06-13 17:58:34 +02:00
libexpat1 \
libglib2.0-0 \
2023-11-28 11:04:40 +01:00
libicu72 \
libidn12 \
2024-06-13 17:58:34 +02:00
libpq5 \
2023-11-28 11:04:40 +01:00
libreadline8 \
2024-06-13 17:58:34 +02:00
libssl3 \
2023-11-28 11:04:40 +01:00
libyaml-0-2 \
2024-06-13 17:58:34 +02:00
# libvips components
libcgif0 \
libexif12 \
libheif1 \
libimagequant0 \
libjpeg62-turbo \
liblcms2-2 \
liborc-0.4-0 \
libspng0 \
libtiff6 \
libwebp7 \
libwebpdemux2 \
libwebpmux3 \
2024-06-18 16:51:51 +02:00
# ffmpeg components
libdav1d6 \
libmp3lame0 \
libopencore-amrnb0 \
libopencore-amrwb0 \
libopus0 \
libsnappy1v5 \
libtheora0 \
libvorbis0a \
libvorbisenc2 \
libvorbisfile3 \
libvpx7 \
libx264-164 \
libx265-199 \
2023-11-28 11:04:40 +01:00
;
2019-03-08 16:12:48 +01:00
2023-11-28 11:04:40 +01:00
# Copy Mastodon sources into final layer
COPY . /opt/mastodon/
2019-02-24 16:32:40 +01:00
2023-11-28 11:04:40 +01:00
# 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/
2024-06-13 17:58:34 +02:00
# 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
2024-06-18 16:51:51 +02:00
# 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
2024-06-13 17:58:34 +02:00
RUN \
ldconfig; \
# Smoketest media processors
2024-06-18 16:51:51 +02:00
vips -v; \
ffmpeg -version; \
ffprobe -version;
2019-02-24 16:32:40 +01:00
2023-11-28 11:04:40 +01:00
RUN \
2024-06-13 17:58:34 +02:00
# Precompile bootsnap code for faster Rails startup
2023-11-28 11:04:40 +01:00
bundle exec bootsnap precompile --gemfile app/ lib/;
2018-02-20 17:25:01 +01:00
2023-11-28 11:04:40 +01:00
RUN \
# Pre-create and chown system volume to Mastodon user
mkdir -p /opt/mastodon/public/system; \
2023-11-30 17:11:21 +01:00
chown mastodon:mastodon /opt/mastodon/public/system; \
# Set Mastodon user as owner of tmp folder
chown -R mastodon:mastodon /opt/mastodon/tmp;
2018-07-15 01:19:09 +02:00
2023-11-28 11:04:40 +01:00
# Set the running user for resulting container
USER mastodon
# Expose default Puma ports
EXPOSE 3000
# Set container tini as default entry point
2024-04-24 10:21:05 +02:00
ENTRYPOINT [ "/usr/bin/tini" , "--" ]