405 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Docker
		
	
	
	
	
	
			
		
		
	
	
			405 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Docker
		
	
	
	
	
	
| # syntax=docker/dockerfile:1.8
 | |
| 
 | |
| # 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.4"
 | |
| # # 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.2
 | |
| # 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
 | |
| 
 | |
| RUN \
 | |
|   curl -sSL -o vips-${VIPS_VERSION}.tar.xz ${VIPS_URL}/v${VIPS_VERSION}/vips-${VIPS_VERSION}.tar.xz; \
 | |
|   tar xf vips-${VIPS_VERSION}.tar.xz; \
 | |
|   cd vips-${VIPS_VERSION}; \
 | |
|   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.0.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
 | |
| 
 | |
| RUN \
 | |
|   curl -sSL -o ffmpeg-${FFMPEG_VERSION}.tar.xz ${FFMPEG_URL}/ffmpeg-${FFMPEG_VERSION}.tar.xz; \
 | |
|   tar xf ffmpeg-${FFMPEG_VERSION}.tar.xz; \
 | |
|   cd ffmpeg-${FFMPEG_VERSION}; \
 | |
|   ./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", "--"]
 |