Docker Stacks Reference¶
All services run via Docker Compose. Stacks are organized by function and live in ~/stacks/ on the relevant host.
Stack Organization¶
~/stacks/
├── core/
│ ├── portainer.yml
│ ├── npm.yml
│ ├── pihole.yml
│ └── uptime-kuma.yml
├── monitoring/
│ ├── grafana.yml
│ ├── prometheus.yml
│ ├── node-exporter.yml
│ └── cadvisor.yml
└── apps/
└── (add per service)
Core Stack¶
Portainer¶
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
ports:
- "9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
volumes:
portainer_data:
Nginx Proxy Manager¶
services:
npm:
image: jc21/nginx-proxy-manager:latest
container_name: nginx-proxy-mgr
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "81:81"
volumes:
- npm_data:/data
- npm_letsencrypt:/etc/letsencrypt
volumes:
npm_data:
npm_letsencrypt:
Monitoring Stack¶
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=30d'
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: unless-stopped
network_mode: host
pid: host
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
volumes:
prometheus_data:
grafana_data:
Deployment Notes¶
- All stacks use
restart: unless-stopped— they survive reboots. - Secrets go in
.envfiles per stack directory — never hardcoded in compose files. - Check port conflicts before deploying:
ss -tulnp | grep PORTNUMBER - After editing a compose file:
docker compose -f <file>.yml up -d --force-recreate