-
-
Notifications
You must be signed in to change notification settings - Fork 0
Stacks
A stack is several containers stood up together as one unit — a web app and its
database, say. container itself has no compose concept; a stack is a ContainerManager
convenience that creates the pieces, wires them together, and labels them so they can be
managed as a group.
Create a stack called mysite and the app:
- Creates a private NAT network,
mysite-net, labelled with the stack. - Creates the named volumes its services need, labelled with the stack, so they're recognisable later even if the stack is gone.
- Validates the whole plan — mount specs, port specs, missing host paths — before creating anything, so a mistake in the fourth service doesn't leave the first three running.
- Creates and starts each service in dependency order, named
mysite-<role>, attached to the network. - Substitutes real addresses into each service's environment as it goes (below).
- Saves a definition of what it built, and a log of how it went.
Every container carries a com.containermanager.stack label, which is how the lists group
them. They also appear individually under Containers.
By default, containers on a container network reach each other by IP address —
nothing resolves container names until a DNS domain is configured, and the app can't assume
one, so it substitutes addresses instead of relying on names.
(If you have set up Local DNS, names do resolve between containers. Stacks still wire themselves with addresses, because a stack has to work whether or not you've done that.)
A definition refers to another service with a token:
WORDPRESS_DB_HOST=${IP:db}:3306
At create time the db service is started first, its address is read, and ${IP:db} is
replaced with it. No DNS, no copying addresses by hand.
Addresses change when containers restart, which would ordinarily break the wiring. Starting a stack reconciles it: services come up in dependency order, and any whose recorded addresses have gone stale are re-created with the current ones. Only the address entries are rewritten — anything you've edited by hand survives.
Two consequences worth knowing:
- A service started on its own, outside the stack, isn't reconciled.
- Anything a service records about itself during setup — a "site URL" written into a
database on first run — isn't ours to rewrite. Point those at
localhost:<published port>, which survives a restart.
With Local DNS configured you can sidestep all of this in
your own service definitions by using names — db.test rather than ${IP:db} — which
survive restarts and need no reconciling. The trade is that the stack then only works on a
Mac where DNS has been set up, which is why the bundled templates don't do it.
Stacks ▸ + lists what ships with the app:
| Template | What it is |
|---|---|
| WordPress + MariaDB | Blog/CMS with its database, both on volumes |
| PostgreSQL | A database on a volume, published for an app on your Mac |
| PostgreSQL + Adminer | The above plus a web UI to browse and query it |
| Mailpit | Local SMTP server with a web inbox, for testing outbound mail |
| Gitea | Self-hosted Git server with a web UI and git-over-SSH |
| code-server | VS Code in a browser, with a persistent /config volume |
| Nginx + host folder | Serve a folder from your Mac as a static site |
Below them are any templates you've imported, then Custom Stack…, then Import Template… and Show Templates Folder.
The bundled templates are ordinary .containerstack documents — the
same format you can export, edit and import.
Custom Stack… builds one from a web service plus an optional database service. If the
database is enabled you choose the variable to inject its address into — Inject DB
address into web as, default DB_HOST — and the database starts first so the address is
known.
The variable has to be one your image actually reads. The templates know the right names; a custom image may want something else.
Select a stack for a detail pane with:
- Start / Stop / Delete in the toolbar. Both Start and Stop stay put and enable or disable rather than swapping, because a stack containing a one-shot init service is never all running.
-
Appearance — a display name and icon of your choosing, so
wordpress-2can read as "Client site". - Services — each with its status, image and address. Right-click for a terminal, or Replace… to change a service's image, command, environment, ports or mounts. The replacement inherits what the old one had, so you can edit one field.
-
Add Service… — add a container to a running stack. It joins the network, gets the
labels, and can use
${IP:role}tokens against the services already up. - Network and Volumes — what the stack owns.
- Log — how the stack was built, and anything an import couldn't carry over.
If a service in the saved definition isn't running, the detail pane says so and offers Re-create, which rebuilds it from the settings it was created with. This is the usual outcome of a service that failed to start the first time.
Services added later with Add Service… aren't in the saved definition, so they aren't tracked this way.
Delete removes every container in the stack and its network. Volumes are kept — a database shouldn't disappear because you deleted the stack that used it. Remove them from Volumes when you actually want the data gone.
Containers get their stack label when they're created; the runtime has no way to change labels afterwards. So an existing container can't be moved into a stack — it has to be re-created.
Two ways to create one in a stack:
- Containers ▸ +, and pick the stack in the Stack row. It joins the stack's network automatically.
-
Stacks ▸ the stack ▸ Add Service…, which additionally lets you use
${IP:role}tokens.
Both mean the container is started and stopped with the stack, and deleted with it.
Volumes work the same way — Volumes ▸ + has a Stack picker — except that deleting a stack keeps its volumes. A volume that already exists can be grouped after the fact: right-click it and use Set Label…, which the app records itself.
Stacks come back stopped. Start them from the Stacks list — the reconcile step handles whatever addresses have changed.
Getting started
Guides
- Stacks
- Stack definitions
- Importing docker-compose
- Machines
- Images and builds
- Networking and DNS
- Settings and updates
Help