---
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/<product>
```

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:<port>/health | jq .

# Check logs
docker compose logs backend --tail=20

# Run smoke test
curl -s http://localhost:<port>/api/<endpoint> | jq .

# Cleanup
docker compose down
```

### 4. Security Scan

```bash
# Scan the built image
docker scout cves <image>

# Check for leaked secrets
docker history <image> --no-trunc | grep -i "secret\|key\|password"
```

### 5. Optimize Image Size

```bash
# Check image size
docker images | grep <product>

# 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
