--- name: docker-production-prep description: 'Prepare Docker images for production deployment following ByteLyst conventions for corporate network, multi-stage builds, and security.' argument-hint: 'Product and surface, e.g. "efforise backend", "flowmonk backend + web", "all product backends"' agent: agent --- # Docker Production Prep Prompt Build production-ready Docker images for ByteLyst services following network, security, and performance best practices. ## Context — ByteLyst Docker Conventions **Critical rules from corporate network:** - **Never use Alpine** — `apk` cannot bypass TLS interception; use `node:22-slim` (Debian) - **Never use `corepack`** in Dockerfiles — use `npm install -g pnpm@10` or plain `npm` - **Always add** `npm config set strict-ssl false` before any `npm install` in build stages - **Always add** `ENV NODE_TLS_REJECT_UNAUTHORIZED=0` in build stages with native modules - **Production images** don't need these workarounds (only build stages) ## Dockerfile Template (Backend Service) ```dockerfile # ── Build Stage ──────────────────────────────────── FROM node:22-slim AS builder # Corporate network workaround (build stage only) RUN npm config set strict-ssl false ENV NODE_TLS_REJECT_UNAUTHORIZED=0 WORKDIR /app # Install pnpm (never use corepack) RUN npm install -g pnpm@10 # Copy workspace files COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ COPY backend/package.json backend/ COPY shared/ shared/ # Copy @bytelyst/* tarballs (if using prep-consumer.sh) COPY .bytelyst-tarballs/ .bytelyst-tarballs/ # Install dependencies RUN pnpm install --frozen-lockfile # Copy source and build COPY backend/ backend/ RUN cd backend && pnpm build # ── Production Stage ─────────────────────────────── FROM node:22-slim AS production WORKDIR /app # Non-root user for security RUN groupadd -r appuser && useradd -r -g appuser appuser # Copy only production artifacts COPY --from=builder /app/backend/dist/ ./dist/ COPY --from=builder /app/backend/package.json ./ COPY --from=builder /app/shared/ ./shared/ COPY --from=builder /app/node_modules/ ./node_modules/ # Security headers ENV NODE_ENV=production # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD node -e "fetch('http://localhost:${PORT:-4020}/health').then(r => r.ok ? process.exit(0) : process.exit(1)).catch(() => process.exit(1))" # Run as non-root USER appuser EXPOSE ${PORT:-4020} CMD ["node", "dist/server.js"] ``` ## Preparation Steps ### 1. Pack @bytelyst/* Dependencies If the Docker build doesn't have access to the sibling common_plat repo: ```bash cd ../learning_ai_common_plat ./scripts/prep-consumer.sh /path/to/ ``` This packs tarballs and rewrites `file:` refs in package.json. ### 2. Create/Update docker-compose.yml ```yaml services: backend: build: context: . dockerfile: backend/Dockerfile ports: - "${PORT:-4020}:${PORT:-4020}" env_file: ./backend/.env restart: unless-stopped depends_on: platform-service: condition: service_healthy healthcheck: test: ["CMD", "node", "-e", "fetch('http://localhost:${PORT:-4020}/health')"] interval: 30s timeout: 3s retries: 3 web: build: context: . dockerfile: web/Dockerfile ports: - "3000:3000" environment: - NEXT_PUBLIC_API_URL=http://backend:${PORT:-4020} ``` ### 3. Build & Test Locally ```bash # Build docker compose build # Run docker compose up -d # Verify health docker compose ps curl -s http://localhost:/health | jq . # Check logs docker compose logs backend --tail=20 # Run smoke test curl -s http://localhost:/api/ | jq . # Cleanup docker compose down ``` ### 4. Security Scan ```bash # Scan the built image docker scout cves # Check for leaked secrets docker history --no-trunc | grep -i "secret\|key\|password" ``` ### 5. Optimize Image Size ```bash # Check image size docker images | grep # Target: < 200MB for backend services # If too large, check: # - Are devDependencies excluded? (use --prod install) # - Is the build stage copying unnecessary files? # - Are node_modules pruned in the production stage? ``` ### 6. Commit ```bash git add Dockerfile docker-compose.yml git commit -m "chore(docker): production-ready Docker setup - Multi-stage build (builder + production) - Non-root user for security - Health check configured - Corporate network workarounds in build stage only - Production image: ~NMB" git push ``` ## Checklist - [ ] Base image: `node:22-slim` (never Alpine) - [ ] No `corepack` usage - [ ] `strict-ssl false` in build stage - [ ] Multi-stage build (builder → production) - [ ] Non-root user in production stage - [ ] Health check configured - [ ] `NODE_ENV=production` in production stage - [ ] No secrets in image layers - [ ] `.dockerignore` excludes: node_modules, .git, .env, dist, coverage - [ ] Image size < 200MB