510 lines
9.5 KiB
Markdown
510 lines
9.5 KiB
Markdown
# 🐳 Docker Compose Guide
|
|
|
|
*Comprehensive guide for Docker Compose usage in the homelab environment*
|
|
|
|
## 📋 Overview
|
|
|
|
This guide covers Docker Compose best practices, patterns, and configurations used throughout the homelab infrastructure for consistent and maintainable container deployments.
|
|
|
|
## 🏗️ Standard Compose Structure
|
|
|
|
### Basic Template
|
|
```yaml
|
|
version: '3.8'
|
|
|
|
services:
|
|
service-name:
|
|
image: organization/image:latest
|
|
container_name: service-name
|
|
restart: unless-stopped
|
|
|
|
environment:
|
|
- PUID=1000
|
|
- PGID=1000
|
|
- TZ=America/Los_Angeles
|
|
|
|
volumes:
|
|
- ./config:/config
|
|
- /data/service:/data
|
|
|
|
ports:
|
|
- "8080:8080"
|
|
|
|
networks:
|
|
- homelab
|
|
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.service.rule=Host(`service.vish.gg`)"
|
|
- "com.centurylinklabs.watchtower.enable=true"
|
|
|
|
networks:
|
|
homelab:
|
|
external: true
|
|
```
|
|
|
|
## 🔧 Configuration Patterns
|
|
|
|
### Environment Variables
|
|
```yaml
|
|
environment:
|
|
# User/Group IDs (required for file permissions)
|
|
- PUID=1000
|
|
- PGID=1000
|
|
|
|
# Timezone (consistent across all services)
|
|
- TZ=America/Los_Angeles
|
|
|
|
# Service-specific configuration
|
|
- DATABASE_URL=postgresql://user:REDACTED_PASSWORD@db:5432/dbname
|
|
- REDIS_URL=redis://redis:6379
|
|
|
|
# Security settings
|
|
- SECURE_SSL_REDIRECT=true
|
|
- SESSION_COOKIE_SECURE=true
|
|
```
|
|
|
|
### Volume Mapping
|
|
```yaml
|
|
volumes:
|
|
# Configuration (relative to compose file)
|
|
- ./config:/config
|
|
- ./data:/data
|
|
|
|
# Shared storage (absolute paths)
|
|
- /mnt/storage/media:/media:ro
|
|
- /mnt/storage/downloads:/downloads
|
|
|
|
# System integration
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
- /etc/localtime:/etc/localtime:ro
|
|
```
|
|
|
|
### Network Configuration
|
|
```yaml
|
|
networks:
|
|
# External network (created separately)
|
|
homelab:
|
|
external: true
|
|
|
|
# Internal network (service-specific)
|
|
internal:
|
|
driver: bridge
|
|
internal: true
|
|
```
|
|
|
|
## 🏷️ Labeling Standards
|
|
|
|
### Traefik Integration
|
|
```yaml
|
|
labels:
|
|
# Enable Traefik
|
|
- "traefik.enable=true"
|
|
|
|
# HTTP Router
|
|
- "traefik.http.routers.service.rule=Host(`service.vish.gg`)"
|
|
- "traefik.http.routers.service.entrypoints=websecure"
|
|
- "traefik.http.routers.service.tls.certresolver=letsencrypt"
|
|
|
|
# Service configuration
|
|
- "traefik.http.services.service.loadbalancer.server.port=8080"
|
|
|
|
# Middleware
|
|
- "traefik.http.routers.service.middlewares=auth@file"
|
|
```
|
|
|
|
### Watchtower Configuration
|
|
```yaml
|
|
labels:
|
|
# Enable automatic updates
|
|
- "com.centurylinklabs.watchtower.enable=true"
|
|
|
|
# Update schedule (optional)
|
|
- "com.centurylinklabs.watchtower.schedule=0 0 4 * * *"
|
|
|
|
# Notification settings
|
|
- "com.centurylinklabs.watchtower.notification-url=ntfy://ntfy.vish.gg/watchtower"
|
|
```
|
|
|
|
### Monitoring Labels
|
|
```yaml
|
|
labels:
|
|
# Prometheus monitoring
|
|
- "prometheus.io/scrape=true"
|
|
- "prometheus.io/port=9090"
|
|
- "prometheus.io/path=/metrics"
|
|
|
|
# Service metadata
|
|
- "homelab.service.category=media"
|
|
- "homelab.service.tier=production"
|
|
- "homelab.service.owner=vish"
|
|
```
|
|
|
|
## 🔐 Security Best Practices
|
|
|
|
### User and Permissions
|
|
```yaml
|
|
# Always specify user/group IDs
|
|
environment:
|
|
- PUID=1000
|
|
- PGID=1000
|
|
|
|
# Or use user directive
|
|
user: "1000:1000"
|
|
|
|
# For root-required services, minimize privileges
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
```
|
|
|
|
### Secrets Management
|
|
```yaml
|
|
# Use Docker secrets
|
|
secrets:
|
|
db_password:
|
|
"REDACTED_PASSWORD" ./secrets/db_password.txt
|
|
|
|
services:
|
|
app:
|
|
secrets:
|
|
- db_password
|
|
environment:
|
|
- DB_PASSWORD_FILE=/run/secrets/db_password
|
|
```
|
|
|
|
### Network Security
|
|
```yaml
|
|
# Avoid host networking
|
|
network_mode: host # ❌ Avoid this
|
|
|
|
# Use custom networks instead
|
|
networks:
|
|
- internal # ✅ Preferred approach
|
|
|
|
# Limit exposed ports
|
|
ports:
|
|
- "127.0.0.1:8080:8080" # ✅ Bind to localhost only
|
|
```
|
|
|
|
## 📊 Resource Management
|
|
|
|
### Resource Limits
|
|
```yaml
|
|
services:
|
|
service-name:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '2.0'
|
|
memory: 2G
|
|
reservations:
|
|
cpus: '0.5'
|
|
memory: 512M
|
|
```
|
|
|
|
### Health Checks
|
|
```yaml
|
|
services:
|
|
service-name:
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
```
|
|
|
|
### Restart Policies
|
|
```yaml
|
|
# Standard restart policy
|
|
restart: unless-stopped
|
|
|
|
# Alternative policies
|
|
restart: "no" # Never restart
|
|
restart: always # Always restart
|
|
restart: on-failure # Restart on failure only
|
|
```
|
|
|
|
## 🗂️ Multi-Service Patterns
|
|
|
|
### Database Integration
|
|
```yaml
|
|
version: '3.8'
|
|
|
|
services:
|
|
app:
|
|
image: myapp:latest
|
|
depends_on:
|
|
- database
|
|
environment:
|
|
- DATABASE_URL=postgresql://user:REDACTED_PASSWORD@database:5432/myapp
|
|
networks:
|
|
- internal
|
|
|
|
database:
|
|
image: postgres:15
|
|
environment:
|
|
- POSTGRES_DB=myapp
|
|
- POSTGRES_USER=user
|
|
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
|
|
volumes:
|
|
- db_data:/var/lib/postgresql/data
|
|
networks:
|
|
- internal
|
|
secrets:
|
|
- db_password
|
|
|
|
volumes:
|
|
db_data:
|
|
|
|
networks:
|
|
internal:
|
|
driver: bridge
|
|
|
|
secrets:
|
|
db_password:
|
|
"REDACTED_PASSWORD" ./secrets/db_password.txt
|
|
```
|
|
|
|
### Reverse Proxy Integration
|
|
```yaml
|
|
services:
|
|
app:
|
|
image: myapp:latest
|
|
networks:
|
|
- homelab
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.app.rule=Host(`app.vish.gg`)"
|
|
- "traefik.http.routers.app.entrypoints=websecure"
|
|
- "traefik.http.routers.app.tls.certresolver=letsencrypt"
|
|
|
|
networks:
|
|
homelab:
|
|
external: true
|
|
```
|
|
|
|
## 🔄 Development vs Production
|
|
|
|
### Development Override
|
|
```yaml
|
|
# docker-compose.override.yml
|
|
version: '3.8'
|
|
|
|
services:
|
|
app:
|
|
build: .
|
|
volumes:
|
|
- .:/app
|
|
environment:
|
|
- DEBUG=true
|
|
ports:
|
|
- "8080:8080"
|
|
```
|
|
|
|
### Production Configuration
|
|
```yaml
|
|
# docker-compose.prod.yml
|
|
version: '3.8'
|
|
|
|
services:
|
|
app:
|
|
image: myapp:v1.2.3
|
|
restart: unless-stopped
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 1G
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
```
|
|
|
|
## 📝 Documentation Standards
|
|
|
|
### Service Documentation
|
|
```yaml
|
|
# At the top of each compose file
|
|
# Service: Application Name
|
|
# Purpose: Brief description of what this service does
|
|
# Access: How to access the service (URL, port, etc.)
|
|
# Dependencies: Other services this depends on
|
|
# Volumes: Important volume mappings
|
|
# Configuration: Key environment variables
|
|
```
|
|
|
|
### Inline Comments
|
|
```yaml
|
|
services:
|
|
app:
|
|
image: myapp:latest
|
|
container_name: myapp
|
|
restart: unless-stopped
|
|
|
|
environment:
|
|
# Required: User/group for file permissions
|
|
- PUID=1000
|
|
- PGID=1000
|
|
|
|
# Optional: Custom configuration
|
|
- CUSTOM_SETTING=value
|
|
|
|
volumes:
|
|
# Configuration directory
|
|
- ./config:/config
|
|
|
|
# Data storage (persistent)
|
|
- app_data:/data
|
|
|
|
ports:
|
|
# Web interface
|
|
- "8080:8080"
|
|
```
|
|
|
|
## 🚀 Deployment Strategies
|
|
|
|
### GitOps Deployment
|
|
```yaml
|
|
# Compose files are deployed via Portainer GitOps
|
|
# Repository: https://git.vish.gg/Vish/homelab.git
|
|
# Branch: main
|
|
# Automatic deployment on git push
|
|
```
|
|
|
|
### Manual Deployment
|
|
```bash
|
|
# Deploy stack
|
|
docker-compose up -d
|
|
|
|
# Update stack
|
|
docker-compose pull
|
|
docker-compose up -d
|
|
|
|
# Remove stack
|
|
docker-compose down
|
|
```
|
|
|
|
### Stack Management
|
|
```bash
|
|
# View running services
|
|
docker-compose ps
|
|
|
|
# View logs
|
|
docker-compose logs -f service-name
|
|
|
|
# Execute commands
|
|
docker-compose exec service-name bash
|
|
|
|
# Scale services
|
|
docker-compose up -d --scale worker=3
|
|
```
|
|
|
|
## 🔍 Troubleshooting
|
|
|
|
### Common Issues
|
|
```bash
|
|
# Check service status
|
|
docker-compose ps
|
|
|
|
# View logs
|
|
docker-compose logs service-name
|
|
|
|
# Validate configuration
|
|
docker-compose config
|
|
|
|
# Check resource usage
|
|
docker stats
|
|
```
|
|
|
|
### Debug Commands
|
|
```bash
|
|
# Inspect container
|
|
docker inspect container-name
|
|
|
|
# Check networks
|
|
docker network ls
|
|
docker network inspect network-name
|
|
|
|
# Volume inspection
|
|
docker volume ls
|
|
docker volume inspect volume-name
|
|
```
|
|
|
|
## 📊 Monitoring Integration
|
|
|
|
### Prometheus Metrics
|
|
```yaml
|
|
services:
|
|
app:
|
|
labels:
|
|
- "prometheus.io/scrape=true"
|
|
- "prometheus.io/port=9090"
|
|
- "prometheus.io/path=/metrics"
|
|
```
|
|
|
|
### Log Management
|
|
```yaml
|
|
services:
|
|
app:
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
labels: "service,environment"
|
|
```
|
|
|
|
## 🔧 Advanced Patterns
|
|
|
|
### Init Containers
|
|
```yaml
|
|
services:
|
|
app:
|
|
image: myapp:latest
|
|
depends_on:
|
|
init:
|
|
condition: service_completed_successfully
|
|
|
|
init:
|
|
image: busybox
|
|
command: ["sh", "-c", "echo 'Initialization complete'"]
|
|
```
|
|
|
|
### Sidecar Containers
|
|
```yaml
|
|
services:
|
|
app:
|
|
image: myapp:latest
|
|
volumes:
|
|
- shared_data:/data
|
|
|
|
sidecar:
|
|
image: nginx:alpine
|
|
volumes:
|
|
- shared_data:/usr/share/nginx/html:ro
|
|
ports:
|
|
- "80:80"
|
|
|
|
volumes:
|
|
shared_data:
|
|
```
|
|
|
|
## 📚 Additional Resources
|
|
|
|
### External Documentation
|
|
- [Docker Compose Reference](https://docs.docker.com/compose/compose-file/)
|
|
- [Docker Best Practices](https://docs.docker.com/develop/best-practices/)
|
|
- [Traefik Docker Integration](https://doc.traefik.io/traefik/providers/docker/)
|
|
|
|
### Internal Resources
|
|
- [Development Guide](DEVELOPMENT.md)
|
|
- [GitOps Deployment Guide](../admin/gitops-deployment-guide.md)
|
|
- [Security Guidelines](../security/SECURITY_GUIDELINES.md)
|
|
|
|
---
|
|
|
|
**Last Updated**: February 24, 2026
|
|
**Docker Compose Version**: 3.8+ recommended
|
|
**Status**: ✅ **PRODUCTION** - Used across all homelab services |