FROM node:20.19-bullseye-slim AS builder # Install required system dependencies RUN apt-get update && apt-get install -y \ postgresql-client \ redis-tools \ curl \ bash \ && rm -rf /var/lib/apt/lists/* WORKDIR /app # Install global TypeScript and build tools RUN npm install -g typescript @types/node tsc-alias # Copy base configuration and root package files for workspace setup COPY tsconfig.base.json ./ COPY tsconfig.json ./ COPY package.json package-lock.json ./ # Copy all workspace package.json files to set up the dependency tree COPY ee/packages/workflows/package.json ./ee/packages/workflows/ COPY ee/temporal-workflows/package.json ./ee/temporal-workflows/ COPY packages/ee/package.json ./packages/ee/ COPY shared/package.json ./shared/ COPY services/workflow-worker/package.json ./services/workflow-worker/ COPY server/package.json ./server/ COPY packages/core/package.json ./packages/core/ COPY packages/authorization/package.json ./packages/authorization/ COPY packages/db/package.json ./packages/db/ COPY packages/event-bus/package.json ./packages/event-bus/ COPY packages/event-schemas/package.json ./packages/event-schemas/ COPY packages/formatting/package.json ./packages/formatting/ COPY packages/portal-shared/package.json ./packages/portal-shared/ COPY packages/storage/package.json ./packages/storage/ COPY packages/types/package.json ./packages/types/ COPY packages/ui/package.json ./packages/ui/ # Install dependencies for required workspaces (shared, worker, server, and required @alga-psa/* deps) # Skip puppeteer Chrome download to save disk space RUN npm config set legacy-peer-deps true && PUPPETEER_SKIP_DOWNLOAD=true npm install --include-workspace-root \ --workspace=@alga-psa/workflows \ --workspace=temporal-workflows \ --workspace=@alga-psa/ee-stubs \ --workspace=@alga-psa/shared \ --workspace=workflow-worker \ --workspace=server \ --workspace=@alga-psa/core \ --workspace=@alga-psa/authorization \ --workspace=@alga-psa/db \ --workspace=@alga-psa/event-bus \ --workspace=@alga-psa/event-schemas \ --workspace=@alga-psa/formatting \ --workspace=@alga-psa/portal-shared \ --workspace=@alga-psa/storage \ --workspace=@alga-psa/types \ --workspace=@alga-psa/validation \ --workspace=@alga-psa/email \ --workspace=@alga-psa/ui \ && npm install --no-save openai@^4.104.0 # Copy source code for shared + server workspaces COPY ee/packages/workflows/ ./ee/packages/workflows/ COPY ee/temporal-workflows/ ./ee/temporal-workflows/ COPY ee/server/ ./ee/server/ COPY shared/ ./shared/ COPY server/ ./server/ COPY packages/ ./packages/ # Build core workspace dependencies that export dist artifacts consumed by runtime packages. WORKDIR /app/packages/core RUN npm run build WORKDIR /app/packages/types RUN npm run build WORKDIR /app/packages/db RUN npm run build # packages/db currently emits under dist/db/src when built in the worker image because # it compiles path-mapped sources from the monorepo. Normalize the output to the # package.json exports expected by Node at runtime. RUN if [ -d dist/db/src ]; then cp -R dist/db/src/. dist/; fi \ && tsc-alias -p tsconfig.json -f --resolve-full-paths WORKDIR /app/packages/authorization RUN npm run build WORKDIR /app/packages/formatting RUN npm run build WORKDIR /app/packages/validation RUN npm run build WORKDIR /app/packages/storage RUN npm run build # Build event schemas (required by workflow streams runtime) WORKDIR /app/packages/event-schemas RUN npm run build # Build event bus (required by shared) WORKDIR /app/packages/event-bus RUN npm run build # Build shared workspace first (server is only referenced for type imports) WORKDIR /app/shared RUN npm run build # Build workflow package dist so Temporal-authored modules can resolve runtime exports. WORKDIR /app/ee/packages/workflows RUN npm run build # Build temporal workflows so workflow-worker can host authored queue polling. WORKDIR /app/ee/temporal-workflows RUN npm run build # Copy workflow worker source code and build WORKDIR /app/services/workflow-worker COPY services/workflow-worker/ ./ RUN npm run build # Copy and make entrypoint executable COPY services/workflow-worker/entrypoint.sh /app/entrypoint.sh RUN chmod +x /app/entrypoint.sh # Trim build-time-only bulk HERE (in the builder), so the runtime COPY below # captures the already-trimmed tree — deleting after the COPY would not reclaim # space. server/ is type-imports-only at build; the worker's dist never loads it. RUN rm -rf /app/server /app/node_modules/server \ && npm cache clean --force 2>/dev/null || true # --------------------------------------------------------------------------- # Runtime stage: a fresh image with only what the worker needs at runtime. # The builder above keeps every workspace's source + devDeps + intermediate # layers (~10GB). The worker runs `node dist/.../index.js`, which resolves # @alga-psa/* via node_modules -> packages/*/dist, and does NOT load server/ # (build-time type imports only) or the UI/build libs. Copying the final /app # into a clean stage drops the intermediate layers; removing server/ source # reclaims ~2GB more. # --------------------------------------------------------------------------- FROM node:20.19-bullseye-slim AS runtime RUN apt-get update && apt-get install -y \ postgresql-client \ redis-tools \ curl \ bash \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY --from=builder /app /app ENV NODE_ENV=production ENTRYPOINT ["/app/entrypoint.sh"]