123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- # syntax=docker/dockerfile:1.10
- # 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
- # 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}
- # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.3.x"]
- # renovate: datasource=docker depName=docker.io/ruby
- ARG RUBY_VERSION="3.3.5"
- # # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
- # renovate: datasource=node-version depName=node
- ARG NODE_MAJOR_VERSION="20"
- # 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)
- FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node
- # Ruby image to use for base image based on combined variables (ex: 3.3.x-slim-bookworm)
- FROM docker.io/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=""
- # 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 \
- # 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
- MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" \
- # Enable libvips, should not be changed
- 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
- # 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 \
- # 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 \
- wget \
- ; \
- # 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
- FROM ruby AS build
- # 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
- # 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 \
- autoconf \
- automake \
- build-essential \
- cmake \
- git \
- libgdbm-dev \
- libglib2.0-dev \
- libgmp-dev \
- libicu-dev \
- libidn-dev \
- libpq-dev \
- libssl-dev \
- libtool \
- meson \
- nasm \
- pkg-config \
- shared-mime-info \
- xz-utils \
- # 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 \
- # ffmpeg components
- libdav1d-dev \
- liblzma-dev \
- libmp3lame-dev \
- libopus-dev \
- libsnappy-dev \
- libvorbis-dev \
- libvpx-dev \
- libx264-dev \
- libx265-dev \
- ;
- RUN \
- # Configure Corepack
- rm /usr/local/bin/yarn*; \
- corepack enable; \
- corepack prepare --activate;
- # Create temporary libvips specific build layer from build layer
- FROM 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.15.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 and compile libvips
- RUN \
- meson setup build --prefix /usr/local/libvips --libdir=lib -Ddeprecated=false -Dintrospection=disabled -Dmodules=disabled -Dexamples=false; \
- cd build; \
- ninja; \
- ninja install;
- # Create temporary ffmpeg specific build layer from build layer
- FROM build AS ffmpeg
- # ffmpeg version to compile, change with [--build-arg FFMPEG_VERSION="7.0.x"]
- # renovate: datasource=repology depName=ffmpeg packageName=openpkg_current/ffmpeg
- ARG FFMPEG_VERSION=7.1
- # 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
- # 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}
- # 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 bundler specific build layer from build layer
- FROM build AS bundler
- 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
- FROM build AS yarn
- ARG TARGETPLATFORM
- # Copy Node package configuration files into working directory
- COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
- COPY streaming/package.json /opt/mastodon/streaming/
- COPY .yarn /opt/mastodon/.yarn
- # 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;
- # Create temporary assets build layer from build layer
- FROM build AS precompiler
- # Copy Mastodon sources into precompiler layer
- COPY . /opt/mastodon/
- # 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/
- # 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
- ARG TARGETPLATFORM
- 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
- # 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 \
- libexpat1 \
- libglib2.0-0 \
- libicu72 \
- libidn12 \
- libpq5 \
- libreadline8 \
- libssl3 \
- libyaml-0-2 \
- # libvips components
- libcgif0 \
- libexif12 \
- libheif1 \
- libimagequant0 \
- libjpeg62-turbo \
- liblcms2-2 \
- liborc-0.4-0 \
- libspng0 \
- libtiff6 \
- libwebp7 \
- libwebpdemux2 \
- libwebpmux3 \
- # ffmpeg components
- libdav1d6 \
- libmp3lame0 \
- libopencore-amrnb0 \
- libopencore-amrwb0 \
- libopus0 \
- libsnappy1v5 \
- libtheora0 \
- libvorbis0a \
- libvorbisenc2 \
- libvorbisfile3 \
- libvpx7 \
- libx264-164 \
- libx265-199 \
- ;
- # 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/;
- 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", "--"]
|