Dockerfile 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. # syntax=docker/dockerfile:1.7
  2. # Please see https://docs.docker.com/engine/reference/builder for information about
  3. # the extended buildx capabilities used in this file.
  4. # Make sure multiarch TARGETPLATFORM is available for interpolation
  5. # See: https://docs.docker.com/build/building/multi-platform/
  6. ARG TARGETPLATFORM=${TARGETPLATFORM}
  7. ARG BUILDPLATFORM=${BUILDPLATFORM}
  8. # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.2.3"]
  9. ARG RUBY_VERSION="3.2.3"
  10. # # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
  11. ARG NODE_MAJOR_VERSION="20"
  12. # Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
  13. ARG DEBIAN_VERSION="bookworm"
  14. # Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
  15. FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as node
  16. # Ruby image to use for base image based on combined variables (ex: 3.2.3-slim-bookworm)
  17. FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} as ruby
  18. # Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
  19. # Example: v4.2.0-nightly.2023.11.09+something
  20. # Overwrite existence of 'alpha.0' in version.rb [--build-arg MASTODON_VERSION_PRERELEASE="nightly.2023.11.09"]
  21. ARG MASTODON_VERSION_PRERELEASE=""
  22. # Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="something"]
  23. ARG MASTODON_VERSION_METADATA=""
  24. # Allow Ruby on Rails to serve static files
  25. # See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files
  26. ARG RAILS_SERVE_STATIC_FILES="true"
  27. # Allow to use YJIT compiler
  28. # See: https://github.com/ruby/ruby/blob/v3_2_3/doc/yjit/yjit.md
  29. ARG RUBY_YJIT_ENABLE="1"
  30. # Timezone used by the Docker container and runtime, change with [--build-arg TZ=Europe/Berlin]
  31. ARG TZ="Etc/UTC"
  32. # Linux UID (user id) for the mastodon user, change with [--build-arg UID=1234]
  33. ARG UID="991"
  34. # Linux GID (group id) for the mastodon user, change with [--build-arg GID=1234]
  35. ARG GID="991"
  36. # Apply Mastodon build options based on options above
  37. ENV \
  38. # Apply Mastodon version information
  39. MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \
  40. MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \
  41. # Apply Mastodon static files and YJIT options
  42. RAILS_SERVE_STATIC_FILES=${RAILS_SERVE_STATIC_FILES} \
  43. RUBY_YJIT_ENABLE=${RUBY_YJIT_ENABLE} \
  44. # Apply timezone
  45. TZ=${TZ}
  46. ENV \
  47. # Configure the IP to bind Mastodon to when serving traffic
  48. BIND="0.0.0.0" \
  49. # Use production settings for Yarn, Node and related nodejs based tools
  50. NODE_ENV="production" \
  51. # Use production settings for Ruby on Rails
  52. RAILS_ENV="production" \
  53. # Add Ruby and Mastodon installation to the PATH
  54. DEBIAN_FRONTEND="noninteractive" \
  55. PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" \
  56. # Optimize jemalloc 5.x performance
  57. MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0"
  58. # Set default shell used for running commands
  59. SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"]
  60. ARG TARGETPLATFORM
  61. RUN echo "Target platform is $TARGETPLATFORM"
  62. RUN \
  63. # Remove automatic apt cache Docker cleanup scripts
  64. rm -f /etc/apt/apt.conf.d/docker-clean; \
  65. # Sets timezone
  66. echo "${TZ}" > /etc/localtime; \
  67. # Creates mastodon user/group and sets home directory
  68. groupadd -g "${GID}" mastodon; \
  69. useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon; \
  70. # Creates /mastodon symlink to /opt/mastodon
  71. ln -s /opt/mastodon /mastodon;
  72. # Set /opt/mastodon as working directory
  73. WORKDIR /opt/mastodon
  74. # hadolint ignore=DL3008,DL3005
  75. RUN \
  76. # Mount Apt cache and lib directories from Docker buildx caches
  77. --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
  78. --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
  79. # Apt update & upgrade to check for security updates to Debian image
  80. apt-get update; \
  81. apt-get dist-upgrade -yq; \
  82. # Install jemalloc, curl and other necessary components
  83. apt-get install -y --no-install-recommends \
  84. ca-certificates \
  85. curl \
  86. ffmpeg \
  87. file \
  88. imagemagick \
  89. libjemalloc2 \
  90. patchelf \
  91. procps \
  92. tini \
  93. tzdata \
  94. wget \
  95. ; \
  96. # Patch Ruby to use jemalloc
  97. patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \
  98. # Discard patchelf after use
  99. apt-get purge -y \
  100. patchelf \
  101. ;
  102. # Create temporary build layer from base image
  103. FROM ruby as build
  104. # Copy Node package configuration files into working directory
  105. COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
  106. COPY .yarn /opt/mastodon/.yarn
  107. COPY --from=node /usr/local/bin /usr/local/bin
  108. COPY --from=node /usr/local/lib /usr/local/lib
  109. ARG TARGETPLATFORM
  110. # hadolint ignore=DL3008
  111. RUN \
  112. # Mount Apt cache and lib directories from Docker buildx caches
  113. --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
  114. --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
  115. # Install build tools and bundler dependencies from APT
  116. apt-get install -y --no-install-recommends \
  117. g++ \
  118. gcc \
  119. git \
  120. libgdbm-dev \
  121. libgmp-dev \
  122. libicu-dev \
  123. libidn-dev \
  124. libpq-dev \
  125. libssl-dev \
  126. make \
  127. shared-mime-info \
  128. zlib1g-dev \
  129. ;
  130. RUN \
  131. # Configure Corepack
  132. rm /usr/local/bin/yarn*; \
  133. corepack enable; \
  134. corepack prepare --activate;
  135. # Create temporary bundler specific build layer from build layer
  136. FROM build as bundler
  137. ARG TARGETPLATFORM
  138. # Copy Gemfile config into working directory
  139. COPY Gemfile* /opt/mastodon/
  140. RUN \
  141. # Mount Ruby Gem caches
  142. --mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \
  143. # Configure bundle to prevent changes to Gemfile and Gemfile.lock
  144. bundle config set --global frozen "true"; \
  145. # Configure bundle to not cache downloaded Gems
  146. bundle config set --global cache_all "false"; \
  147. # Configure bundle to only process production Gems
  148. bundle config set --local without "development test"; \
  149. # Configure bundle to not warn about root user
  150. bundle config set silence_root_warning "true"; \
  151. # Download and install required Gems
  152. bundle install -j"$(nproc)";
  153. # Create temporary node specific build layer from build layer
  154. FROM build as yarn
  155. ARG TARGETPLATFORM
  156. # Copy Node package configuration files into working directory
  157. COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
  158. COPY streaming/package.json /opt/mastodon/streaming/
  159. COPY .yarn /opt/mastodon/.yarn
  160. # hadolint ignore=DL3008
  161. RUN \
  162. --mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
  163. --mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
  164. # Install Node packages
  165. yarn workspaces focus --production @mastodon/mastodon;
  166. # Create temporary assets build layer from build layer
  167. FROM build as precompiler
  168. # Copy Mastodon sources into precompiler layer
  169. COPY . /opt/mastodon/
  170. # Copy bundler and node packages from build layer to container
  171. COPY --from=yarn /opt/mastodon /opt/mastodon/
  172. COPY --from=bundler /opt/mastodon /opt/mastodon/
  173. COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
  174. ARG TARGETPLATFORM
  175. RUN \
  176. # Use Ruby on Rails to create Mastodon assets
  177. OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder bundle exec rails assets:precompile; \
  178. # Cleanup temporary files
  179. rm -fr /opt/mastodon/tmp;
  180. # Prep final Mastodon Ruby layer
  181. FROM ruby as mastodon
  182. ARG TARGETPLATFORM
  183. # hadolint ignore=DL3008
  184. RUN \
  185. # Mount Apt cache and lib directories from Docker buildx caches
  186. --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
  187. --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
  188. # Mount Corepack and Yarn caches from Docker buildx caches
  189. --mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
  190. --mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
  191. # Apt update install non-dev versions of necessary components
  192. apt-get install -y --no-install-recommends \
  193. libssl3 \
  194. libpq5 \
  195. libicu72 \
  196. libidn12 \
  197. libreadline8 \
  198. libyaml-0-2 \
  199. ;
  200. # Copy Mastodon sources into final layer
  201. COPY . /opt/mastodon/
  202. # Copy compiled assets to layer
  203. COPY --from=precompiler /opt/mastodon/public/packs /opt/mastodon/public/packs
  204. COPY --from=precompiler /opt/mastodon/public/assets /opt/mastodon/public/assets
  205. # Copy bundler components to layer
  206. COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
  207. RUN \
  208. # Precompile bootsnap code for faster Rails startup
  209. bundle exec bootsnap precompile --gemfile app/ lib/;
  210. RUN \
  211. # Pre-create and chown system volume to Mastodon user
  212. mkdir -p /opt/mastodon/public/system; \
  213. chown mastodon:mastodon /opt/mastodon/public/system; \
  214. # Set Mastodon user as owner of tmp folder
  215. chown -R mastodon:mastodon /opt/mastodon/tmp;
  216. # Set the running user for resulting container
  217. USER mastodon
  218. # Expose default Puma ports
  219. EXPOSE 3000
  220. # Set container tini as default entry point
  221. ENTRYPOINT ["/usr/bin/tini", "--"]