Skip to content

How dockmesh thinks about Stacks

To use dockmesh well, it helps to understand how it thinks about stacks. The design is opinionated; the model is small.

Every stack in dockmesh corresponds to one docker compose project:

  • One compose.yaml file
  • Zero or more services (containers)
  • Zero or more volumes, networks, configs
  • A unique project name (<host>/<stack-name> in dockmesh)

This is exactly what docker compose calls a project. dockmesh doesn’t add a new abstraction — it uses the Compose spec.

Your compose.yaml lives on disk at <stacks-root>/<host>/<stack>/compose.yaml. It is the authoritative version.

The dockmesh database stores:

  • Metadata (name, host, created time, last deploy status)
  • Audit log entries
  • Template bindings (if the stack was deployed from a template)

But not the compose content. If you delete the dockmesh DB, your stacks still exist on disk. If you edit a file on disk, dockmesh detects the change and marks the stack as “changes pending” — the next deploy applies them.

This is deliberate. It means:

  • You can mix CLI (docker compose up) and dockmesh UI
  • Git-backed stacks (pull from a repo) work naturally
  • Disaster recovery is “copy the stacks/ directory back”
  • No vendor lock-in — uninstall dockmesh and your stacks keep working

In dockmesh, a stack always belongs to one host. Unlike Kubernetes (where pods float), Docker containers are pinned to machines.

To run the same stack in multiple places, create copies:

  • stacks/prod-eu/analytics/compose.yaml
  • stacks/prod-us/analytics/compose.yaml

They’re separate stacks that happen to share a compose file (or not — each has its own copy).

Clicking Deploy runs the equivalent of:

Terminal window
docker compose -f compose.yaml -p <project> up -d --remove-orphans

This is idempotent:

  • No changes → no containers recreated
  • Image tag bump → affected containers recreated
  • Volume added → created
  • Volume removed → not automatically removed (safety; use Prune to reclaim)

A stack is always in exactly one of:

StateMeaning
not_deployedCompose file on disk, never deployed
runningAll services running and healthy
partialSome services running, some not
stoppedExplicitly stopped via dockmesh or docker compose stop
errorLast deploy failed
changes_pendingcompose.yaml or env on disk differ from last deploy

State is computed from: Docker’s reported container states + the last-deploy hash stored in .dockmesh/state.json.

A service = a declared container template in compose. Services can scale to N containers (via Scaling):

  • service: web, replicas: 3 → 3 containers named myapp_web_1, myapp_web_2, myapp_web_3
  • Each gets the same image, env, volumes (except for container-scoped ones)
  • Load-balanced by Docker’s built-in DNS round-robin or by an external LB

When you deploy a stack, Compose creates a Docker network named <project>_default. All services in the stack join it. They can reach each other by service name.

Other stacks can’t reach this network unless you explicitly declare it as external: true in both stacks’ compose files.

This is the inverse of Kubernetes’ default: in K8s everything is reachable, and you add NetworkPolicies to restrict. In dockmesh/Compose, nothing is reachable cross-stack unless you arrange it.

Same pattern. volumes: pgdata: in compose creates a Docker volume named <project>_pgdata. It’s local to the stack unless declared external: true.

Cross-stack volume sharing is possible but unusual — usually you share data via networked APIs instead.

Why not “services” (Docker Swarm concept)?

Section titled “Why not “services” (Docker Swarm concept)?”

Docker Swarm’s “service” is a superset of a Compose service — adds replicas, constraints, rolling updates, health-based restarts. dockmesh uses plain Compose + a coordinator on top:

  • Replicas via dockmesh Scaling (which does what Swarm does, but cross-host-aware)
  • Constraints via host tags
  • Rolling updates via Stack Migration
  • Health-based restart via Compose’s healthcheck: + Docker’s auto-restart

Same capabilities, simpler runtime.

Kubernetes is more powerful and more complex. dockmesh is for the sweet spot between “one Docker host” and “I really need Kubernetes”:

  • 10-500 containers
  • Compose-shaped apps
  • Team size < 20 engineers managing it
  • Homelabs, small SaaS, internal tools

If your needs outgrow dockmesh: plan a migration to K8s. dockmesh doesn’t pretend to replace it.