diff --git a/apps/api/src/runner-jobs/runner-jobs.module.ts b/apps/api/src/runner-jobs/runner-jobs.module.ts index 6623e2c..828fff2 100644 --- a/apps/api/src/runner-jobs/runner-jobs.module.ts +++ b/apps/api/src/runner-jobs/runner-jobs.module.ts @@ -3,6 +3,7 @@ import { RunnerJobsController } from "./runner-jobs.controller"; import { RunnerJobsService } from "./runner-jobs.service"; import { PrismaModule } from "../prisma/prisma.module"; import { BullMqModule } from "../bullmq/bullmq.module"; +import { AuthModule } from "../auth/auth.module"; /** * Runner Jobs Module @@ -11,7 +12,7 @@ import { BullMqModule } from "../bullmq/bullmq.module"; * for asynchronous job processing. */ @Module({ - imports: [PrismaModule, BullMqModule], + imports: [PrismaModule, BullMqModule, AuthModule], controllers: [RunnerJobsController], providers: [RunnerJobsService], exports: [RunnerJobsService], diff --git a/apps/orchestrator/Dockerfile b/apps/orchestrator/Dockerfile index 3064704..e66574d 100644 --- a/apps/orchestrator/Dockerfile +++ b/apps/orchestrator/Dockerfile @@ -1,51 +1,58 @@ -# ============================================ -# Multi-stage build for security and size -# ============================================ +# syntax=docker/dockerfile:1 +# Enable BuildKit features for cache mounts -# ============================================ -# Stage 1: Base Image -# ============================================ +# Base image for all stages FROM node:20-alpine AS base -ENV PNPM_HOME="/pnpm" -ENV PATH="$PNPM_HOME:$PATH" -RUN corepack enable -# ============================================ -# Stage 2: Dependencies -# ============================================ -FROM base AS dependencies +# Install pnpm globally +RUN corepack enable && corepack prepare pnpm@10.27.0 --activate + +# Set working directory WORKDIR /app -# Copy dependency files -COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ -COPY apps/orchestrator/package.json ./apps/orchestrator/ +# Copy monorepo configuration files +COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./ +COPY turbo.json ./ + +# ====================== +# Dependencies stage +# ====================== +FROM base AS deps + +# Copy all package.json files for workspace resolution COPY packages/shared/package.json ./packages/shared/ COPY packages/config/package.json ./packages/config/ +COPY apps/orchestrator/package.json ./apps/orchestrator/ -# Install production dependencies only -RUN pnpm install --frozen-lockfile --prod +# Install ALL dependencies (not just production) +# This ensures NestJS packages and other required deps are available +RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store \ + pnpm install --frozen-lockfile -# ============================================ -# Stage 3: Builder -# ============================================ +# ====================== +# Builder stage +# ====================== FROM base AS builder -WORKDIR /app + +# Copy root node_modules from deps +COPY --from=deps /app/node_modules ./node_modules # Copy all source code -COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ -COPY apps/orchestrator ./apps/orchestrator COPY packages ./packages +COPY apps/orchestrator ./apps/orchestrator -# Install all dependencies (including dev) -RUN pnpm install --frozen-lockfile +# Copy workspace node_modules from deps +COPY --from=deps /app/packages/shared/node_modules ./packages/shared/node_modules +COPY --from=deps /app/packages/config/node_modules ./packages/config/node_modules +COPY --from=deps /app/apps/orchestrator/node_modules ./apps/orchestrator/node_modules -# Build the application -RUN pnpm --filter @mosaic/orchestrator build +# Build the orchestrator app using TurboRepo +RUN pnpm turbo build --filter=@mosaic/orchestrator -# ============================================ -# Stage 4: Production Runtime -# ============================================ -FROM node:20-alpine AS runtime +# ====================== +# Production stage +# ====================== +FROM node:20-alpine AS production # Add metadata labels LABEL maintainer="mosaic-team@mosaicstack.dev" @@ -56,29 +63,42 @@ LABEL org.opencontainers.image.vendor="Mosaic Stack" LABEL org.opencontainers.image.title="Mosaic Orchestrator" LABEL org.opencontainers.image.description="Agent orchestration service for Mosaic Stack" -# Install wget for health checks (if not present) -RUN apk add --no-cache wget +# Install wget and dumb-init +RUN apk add --no-cache wget dumb-init + +# Create non-root user +RUN addgroup -g 1001 -S nodejs && adduser -S nestjs -u 1001 -# Create non-root user and group (node user already exists in alpine) -# UID/GID 1000 is the default node user in alpine images WORKDIR /app -# Copy built application with proper ownership -COPY --from=builder --chown=node:node /app/apps/orchestrator/dist ./dist -COPY --from=dependencies --chown=node:node /app/node_modules ./node_modules +# Copy node_modules from builder (includes all dependencies) +COPY --from=builder --chown=nestjs:nodejs /app/node_modules ./node_modules -# Set proper permissions -RUN chown -R node:node /app +# Copy built packages (includes dist/ directories) +COPY --from=builder --chown=nestjs:nodejs /app/packages ./packages + +# Copy built orchestrator application +COPY --from=builder --chown=nestjs:nodejs /app/apps/orchestrator/dist ./apps/orchestrator/dist +COPY --from=builder --chown=nestjs:nodejs /app/apps/orchestrator/package.json ./apps/orchestrator/ + +# Copy app's node_modules which contains symlinks to root node_modules +COPY --from=builder --chown=nestjs:nodejs /app/apps/orchestrator/node_modules ./apps/orchestrator/node_modules + +# Set working directory to orchestrator app +WORKDIR /app/apps/orchestrator # Switch to non-root user -USER node +USER nestjs -# Expose port +# Expose orchestrator port EXPOSE 3001 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:3001/health || exit 1 +# Use dumb-init to handle signals properly +ENTRYPOINT ["dumb-init", "--"] + # Start the application CMD ["node", "dist/main.js"]