mirror of
https://github.com/basnijholt/compose-farm.git
synced 2026-02-12 01:44:30 +00:00
172 lines
4.8 KiB
Markdown
172 lines
4.8 KiB
Markdown
# Compose Farm Examples
|
|
|
|
Real-world examples demonstrating compose-farm patterns for multi-host Docker deployments.
|
|
|
|
## Stacks
|
|
|
|
| Stack | Type | Demonstrates |
|
|
|---------|------|--------------|
|
|
| [traefik](traefik/) | Infrastructure | Reverse proxy, Let's Encrypt, file-provider |
|
|
| [mealie](mealie/) | Single container | Traefik labels, resource limits, environment vars |
|
|
| [uptime-kuma](uptime-kuma/) | Single container | Docker socket, user mapping, custom DNS |
|
|
| [paperless-ngx](paperless-ngx/) | Multi-container | Redis + App stack (SQLite) |
|
|
| [autokuma](autokuma/) | Multi-host | Demonstrates `all` keyword (runs on every host) |
|
|
|
|
## Key Patterns
|
|
|
|
### External Network
|
|
|
|
All stacks connect to a shared external network for inter-service communication:
|
|
|
|
```yaml
|
|
networks:
|
|
mynetwork:
|
|
external: true
|
|
```
|
|
|
|
Create it on each host with consistent settings:
|
|
|
|
```bash
|
|
compose-farm init-network --network mynetwork --subnet 172.20.0.0/16
|
|
```
|
|
|
|
### Traefik Labels (Dual Routes)
|
|
|
|
Stacks expose two routes for different access patterns:
|
|
|
|
1. **HTTPS route** (`websecure` entrypoint): For your custom domain with Let's Encrypt TLS
|
|
2. **HTTP route** (`web` entrypoint): For `.local` domains on your LAN (no TLS needed)
|
|
|
|
This pattern allows accessing stacks via:
|
|
- `https://mealie.example.com` - from anywhere, with TLS
|
|
- `http://mealie.local` - from your local network, no TLS overhead
|
|
|
|
```yaml
|
|
labels:
|
|
# HTTPS route for custom domain (e.g., mealie.example.com)
|
|
- traefik.enable=true
|
|
- traefik.http.routers.myapp.rule=Host(`myapp.${DOMAIN}`)
|
|
- traefik.http.routers.myapp.entrypoints=websecure
|
|
- traefik.http.services.myapp.loadbalancer.server.port=8080
|
|
# HTTP route for .local domain (e.g., myapp.local)
|
|
- traefik.http.routers.myapp-local.rule=Host(`myapp.local`)
|
|
- traefik.http.routers.myapp-local.entrypoints=web
|
|
```
|
|
|
|
> **Note:** `.local` domains require local DNS (e.g., Pi-hole, Technitium) to resolve to your Traefik host.
|
|
|
|
### Environment Variables
|
|
|
|
Each stack has a `.env` file for secrets and domain configuration.
|
|
Edit these files to set your domain and credentials:
|
|
|
|
```bash
|
|
# Example: set your domain
|
|
echo "DOMAIN=example.com" > mealie/.env
|
|
```
|
|
|
|
Variables like `${DOMAIN}` are substituted at runtime by Docker Compose.
|
|
|
|
### NFS Volume Mounts
|
|
|
|
All data is stored on shared NFS storage at `/mnt/data/`:
|
|
|
|
```yaml
|
|
volumes:
|
|
- /mnt/data/myapp:/app/data
|
|
```
|
|
|
|
This allows stacks to migrate between hosts without data loss.
|
|
|
|
### Multi-Host Stacks
|
|
|
|
Stacks that need to run on every host (e.g., monitoring agents):
|
|
|
|
```yaml
|
|
# In compose-farm.yaml
|
|
stacks:
|
|
autokuma: all # Runs on every configured host
|
|
```
|
|
|
|
### Multi-Container Stacks
|
|
|
|
Database-backed apps with multiple services:
|
|
|
|
```yaml
|
|
services:
|
|
redis:
|
|
image: redis:7
|
|
app:
|
|
depends_on:
|
|
- redis
|
|
```
|
|
|
|
> **NFS + PostgreSQL Warning:** PostgreSQL should NOT run on NFS storage due to
|
|
> fsync and file locking issues. Use SQLite (safe for single-writer on NFS) or
|
|
> keep PostgreSQL data on local volumes (non-migratable).
|
|
|
|
### AutoKuma Labels (Optional)
|
|
|
|
The autokuma example demonstrates compose-farm's **multi-host feature** - running the same stack on all hosts using the `all` keyword. AutoKuma itself is not part of compose-farm; it's just a good example because it needs to run on every host to monitor local Docker containers.
|
|
|
|
[AutoKuma](https://github.com/BigBoot/AutoKuma) automatically creates Uptime Kuma monitors from Docker labels:
|
|
|
|
```yaml
|
|
labels:
|
|
- kuma.myapp.http.name=My App
|
|
- kuma.myapp.http.url=https://myapp.${DOMAIN}
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
cd examples
|
|
|
|
# 1. Create the shared network on all hosts
|
|
compose-farm init-network
|
|
|
|
# 2. Start Traefik first (the reverse proxy)
|
|
compose-farm up traefik
|
|
|
|
# 3. Start other stacks
|
|
compose-farm up mealie uptime-kuma
|
|
|
|
# 4. Check status
|
|
compose-farm ps
|
|
|
|
# 5. Generate Traefik file-provider config for cross-host routing
|
|
compose-farm traefik-file --all
|
|
|
|
# 6. View logs
|
|
compose-farm logs mealie
|
|
|
|
# 7. Stop everything
|
|
compose-farm down --all
|
|
```
|
|
|
|
## Configuration
|
|
|
|
The `compose-farm.yaml` shows a multi-host setup:
|
|
|
|
- **primary** (192.168.1.10): Runs Traefik and heavy stacks
|
|
- **secondary** (192.168.1.11): Runs lighter stacks
|
|
- **autokuma**: Runs on ALL hosts to monitor local containers
|
|
|
|
When Traefik runs on `primary` and a stack runs on `secondary`, compose-farm
|
|
automatically generates file-provider config so Traefik can route to it.
|
|
|
|
## Traefik File-Provider
|
|
|
|
When stacks run on different hosts than Traefik, use `traefik-file` to generate routing config:
|
|
|
|
```bash
|
|
# Generate config for all stacks
|
|
compose-farm traefik-file --all -o traefik/dynamic.d/compose-farm.yml
|
|
|
|
# Or configure auto-generation in compose-farm.yaml:
|
|
traefik_file: /opt/stacks/traefik/dynamic.d/compose-farm.yml
|
|
traefik_stack: traefik
|
|
```
|
|
|
|
With `traefik_file` configured, compose-farm automatically regenerates the config after `up`, `down`, `restart`, and `update` commands.
|