Files
homelab-optimized/DOCKER_COMPOSE_GUIDE.md
Gitea Mirror Bot ca723d77b9
Some checks failed
Documentation / Deploy to GitHub Pages (push) Has been cancelled
Documentation / Build Docusaurus (push) Has been cancelled
Sanitized mirror from private repository - 2026-04-20 00:50:49 UTC
2026-04-20 00:50:49 +00:00

419 lines
8.0 KiB
Markdown

# 🐳 Docker Compose Guide
*Comprehensive guide for Docker Compose best practices in the homelab*
## Overview
This guide covers Docker Compose best practices, patterns, and standards used throughout the homelab infrastructure for consistent, maintainable, and secure container deployments.
## File Structure Standards
### Naming Conventions
- **Service files**: `service-name.yml` or `service-name.yaml`
- **Stack names**: Use descriptive, kebab-case names
- **Container names**: Include service and host identifier
- **Volume names**: Prefix with service name for clarity
### Directory Organization
```
host-name/
├── service-name/
│ ├── docker-compose.yml
│ ├── .env
│ ├── config/
│ └── data/
└── service-name.yml (simple services)
```
## Compose File Best Practices
### Version and Services
```yaml
version: '3.8' # Use stable version
services:
service-name:
image: official/image:tag # Always pin versions
container_name: service-name-hostname
restart: unless-stopped # Standard restart policy
```
### Environment Variables
```yaml
# Prefer environment files
env_file:
- .env
# Or explicit environment variables
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
```
### Volume Management
```yaml
volumes:
# Named volumes for data persistence
- service-data:/app/data
# Bind mounts for configuration
- ./config:/app/config:ro
# Host paths for media/large data
- /mnt/storage/media:/media:ro
volumes:
service-data:
driver: local
```
### Network Configuration
```yaml
networks:
default:
name: service-network
# Or use existing networks
proxy:
external: true
name: nginx-proxy-manager_default
```
## Security Best Practices
### User and Permissions
```yaml
services:
app:
user: "1000:1000" # Run as non-root user
# Or use environment variables
environment:
- PUID=1000
- PGID=1000
```
### Resource Limits
```yaml
services:
app:
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
reservations:
memory: 256M
```
### Security Options
```yaml
services:
app:
security_opt:
- no-new-privileges:true
# Read-only root filesystem when possible
read_only: true
tmpfs:
- /tmp
- /var/tmp
```
## Common Patterns
### Reverse Proxy Integration
```yaml
services:
app:
labels:
# Nginx Proxy Manager
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`app.domain.com`)"
# Or Traefik labels
- "traefik.http.services.app.loadbalancer.server.port=8080"
```
### Health Checks
```yaml
services:
app:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
```
### Dependency Management
```yaml
services:
app:
depends_on:
database:
condition: service_healthy
database:
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"]
```
## GitOps Integration
### Portainer Stack Deployment
- **Repository**: `https://git.vish.gg/Vish/homelab.git`
- **Branch**: `main`
- **Compose file path**: `host-name/service-name.yml`
- **Environment variables**: Managed in Portainer UI
### File Path Standards
```
Atlantis/service-name.yml # Primary NAS services
Calypso/service-name.yml # Secondary NAS services
homelab_vm/service-name.yml # VM-based services
concord_nuc/service-name.yml # NUC services
raspberry-pi-5-vish/service-name.yml # Pi services
```
### Environment File Management
```bash
# .env file structure
PUID=1000
PGID=1000
TZ=America/New_York
SERVICE_PORT=8080
DATA_PATH=/mnt/storage/service-name
```
## Service Categories
### Media Services
```yaml
services:
plex:
image: plexinc/pms-docker:latest
environment:
- PLEX_CLAIM=claim-token
- PLEX_UID=1000
- PLEX_GID=1000
volumes:
- plex-config:/config
- /mnt/media:/media:ro
ports:
- "32400:32400"
```
### Database Services
```yaml
services:
postgres:
image: postgres:15-alpine
environment:
- POSTGRES_DB=appdb
- POSTGRES_USER=appuser
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
secrets:
- db_password
volumes:
- postgres-data:/var/lib/postgresql/data
secrets:
db_password:
"REDACTED_PASSWORD" ./secrets/db_password.txt
```
### Web Applications
```yaml
services:
webapp:
image: nginx:alpine
volumes:
- ./html:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/nginx.conf:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.webapp.rule=Host(`app.local`)"
```
## Monitoring Integration
### Prometheus Metrics
```yaml
services:
app:
labels:
- "prometheus.io/scrape=true"
- "prometheus.io/port=9090"
- "prometheus.io/path=/metrics"
```
### Logging Configuration
```yaml
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# Or use centralized logging
logging:
driver: "loki"
options:
loki-url: "http://loki:3100/loki/api/v1/push"
```
## Backup Considerations
### Volume Backup Strategy
```yaml
# Backup-friendly volume structure
volumes:
app-config:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/backup/app/config
app-data:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/backup/app/data
```
### Database Backup
```yaml
services:
db-backup:
image: postgres:15-alpine
command: |
sh -c "
while true; do
pg_dump -h postgres -U $$POSTGRES_USER $$POSTGRES_DB > /backup/backup_$$(date +%Y%m%d_%H%M%S).sql
sleep 86400
done"
volumes:
- ./backups:/backup
depends_on:
- postgres
```
## Troubleshooting
### Common Issues
#### Port Conflicts
```bash
# Check port usage
netstat -tulpn | grep :8080
docker ps --format "table {{.Names}}\t{{.Ports}}"
```
#### Volume Permissions
```bash
# Fix volume permissions
sudo chown -R 1000:1000 /path/to/volume
sudo chmod -R 755 /path/to/volume
```
#### Network Issues
```bash
# Inspect networks
docker network ls
docker network inspect network-name
# Test connectivity
docker exec container-name ping other-container
```
### Debugging Commands
```bash
# View logs
docker-compose logs -f service-name
# Execute commands in container
docker-compose exec service-name bash
# Validate compose file
docker-compose config
# Check service status
docker-compose ps
```
## Performance Optimization
### Resource Management
```yaml
services:
app:
deploy:
resources:
limits:
memory: 1G
cpus: '1.0'
# Use init system for proper signal handling
init: true
# Optimize for specific workloads
sysctls:
- net.core.somaxconn=1024
```
### Storage Optimization
```yaml
# Use tmpfs for temporary data
tmpfs:
- /tmp:size=100M,noexec,nosuid,nodev
# Optimize volume drivers
volumes:
fast-data:
driver: local
driver_opts:
type: tmpfs
device: tmpfs
o: size=1G
```
## Validation and Testing
### Pre-deployment Checks
```bash
# Validate syntax
docker-compose config
# Check for security issues
docker-compose config | docker run --rm -i hadolint/hadolint
# Test deployment
docker-compose up --dry-run
```
### Health Monitoring
```yaml
services:
app:
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
```
## Related Documentation
- [GitOps Deployment Guide](docs/GITOPS_DEPLOYMENT_GUIDE.md) - GitOps workflow and deployment procedures
- [Security Guidelines](docs/security/SECURITY_GUIDELINES.md) - Security best practices for containers
- [Monitoring Architecture](docs/MONITORING_ARCHITECTURE.md) - Monitoring and observability setup
---
**Status**: ✅ Docker Compose standards implemented across all homelab services