Docker Compose describes a multi-container stack in one file and runs it with one command. This is the deploy how-to; first install Docker if you haven't. For an AI-agent-specific stack (agent + vector DB + Redis), see docker-compose for AI agents.
1. A stack: app + database + reverse proxy
# /opt/stack/docker-compose.yml
services:
app:
image: your/app:latest
restart: unless-stopped
env_file: [.env]
depends_on: [db]
# no ports: — reached only through the proxy below
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes: ["pg:/var/lib/postgresql/data"] # internal only
caddy: # HTTPS automatically
image: caddy:2
restart: unless-stopped
ports: ["80:80", "443:443"] # the only public entrypoint
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
volumes: { pg: {}, caddy_data: {} }
Secrets live in .env, never the compose file:
# /opt/stack/.env (chmod 600, git-ignored)
DB_PASSWORD=a-long-random-string
A minimal Caddyfile proxies your domain to the app and fetches HTTPS on its own:
app.yourdomain.com {
reverse_proxy app:8080
}
2. Bring it up
cd /opt/stack
docker compose up -d
docker compose ps
docker compose logs -f app
restart: unless-stopped on every service + Docker enabled on boot = the stack returns after a reboot on its own.
3. Everyday commands
docker compose pull && docker compose up -d # update images
docker compose down # stop the stack
docker compose restart app # restart one service
The part people get wrong: exposed ports
Docker publishes ports through iptables, so a container with ports: ["5432:5432"] is reachable from the internet even behind a UFW firewall you thought was closed. Publish only the public entrypoint (the proxy on 80/443); keep databases and caches on the compose network or bound to 127.0.0.1. Anything serving web traffic needs a dedicated-IP plan; pair with a UFW firewall.
For a whole stack behind one IP, see self-host multiple services. Root in about a minute, NVMe, no KYC, pay in crypto.
Comments
No comments yet. Be the first.