Best Practices¶
Tips, limitations, and recommendations for using Compose Farm effectively.
Limitations¶
No Cross-Host Networking¶
Compose Farm moves containers between hosts but does not provide cross-host networking. Docker's internal DNS and networks don't span hosts.
What breaks when you move a stack:
| Feature | Works? | Why |
|---|---|---|
http://redis:6379 |
No | Docker DNS doesn't cross hosts |
| Docker network names | No | Networks are per-host |
DATABASE_URL=postgres://db:5432 |
No | Container name won't resolve |
| Host IP addresses | Yes | Use 192.168.1.10:5432 |
What Compose Farm Doesn't Do¶
- No overlay networking (use Swarm/Kubernetes)
- No service discovery across hosts
- No automatic dependency tracking between compose files
- No health checks or restart policies beyond Docker's
- No secrets management beyond Docker's
Stack Organization¶
Keep Dependencies Together¶
If services talk to each other, keep them in the same compose file on the same host:
# /opt/compose/myapp/docker-compose.yml
services:
app:
image: myapp
depends_on:
- db
- redis
db:
image: postgres
redis:
image: redis
Separate Standalone Stacks¶
Stacks whose services don't talk to other containers can be anywhere:
stacks:
# These can run on any host
plex: nuc
jellyfin: hp
homeassistant: nas
# These should stay together
myapp: nuc # includes app + db + redis
Cross-Host Communication¶
If services MUST communicate across hosts, publish ports:
Multi-Host Stacks¶
When to Use all¶
Use all for stacks that need local access to each host:
stacks:
# Need Docker socket
dozzle: all # Log viewer
portainer-agent: all # Portainer agents
autokuma: all # Auto-creates monitors
# Need host metrics
node-exporter: all # Prometheus metrics
promtail: all # Log shipping
Host-Specific Lists¶
For stacks on specific hosts only:
stacks:
# Only on compute nodes
gitlab-runner: [nuc, hp]
# Only on storage nodes
minio: [nas-1, nas-2]
Migration Safety¶
Pre-flight Checks¶
Before migrating, Compose Farm verifies: - Compose file is accessible on new host - Required mounts exist on new host - Required networks exist on new host
Data Considerations¶
Compose Farm doesn't move data. Ensure:
- Shared storage: Data volumes on NFS/shared storage
- External databases: Data in external DB, not container
- Backup first: Always backup before migration
Safe Migration Pattern¶
# 1. Preview changes
cf apply --dry-run
# 2. Verify target host can run the stack
cf check myservice
# 3. Apply changes
cf apply
State Management¶
When to Refresh¶
Run cf refresh after:
- Manual docker compose commands
- Container restarts
- Host reboots
- Any changes outside Compose Farm
State Conflicts¶
If state doesn't match reality:
# See what's actually running
cf refresh --dry-run
# Sync state
cf refresh
# Then apply config
cf apply
Shared Storage¶
NFS Best Practices¶
# Mount options for Docker compatibility
nas:/compose /opt/compose nfs rw,hard,intr,rsize=8192,wsize=8192 0 0
Directory Ownership¶
Ensure consistent UID/GID across hosts:
Config vs Data¶
Keep config and data separate:
/opt/compose/ # Shared: compose files + config
├── plex/
│ ├── docker-compose.yml
│ └── config/ # Small config files OK
/mnt/data/ # Shared: large media files
├── movies/
├── tv/
└── music/
/opt/appdata/ # Local: per-host app data
├── plex/
└── sonarr/
Performance¶
Parallel Operations¶
Compose Farm runs operations in parallel. For large deployments:
# Good: parallel by default
cf up --all
# Avoid: sequential updates when possible
for svc in plex sonarr radarr; do
cf update $svc
done
SSH Connection Reuse¶
SSH connections are reused within a command. For many operations:
# One command, one connection per host
cf update --all
# Multiple commands, multiple connections (slower)
cf update plex && cf update sonarr && cf update radarr
Traefik Setup¶
Stack Placement¶
Put Traefik on a reliable host:
Same-Host Stacks¶
Stacks on the same host as Traefik use Docker provider:
traefik_stack: traefik
stacks:
traefik: nuc
portainer: nuc # Docker provider handles this
plex: hp # File provider handles this
Middleware in Separate File¶
Define middlewares outside Compose Farm's generated file:
# /opt/traefik/dynamic.d/middlewares.yml
http:
middlewares:
redirect-https:
redirectScheme:
scheme: https
Backup Strategy¶
What to Backup¶
| Item | Location | Method |
|---|---|---|
| Compose Farm config | ~/.config/compose-farm/ |
Git or copy |
| Compose files | /opt/compose/ |
Git |
| State file | ~/.config/compose-farm/state.yaml |
Optional (can refresh) |
| App data | /opt/appdata/ |
Backup solution |
Disaster Recovery¶
# Restore config
cp backup/compose-farm.yaml ~/.config/compose-farm/
# Refresh state from running containers
cf refresh
# Or start fresh
cf apply
Troubleshooting¶
Common Issues¶
Stack won't start:
Migration fails:
State out of sync:
SSH issues:
Security Considerations¶
SSH Keys¶
- Use dedicated SSH key for Compose Farm
- Limit key to specific hosts if possible
- Don't store keys in Docker images
Network Exposure¶
- Published ports are accessible from network
- Use firewalls for sensitive services
- Consider VPN for cross-host communication
Secrets¶
- Don't commit
.envfiles with secrets - Use Docker secrets or external secret management
- Avoid secrets in compose file labels
Comparison: When to Use Alternatives¶
| Scenario | Solution |
|---|---|
| 2-10 hosts, static stacks | Compose Farm |
| Cross-host container networking | Docker Swarm |
| Auto-scaling, self-healing | Kubernetes |
| Infrastructure as code | Ansible + Compose Farm |
| High availability requirements | Kubernetes or Swarm |