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.
A stack = a Compose project
Section titled “A stack = a Compose project”Every stack in dockmesh corresponds to one docker compose project:
- One
compose.yamlfile - 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.
The filesystem is the source of truth
Section titled “The filesystem is the source of truth”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
Stacks have a host
Section titled “Stacks have a host”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.yamlstacks/prod-us/analytics/compose.yaml
They’re separate stacks that happen to share a compose file (or not — each has its own copy).
Deploy is idempotent
Section titled “Deploy is idempotent”Clicking Deploy runs the equivalent of:
docker compose -f compose.yaml -p <project> up -d --remove-orphansThis 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)
The state model
Section titled “The state model”A stack is always in exactly one of:
| State | Meaning |
|---|---|
not_deployed | Compose file on disk, never deployed |
running | All services running and healthy |
partial | Some services running, some not |
stopped | Explicitly stopped via dockmesh or docker compose stop |
error | Last deploy failed |
changes_pending | compose.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.
Services within a stack
Section titled “Services within a stack”A service = a declared container template in compose. Services can scale to N containers (via Scaling):
service: web, replicas: 3→ 3 containers namedmyapp_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
Networks: stack-local by default
Section titled “Networks: stack-local by default”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.
Volumes: stack-local by default
Section titled “Volumes: stack-local by default”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.
Why not Kubernetes?
Section titled “Why not Kubernetes?”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.
See also
Section titled “See also”- Stack Management — the UI operations
- Agent Protocol — how multi-host works
- Host Tags — the tagging mental model