feat: add Docker skills and rules
- Add docker-compose skill with patterns (575 lines) - Add docker-swarm skill with examples (756 lines) - Add docker-security skill (684 lines) - Add docker-monitoring skill (755 lines) - Add docker.md rules (548 lines) Total: 3318 lines of Docker documentation
This commit is contained in:
549
.kilo/rules/docker.md
Normal file
549
.kilo/rules/docker.md
Normal file
@@ -0,0 +1,549 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user