diff --git a/services/extraction-service/Dockerfile b/services/extraction-service/Dockerfile new file mode 100644 index 00000000..7b0f63d2 --- /dev/null +++ b/services/extraction-service/Dockerfile @@ -0,0 +1,72 @@ +# Build context: repo root (docker compose sets context: .) +# Multi-stage: Node.js build + Python sidecar + supervisord runtime + +# ── Stage 1: Node.js build ─────────────────────────────────────── +FROM node:22-alpine AS ts-builder +RUN npm install -g pnpm@10 +WORKDIR /app + +# Copy workspace config + lockfile for dependency resolution +COPY package.json pnpm-workspace.yaml pnpm-lock.yaml tsconfig.base.json ./ + +# Copy all package.json files (pnpm needs these for workspace resolution) +COPY packages/errors/package.json packages/errors/ +COPY packages/cosmos/package.json packages/cosmos/ +COPY packages/config/package.json packages/config/ +COPY packages/auth/package.json packages/auth/ +COPY packages/api-client/package.json packages/api-client/ +COPY packages/fastify-core/package.json packages/fastify-core/ +COPY packages/logger/package.json packages/logger/ +COPY packages/react-auth/package.json packages/react-auth/ +COPY packages/design-tokens/package.json packages/design-tokens/ +COPY packages/testing/package.json packages/testing/ +COPY packages/extraction/package.json packages/extraction/ +COPY services/extraction-service/package.json services/extraction-service/ + +# Install all workspace deps +RUN pnpm install --frozen-lockfile + +# Copy source +COPY packages/ packages/ +COPY services/extraction-service/tsconfig.json services/extraction-service/ +COPY services/extraction-service/src/ services/extraction-service/src/ + +# Build packages first, then service +RUN pnpm -r --filter @lysnrai/extraction-service... build + +# Deploy to isolated directory (production deps only) +RUN pnpm --filter @lysnrai/extraction-service deploy /app/deploy + +# ── Stage 2: Python sidecar build ──────────────────────────────── +FROM python:3.12-slim AS py-builder +WORKDIR /sidecar + +COPY services/extraction-service/python/requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY services/extraction-service/python/src/ src/ + +# ── Stage 3: Production runtime ────────────────────────────────── +FROM node:22-alpine +RUN apk add --no-cache python3 py3-pip supervisor + +WORKDIR /app + +# Copy Node.js service +COPY --from=ts-builder /app/deploy ./ + +# Copy Python sidecar + installed packages +COPY --from=py-builder /usr/local/lib/python3.12/site-packages /usr/lib/python3/dist-packages +COPY --from=py-builder /usr/local/bin/uvicorn /usr/local/bin/uvicorn +COPY --from=py-builder /sidecar/src /app/python/src + +# Copy supervisord config +COPY services/extraction-service/supervisord.conf /etc/supervisor/conf.d/extraction.conf + +ENV NODE_ENV=production +ENV PYTHON_SIDECAR_URL=http://localhost:4006 + +EXPOSE 4005 +EXPOSE 4006 + +CMD ["supervisord", "-c", "/etc/supervisor/conf.d/extraction.conf"] diff --git a/services/extraction-service/supervisord.conf b/services/extraction-service/supervisord.conf new file mode 100644 index 00000000..89a36513 --- /dev/null +++ b/services/extraction-service/supervisord.conf @@ -0,0 +1,27 @@ +[supervisord] +nodaemon=true +logfile=/dev/stdout +logfile_maxbytes=0 +loglevel=info + +[program:fastify] +command=node dist/server.js +directory=/app +autostart=true +autorestart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +environment=NODE_ENV="production",PORT="4005" + +[program:python-sidecar] +command=uvicorn src.app:app --host 0.0.0.0 --port 4006 --workers 1 +directory=/app/python +autostart=true +autorestart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 +environment=PYTHONUNBUFFERED="1"