Files
APAW/.kilo/rules/docker.md

549 lines
9.4 KiB
Markdown

# Docker & Containerization Rules
Essential rules for Docker, Docker Compose, Docker Swarm, and container technologies.
## Dockerfile Best Practices
### Layer Optimization
- Minimize layers by combining commands
- Order layers from least to most frequently changing
- Use multi-stage builds to reduce image size
- Clean up package manager caches
```dockerfile
# ✅ Good: Multi-stage build with layer optimization
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
USER node
EXPOSE 3000
CMD ["node", "server.js"]
# ❌ Bad: Single stage, many layers
FROM node:20
RUN npm install -g nodemon
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["nodemon", "server.js"]
```
### Security
- Run as non-root user
- Use specific image versions, not `latest`
- Scan images for vulnerabilities
- Don't store secrets in images
```dockerfile
# ✅ Good
FROM node:20-alpine
RUN addgroup -g 1001 appgroup && \
adduser -u 1001 -G appgroup -D appuser
WORKDIR /app
COPY --chown=appuser:appgroup . .
USER appuser
CMD ["node", "server.js"]
# ❌ Bad
FROM node:latest # Unpredictable version
# Running as root (default)
COPY . .
CMD ["node", "server.js"]
```
### Caching Strategy
```dockerfile
# ✅ Good: Dependencies cached separately
COPY package*.json ./
RUN npm ci
COPY . .
# ❌ Bad: All code copied before dependencies
COPY . .
RUN npm install
```
## Docker Compose
### Service Structure
- Use version 3.8+ for modern features
- Define services in logical order
- Use environment variables for configuration
- Set resource limits
```yaml
# ✅ Good
version: '3.8'
services:
app:
image: myapp:latest
build:
context: .
dockerfile: Dockerfile
environment:
- NODE_ENV=production
- DATABASE_URL=postgres://db:5432/app
depends_on:
db:
condition: service_healthy
networks:
- app-network
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
db:
image: postgres:15-alpine
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_DB: app
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER"]
interval: 10s
timeout: 5s
retries: 5
networks:
app-network:
driver: bridge
volumes:
postgres-data:
```
### Environment Variables
- Use `.env` files for local development
- Never commit `.env` files with secrets
- Use Docker secrets for sensitive data in Swarm
```bash
# .env (gitignored)
NODE_ENV=production
DB_PASSWORD=secure_password_here
JWT_SECRET=your_jwt_secret_here
```
```yaml
# docker-compose.yml
services:
app:
env_file:
- .env
# OR explicit for non-sensitive
environment:
- NODE_ENV=production
# Secrets for sensitive data in Swarm
secrets:
- db_password
```
### Network Patterns
```yaml
# ✅ Good: Separated networks for security
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # No external access
services:
web:
networks:
- frontend
- backend
api:
networks:
- backend
db:
networks:
- backend
```
### Volume Management
```yaml
# ✅ Good: Named volumes with labels
volumes:
postgres-data:
driver: local
labels:
- "app=myapp"
- "type=database"
services:
db:
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init-scripts:/docker-entrypoint-initdb.d:ro
```
## Docker Swarm
### Service Deployment
```yaml
# docker-compose.yml (Swarm compatible)
version: '3.8'
services:
api:
image: myapp/api:latest
deploy:
mode: replicated
replicas: 3
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
rollback_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
placement:
constraints:
- node.role == worker
preferences:
- spread: node.id
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
networks:
- app-network
secrets:
- db_password
- jwt_secret
configs:
- app_config
networks:
app-network:
driver: overlay
attachable: true
secrets:
db_password:
external: true
jwt_secret:
external: true
configs:
app_config:
external: true
```
### Stack Deployment
```bash
# Deploy stack
docker stack deploy -c docker-compose.yml mystack
# List services
docker stack services mystack
# Scale service
docker service scale mystack_api=5
# Update service
docker service update --image myapp/api:v2 mystack_api
# Rollback
docker service rollback mystack_api
```
### Health Checks
```yaml
services:
api:
# Health check in Dockerfile
healthcheck:
test: ["CMD", "node", "healthcheck.js"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# Or in compose
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
```
### Secrets Management
```bash
# Create secret
echo "my_secret_password" | docker secret create db_password -
# Create secret from file
docker secret create jwt_secret ./jwt_secret.txt
# List secrets
docker secret ls
# Use in compose
secrets:
db_password:
external: true
```
### Config Management
```bash
# Create config
docker config create app_config ./config.json
# Use in compose
configs:
app_config:
external: true
services:
api:
configs:
- app_config
```
## Container Security
### Image Security
```bash
# Scan image for vulnerabilities
docker scout vulnerabilities myapp:latest
trivy image myapp:latest
# Check image for secrets
gitleaks --image myapp:latest
```
### Runtime Security
```dockerfile
# ✅ Good: Security measures
FROM node:20-alpine
# Create non-root user
RUN addgroup -g 1001 appgroup && \
adduser -u 1001 -G appgroup -D appuser
# Set read-only filesystem
RUN chmod -R 755 /app && \
chown -R appuser:appgroup /app
WORKDIR /app
COPY --chown=appuser:appgroup . .
# Drop all capabilities
USER appuser
VOLUME ["/tmp"]
CMD ["node", "server.js"]
```
### Network Security
```yaml
# ✅ Good: Limited network access
services:
api:
networks:
- backend
# No ports exposed to host
db:
networks:
- backend
# Internal network only
networks:
backend:
internal: true # No internet access
```
### Resource Limits
```yaml
services:
api:
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
```
## Common Patterns
### Development Setup
```yaml
# docker-compose.dev.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
ports:
- "3000:3000"
command: npm run dev
```
### Production Setup
```yaml
# docker-compose.prod.yml
version: '3.8'
services:
app:
image: myapp:${VERSION}
environment:
- NODE_ENV=production
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
healthcheck:
test: ["CMD", "node", "healthcheck.js"]
interval: 30s
timeout: 10s
retries: 3
```
### Multi-Environment
```bash
# Override files
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
```
### Logging
```yaml
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "app,environment"
```
## CI/CD Integration
### Build Pipeline
```yaml
# .github/workflows/docker.yml
name: Docker Build
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Scan image
run: trivy image myapp:${{ github.sha }}
- name: Push to registry
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USER }} --password-stdin
docker push myapp:${{ github.sha }}
```
## Troubleshooting
### Common Commands
```bash
# View logs
docker-compose logs -f app
# Execute in container
docker-compose exec app sh
# Check health
docker inspect --format='{{.State.Health.Status}}' <container>
# View resource usage
docker stats
# Remove unused resources
docker system prune -a
# Debug network
docker network inspect app-network
# Swarm diagnostics
docker node ls
docker service ps mystack_api
```
## Prohibitions
- DO NOT run containers as root
- DO NOT use `latest` tag in production
- DO NOT expose unnecessary ports
- DO NOT store secrets in images
- DO NOT use privileged mode unnecessarily
- DO NOT mount host directories without restrictions
- DO NOT skip health checks in production
- DO NOT ignore vulnerability scans