# Builds the API image. The same image runs the API server, the worker, and migrations # (see docker-compose.yml). Build from the repo root: docker build -f apps/api/Dockerfile . FROM node:22-bookworm-slim AS base WORKDIR /app # Prune the monorepo to just the API and what it depends on, so unrelated changes # (e.g. a new web dependency) don't invalidate the install layer. FROM base AS prepare RUN npm install -g turbo@2.11.7 COPY . . RUN turbo prune @musicshare/api --docker FROM base AS builder COPY --from=prepare /app/out/json/ . RUN npm ci COPY --from=prepare /app/out/full/ . # turbo prune only copies workspaces; the shared tsconfig they extend lives at the root COPY --from=prepare /app/tsconfig.base.json ./tsconfig.base.json RUN npx turbo run build --filter=@musicshare/api \ && npm prune --omit=dev \ && mkdir -p apps/api/node_modules FROM base AS runner ENV NODE_ENV=production \ MIGRATIONS_DIR=/app/apps/api/drizzle COPY --from=builder --chown=node:node /app/package.json ./package.json COPY --from=builder --chown=node:node /app/node_modules ./node_modules COPY --from=builder --chown=node:node /app/apps/api/package.json ./apps/api/package.json COPY --from=builder --chown=node:node /app/apps/api/node_modules ./apps/api/node_modules COPY --from=builder --chown=node:node /app/apps/api/dist ./apps/api/dist COPY --from=builder --chown=node:node /app/apps/api/drizzle ./apps/api/drizzle WORKDIR /app/apps/api USER node EXPOSE 4000 HEALTHCHECK --interval=10s --timeout=3s --start-period=10s --retries=3 \ CMD node -e "fetch('http://127.0.0.1:' + (process.env.PORT || 4000) + '/health').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))" CMD ["node", "dist/server.js"]