All posts
dockerdocker-composeprocess-managerself-hostingdevopscontainers

Docker Compose vs a Process Manager for Self-Hosting

Docker Compose and process managers overlap more than people admit. Here's an honest comparison of isolation, resource cost, deploys, and debugging — and when to combine them.

Oxmgr Team ·

Docker Compose vs a Process Manager for Self-Hosting

Once you have more than one process to run — an app, a worker, maybe a database — you need something to orchestrate them. On a single server, the two common answers are Docker Compose and a process manager. They overlap enough that the choice is genuinely unclear, so let’s compare them on the things that actually matter.

What each one is really doing

Docker Compose describes a set of containers — isolated filesystems and process namespaces — and the network between them. Its restart policies keep containers alive; its depends_on orders startup.

A process manager describes a set of processes running directly on the host. It keeps them alive, restarts on crash, runs health checks, and manages logs — but they share the host’s filesystem and libraries.

The core trade is isolation vs. weight. Containers isolate; that isolation costs image builds, a daemon, and overhead. Processes are light; the cost is that they share the host.

Head to head

Docker ComposeProcess manager
IsolationStrong (namespaces, own FS)Shared host
Dependency bundlingIn the imageOn the host
Resource overheadDocker daemon + per-containerMinimal
Startup speedSlower (container start)Fast (process spawn)
ReproducibilityExcellent (pinned images)Depends on host setup
DeployRebuild/pull imagePull + reload
Debuggingdocker logs, exec into containerhtop, direct log files
Zero-downtime reloadAwkwardBuilt in
Crash recoveryrestart: alwaysHealth-gated, with backoff

Where Docker Compose wins

  • Dependency hell is real and containers make it go away. If your app needs a specific system library, an exact Python version, or ImageMagick with the right delegates, baking it into an image is cleaner than fighting the host.
  • Reproducibility. A pinned image runs the same on your laptop and the server. “Works on my machine” mostly dies.
  • Third-party services. Spinning up Postgres, Redis, and your app together with one docker compose up is genuinely nice.
  • Blast-radius isolation. A misbehaving container can’t scribble on the host filesystem.

Where a process manager wins

  • Resource cost on small boxes. The Docker daemon plus per-container overhead is noticeable on a 1 GB VPS. A Rust process manager supervising native processes costs a few megabytes total.
  • Deploy and reload ergonomics. oxmgr reload api does a readiness-gated rolling restart in place. Doing the equivalent with Compose usually means a second container and a proxy switch.
  • Debugging directness. The process is right there. htop, strace, a log file, a SIGUSR2 — no docker exec layer between you and the program.
  • Startup latency. Process spawn is milliseconds; container start is seconds. It matters for fast crash recovery.

The move most people miss: use both

These aren’t mutually exclusive, and the best single-server setups often combine them:

Pattern A — Compose for backing services, process manager for your app. Run Postgres and Redis in Docker (where reproducibility helps most), and run your application under a process manager directly on the host (where deploy ergonomics and low overhead help most). Your app connects to localhost:5432. You get pinned dependencies where they matter and fast, health-gated reloads where you deploy constantly.

Pattern B — process manager inside the container. When you do containerize the app, you often still want more than node server.js as PID 1 — a supervisor that handles signals, restarts a crashed worker, and reaps zombies. A tiny static-binary process manager as the container entrypoint gives you graceful shutdown and multi-process supervision without dragging Node into your init layer.

How to choose

Ask what’s actually hard about your deploy:

  • Dependencies / reproducibility is the pain → Docker Compose (at least for the parts with heavy deps).
  • Overhead, deploy speed, and debugging are the pain → process manager on the host.
  • You have both pains → Pattern A: Compose for services, process manager for the app.

There’s no universal winner. Compose gives you isolation and reproducibility; a process manager gives you lightness and operational directness. On a single self-hosted box, the pragmatic answer is usually not “one or the other” but “the container where it earns its overhead, the process manager everywhere else.”