FROM node:24.15.0-alpine3.23 AS builder ENV LANG=C.UTF-8 RUN apk add --no-cache python3 make g++ py3-setuptools libc6-compat COPY . /app ENV NODE_ENV=production RUN cd /app/bundle/programs/server \ && npm install --omit=dev \ && npm cache clean --force \ # Drop sourcemaps from third-party prod deps and the client bundle: # - server/npm/node_modules: .map files shipped inside packages # (openpgp, date-fns, etc.). Node does not read them at runtime. # - web.browser: client-side bundle, maps have no runtime value in the image. # Maps under /app/bundle/programs/server/{app,packages,node_modules/meteor} # are loaded by Meteor's source-map-support at boot, so they are kept. && find /app/bundle/programs/server/npm/node_modules -type f -name '*.map' -delete \ && find /app/bundle/programs/web.browser -type f -name '*.map' -delete \ # The bundle carries build/Release output compiled on the glibc CI host. # node-gyp-build prefers it over prebuilds/, so that binary shadows the musl # one shipped in the same package and fails to load at runtime. && STALE_BUILDS="$(find /app/bundle/programs/server/npm/node_modules -type d -name prebuilds)" \ && for d in $STALE_BUILDS; do rm -rf "${d%/prebuilds}/build"; done FROM node:24.15.0-alpine3.23 AS release-standard LABEL maintainer="buildmaster@rocket.chat" ENV LANG=C.UTF-8 # `nogroup` group is historically reserved for NFS. # We don't use any NFS related tools in this image. # For the same reason of NFS using the gid, we can also use it as long as there are no conflicts in terms of running processes with the same egid (which is 1 in our case). # While 65533 raw gid could be used, renaming nogroup to rocketchat here for maximum compatibility with older debian image. # More info on nobody/nogroup - https://wiki.ubuntu.com/nobody # Debian wiki - https://wiki.debian.org/SystemGroups # """ # daemon: Some unprivileged daemons that need to write to files on disk run as daemon.daemon (e.g., portmap, atd, probably others). # Daemons that don't need to own any files can run as nobody.nogroup instead, # and more complex or security conscious daemons run as dedicated users. # The daemon user is also handy for locally installed daemons. # """ RUN apk add --no-cache shadow deno ttf-dejavu \ # Update OpenSSL # CVE -> https://scout.docker.com/vulnerabilities/id/CVE-2025-9230?s=alpine&n=openssl&ns=alpine&t=apk&osn=alpine&osv=3.22 && apk upgrade --no-cache openssl \ && groupmod -n rocketchat nogroup \ && useradd -u 65533 -r -g rocketchat rocketchat # needs a mongo instance - defaults to container linking with alias 'mongo' ENV DEPLOY_METHOD=docker \ NODE_ENV=production \ MONGO_URL=mongodb://mongo:27017/rocketchat \ HOME=/tmp \ PORT=3000 \ ROOT_URL=http://localhost:3000 \ Accounts_AvatarStorePath=/app/uploads USER rocketchat COPY --from=builder --chown=rocketchat:rocketchat /app /app VOLUME /app/uploads WORKDIR /app/bundle EXPOSE 3000 CMD ["node", "main.js"] FROM rocketchat/dhi-node:24.15.0-alpine3.23-fips AS release-fips LABEL maintainer="buildmaster@rocket.chat" # needs a mongo instance - defaults to container linking with alias 'mongo' ENV DEPLOY_METHOD=docker \ NODE_ENV=production \ MONGO_URL=mongodb://mongo:27017/rocketchat \ HOME=/tmp \ PORT=3000 \ ROOT_URL=http://localhost:3000 \ Accounts_AvatarStorePath=/app/uploads \ APPS_ENGINE_RUNTIME_BACKEND=node # the hardened image has no /etc/alpine-release, so node-gyp-build would detect # glibc and load the wrong prebuild for native modules ENV LIBC=musl USER node COPY --from=builder --chown=node:node /app /app VOLUME /app/uploads WORKDIR /app/bundle EXPOSE 3000 CMD ["node", "--force-fips", "main.js"]