---
globs:
  - "**/Dockerfile"
  - "**/.dockerignore"
  - "docker-compose.yml"
---

# Docker and Containerization Rules

## Dockerfile Best Practices

### Multi-Stage Builds
```dockerfile
# Build stage
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM node:22-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/main.js"]
```

### Layer Optimization
- Order from least to most frequently changing
- Copy dependency files before source code
- Use `.dockerignore` to exclude unnecessary files

```dockerfile
# ✅ Good - Dependencies cached separately
COPY package.json package-lock.json ./
RUN npm ci
COPY . .

# ❌ Bad
COPY . .
RUN npm ci
```

### Base Images
- Use official images
- Prefer Alpine for smaller size
- Pin specific versions (avoid `latest`)

```dockerfile
# ✅ Good
FROM python:3.11-alpine
FROM node:22-alpine

# ❌ Bad
FROM python:latest
```

## Python Dockerfile (hermes-api)

```dockerfile
FROM python:3.11-slim as base

ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PIP_NO_CACHE_DIR=1

WORKDIR /app

# System dependencies (ffmpeg for yt-dlp)
RUN apt-get update && apt-get install -y ffmpeg && \
    rm -rf /var/lib/apt/lists/*

# Python dependencies
COPY pyproject.toml uv.lock ./
RUN pip install uv && uv pip install --system -r uv.lock

COPY . .

# Non-root user
RUN useradd -m -u 1000 hermes && \
    chown -R hermes:hermes /app

USER hermes

EXPOSE 8000

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
```

## Node.js Dockerfile (hermes-app)

```dockerfile
FROM node:22-alpine AS builder
WORKDIR /app

COPY package.json pnpm-lock.yaml ./
RUN corepack enable pnpm && pnpm install --frozen-lockfile

COPY . .
RUN pnpm build

# Production
FROM nginx:alpine AS production
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/dist /usr/share/nginx/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```

## .dockerignore

```dockerignore
# Version control
.git
.gitignore

# Dependencies
node_modules
__pycache__
*.pyc

# Environment
.env
.env.*
!.env.example

# Development
*.log
*.md
!README.md
.vscode

# Build artifacts
dist
build
*.egg-info

# Tests
tests
**/__tests__
*.test.js
*.test.ts

# Docker
Dockerfile
.dockerignore
docker-compose*.yml
```

## docker-compose.yml

```yaml
version: '3.8'

services:
  api:
    build:
      context: ./packages/hermes-api
      dockerfile: Dockerfile
    container_name: hermes-api
    ports:
      - "8000:8000"
    environment:
      - HERMES_SECRET_KEY=${HERMES_SECRET_KEY}
      - REDIS_URL=redis://redis:6379/0
    volumes:
      - ./packages/hermes-api/data:/app/data
      - ./packages/hermes-api/downloads:/app/downloads
    depends_on:
      - redis
    restart: unless-stopped

  app:
    build:
      context: ./packages/hermes-app
      dockerfile: Dockerfile
    container_name: hermes-app
    ports:
      - "3000:80"
    environment:
      - VITE_API_URL=http://localhost:8000
    depends_on:
      - api
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    container_name: hermes-redis
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    restart: unless-stopped

  celery:
    build:
      context: ./packages/hermes-api
      dockerfile: Dockerfile
    container_name: hermes-celery
    command: celery -A app.tasks.celery_app worker --loglevel=info
    environment:
      - REDIS_URL=redis://redis:6379/0
    volumes:
      - ./packages/hermes-api/downloads:/app/downloads
    depends_on:
      - redis
    restart: unless-stopped

volumes:
  redis_data:
```


### Volume Mounts

```yaml
# Development - mount source code
volumes:
  - ./packages/hermes-api:/app
  - /app/node_modules

# Production - persistent data only
volumes:
  - ./data:/app/data
  - ./downloads:/app/downloads
```

### Environment Variables
```yaml
environment:
  - SECRET_KEY=${SECRET_KEY:-changeme}
  - DEBUG=${DEBUG:-false}
  - LOG_LEVEL=${LOG_LEVEL:-info}
```

## Security

### Non-Root Users
```dockerfile
RUN useradd -m -u 1000 appuser
RUN chown -R appuser:appuser /app
USER appuser
```

### Secrets
- Never hardcode secrets
- Use environment variables
- Use build-time arguments sparingly

## Health Checks

```dockerfile
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD curl -f http://localhost:8000/api/v1/health || exit 1
```

```yaml
services:
  api:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/health"]
      interval: 30s
      timeout: 3s
      retries: 3
```

## Development vs Production

### Development Override
```yaml
# docker-compose.override.yml
services:
  api:
    volumes:
      - ./packages/hermes-api:/app
    environment:
      - DEBUG=true
    command: uvicorn app.main:app --reload --host 0.0.0.0
```

### Production
```yaml
# docker-compose.prod.yml
services:
  api:
    build:
      target: production
    environment:
      - DEBUG=false
    restart: always
```

Usage:
```bash
# Development
docker compose up

# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
```
