# This docker file uses a multi-stage build pattern as described here: # https://github.com/goldbergyoni/nodebestpractices/blob/master/sections/docker/multi_stage_builds.md ############################################################################### ############## Stage 1: Create pruned version of monorepo ##################### ############################################################################### FROM node:22.4.1-slim AS prune USER node RUN mkdir /home/node/app WORKDIR /home/node/app # Run turbo prune to create a pruned version of monorepo COPY --chown=node:node ./package.json ./package.json RUN yarn global add turbo@$(node -e "console.log(require('./package.json').devDependencies.turbo)") COPY --chown=node:node . . RUN /home/node/.yarn/bin/turbo prune --scope=@farcaster/hubble --docker ############################################################################### ############## Stage 2: Build the code using a full node image ################ ############################################################################### FROM node:22.4.1-slim AS build # Needed for compilation step RUN apt-get update && apt-get install -y python3 make g++ linux-headers-generic curl protobuf-compiler libclang-dev cmake USER node RUN mkdir /home/node/app WORKDIR /home/node/app # Install Rust # Make sure this matches what we do locally and in CI RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.77.0 ENV PATH="/home/node/.cargo/bin:${PATH}" # Rust flags to allow building with musl, which is needed for alpine ENV RUSTFLAGS="-C target-feature=-crt-static" # Copy dependency information and install all dependencies COPY --chown=node:node --from=prune /home/node/app/out/json/ . COPY --chown=node:node --from=prune /home/node/app/out/yarn.lock ./yarn.lock # Restore commented line if we patch-package again: # COPY --chown=node:node patches patches RUN yarn install --frozen-lockfile --network-timeout 1800000 RUN yarn postinstall # Copy source code (and all other relevant files) COPY --chown=node:node --from=prune /home/node/app/out/full/ . # turbo prune doesn't include global tsconfig.json (https://github.com/vercel/turbo/issues/2177) COPY --chown=node:node tsconfig.json tsconfig.json COPY --chown=node:node protobufs protobufs # Build code RUN yarn build # Purge dev dependencies and only install production dependencies RUN rm -rf node_modules && yarn install --production --ignore-scripts --prefer-offline --force --frozen-lockfile && yarn postinstall ############################################################################### ########## Stage 3: Copy over the built code to a leaner alpine image ######### ############################################################################### FROM node:22.4.1-slim as app RUN apt-get update && apt-get install -y curl procps # Set non-root user and expose ports USER node # Many npm packages use this to trigger production optimized behaviors ENV NODE_ENV production RUN mkdir /home/node/app WORKDIR /home/node/app # Copy results from previous stage. # The base image is same as the build stage, so it is safe to copy node_modules over to this stage. COPY --chown=node:node --from=prune /home/node/app/out/json/ . COPY --chown=node:node --from=build /home/node/app/apps/hubble/build ./apps/hubble/build COPY --chown=node:node --from=build /home/node/app/node_modules ./node_modules COPY --chown=node:node --from=build /home/node/app/packages/core/dist ./packages/core/dist/ COPY --chown=node:node --from=build /home/node/app/packages/hub-nodejs/dist ./packages/hub-nodejs/dist/ # BuildKit doesn't support --squash flag, so emulate by copying into fewer layers FROM scratch COPY --from=app / / # Repeat of above since it is lost between build stages USER node EXPOSE 2282 EXPOSE 2283 WORKDIR /home/node/app/apps/hubble # Run using pm2 as supervisor for faster recoveries on failure COPY --chown=node:node ./apps/hubble/pm2.config.cjs ./pm2.config.cjs ENV NODE_ARGS="--max-old-space-size=8192" ENV HUBBLE_ARGS="start --network 1" CMD ["npx", "pm2-runtime", "start", "pm2.config.cjs"]