*Last updated: November 2026 — UI products change fast; verify RAM with docker stats on your box.*
For: You already know Compose YAML and need to pick how to operate 1–10 containers on a cheap VPS (≈2 GB RAM).
Do not use this page when: You need Kubernetes, multi-node clusters, or a managed PaaS. Those are different tradeoffs.
You want…
Pick
Lowest RAM + full control + copy-paste guides like this site
**Plain Compose**
Web UI to start/stop stacks, view logs, manage volumes — still write your own YAML
**Portainer CE**
Git-push / one-click app templates, built-in domains + TLS, less YAML day-to-day
**Coolify** (needs more RAM)
Numbers are typical idle + UI overhead on Ubuntu 22.04/24.04 with Docker Engine. Apps are extra.
Stack
Idle RAM (approx.)
Disk for the tool
Fits a 2 GB VPS with 1–2 light apps?
Fits a 2 GB VPS with Immich-class apps?
Plain Compose (CLI only)
~0 MB beyond Docker daemon (~150–300 MB)
Compose files only
Yes
Only if apps fit; no UI tax
Portainer CE (container)
+50–150 MB
Image ~200–400 MB
Yes
Tight — measure before Immich
Coolify (full install)
+500 MB–1.5 GB+ (varies by version / services)
Multi-GB after images
Risky for heavy apps
Usually **no** — use ≥4 GB
Rule of thumb: On 2 GB, prefer plain Compose or Portainer. Treat Coolify as a 4 GB+ control plane unless you measured a lean install.
Capability
Plain Compose
Portainer CE
Coolify
Edit `docker-compose.yml` by hand
Native
Yes (stack editor)
Possible; product pushes templates / UI deploy
One-command deploy from git
`git pull && compose up -d`
Manual / webhook DIY
Built-in git deploy flows
Built-in HTTPS for apps
You add Caddy/Traefik
You add proxy yourself
Domain + cert flows built in
Web logs / console
`docker logs` / `exec`
Yes
Yes
Multi-server from one UI
No
Business / agent setups
Designed for servers + apps
Lock-in / recovery if UI dies
None — files on disk
Stacks still in Docker; UI is optional
App metadata lives in Coolify — keep exports / git source of truth
Attack surface
SSH + published ports
+ Portainer port (must not expose `:9000`/`9443` to the world without auth + TLS)
+ Coolify dashboard (same rule)
Learning cost
Compose + reverse proxy
Compose + UI
Product concepts + resources
Symptom
Likely with
Cause
Fix direction
OOM killer hits random containers
Coolify on 2 GB; Immich + any UI
Control plane + app exceed RAM
Drop UI tool, or upgrade to 4 GB; disable Immich ML
“Disk full” after few deploys
Coolify / Portainer image churn
Old images & build cache
`docker system prune` carefully; pin tags; set retention
Forgot how the stack was created
Coolify UI-only deploys
No compose file in git
Always keep compose (or export) in git
Portainer unreachable after reboot
Portainer
No `restart: unless-stopped` or wrong volume
Fix Portainer compose; data in `portainer_data` volume
Accidental public admin UI
Portainer / Coolify
Bound `0.0.0.0:9443` without firewall
Bind to Tailscale/VPN IP or localhost + SSH tunnel; ufw default deny
Guides from this site don’t match UI clicks
Coolify
Abstraction over Compose
Use plain Compose guides as source of truth, or paste same YAML into a Portainer stack
Use plain Compose if:
You are fine with SSH
You want this site’s Caddy + app pattern (one compose project or a shared Caddy)
You care about reproducible git repos more than dashboards
Minimal ops loop:
cd ~/app && git pull
docker compose pull
docker compose up -d
docker compose ps
docker compose logs -f --tail=100
Typical install pattern (illustrative — pin the tag you trust):
services:
portainer:
image: portainer/portainer-ce:2.21.4
container_name: portainer
restart: unless-stopped
security_opt:
- no-new-privileges:true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
ports:
- "127.0.0.1:9443:9443" # SSH tunnel or VPN only — do not publish to 0.0.0.0
volumes:
portainer_data:
Access via ssh -L 9443:127.0.0.1:9443 user@vps then https://localhost:9443.
Do not mount the Docker socket and expose Portainer to the public internet without strict controls — socket access ≈ root on the host.
Choose Coolify when:
You deploy many apps and want domains/TLS without maintaining Caddyfiles by hand
You have ≥4 GB RAM (or a separate small VPS for Coolify and workers elsewhere)
Git-based deploys matter more than matching third-party compose tutorials line-for-line
Avoid Coolify as the only brain on a 2 GB box that also runs Immich, Mattermost, or multiple databases.
Constraint
Compose
Portainer
Coolify
≤2 GB RAM, 1–3 apps
**Best**
OK
Avoid / measure
≥4 GB RAM, many apps + domains
OK
OK
**Best**
Must match public compose tutorials exactly
**Best**
OK (paste stack)
Weaker
Non-SSH teammates need buttons
Weak
**Best**
Strong
Disaster recovery = “git clone + compose up”
**Best**
Good if stacks exported
Need export discipline
Lowest monthly VPS cost
**Best**
Good
Costs more RAM → bigger VPS
free -h shows comfortable free/cache headroom under load
docker stats --no-stream during peak (backup, OCR, sync)
Admin UIs bound to localhost/VPN only
Every production stack exists as files in git (even if a UI started it)
Backups target volumes/bind mounts, not “the UI remembers”
Common Compose errors (ports, permissions, OOM, volumes)
Caddy certificate failures (DNS, ufw, IPv6)
Caddy vs Traefik for multi-app on one VPS