Skip to content

Stack Definitions

Bart Reardon edited this page Aug 9, 2026 · 2 revisions

Stack definitions (.containerstack)

A stack template is a plain JSON document. The templates that ship with the app use the same format, so any of them is a working example — open a template's create sheet and Export… to get one to edit.

Importing and exporting

  • Stacks ▸ + ▸ Import Template… — a .containerstack/.json file, or a docker-compose.yml (converted on the way in).
  • Double-click a .containerstack file in Finder.
  • Imported templates live in ~/Library/Application Support/ContainerManager/StackTemplates/ and appear in the New Stack menu. That folder is the management interface: Show Templates Folder opens it, and editing or deleting a file there is reflected the next time the menu opens.

Format

{
  "version": 1,
  "id": "wordpress",
  "name": "WordPress + MariaDB",
  "summary": "Shown under the create form.",
  "systemImage": "globe",
  "fields": [
    {"key": "name", "label": "Stack name", "default": "mysite"},
    {"key": "password", "label": "Database password", "default": "wordpress", "kind": "password"},
    {"key": "port", "label": "Web port", "default": "8080", "kind": "port"}
  ],
  "services": [
    {
      "key": "db", "displayName": "MariaDB", "image": "mariadb:11",
      "env": ["MARIADB_ROOT_PASSWORD=${password}"],
      "volumes": ["${name}-dbdata:/var/lib/mysql"]
    },
    {
      "key": "web", "displayName": "WordPress", "image": "wordpress:latest",
      "env": ["WORDPRESS_DB_HOST=${IP:db}:3306"],
      "publishPorts": ["${port}:80"]
    }
  ],
  "web": {"serviceKey": "web", "portField": "port"}
}

fields

The create form. kind is one of:

kind Behaviour
text (default) A plain field
password Masked
port Validated as 1–65535
directory Folder picker, and required

A field with key name is required. Its value is sanitised into a valid resource name and also names the network (<name>-net).

services

Created and started in order. Each has key, displayName, image, and optionally env, volumes, publishPorts, command and platform.

  • command overrides the image's default; omit it to use the image's.
  • platform is an OCI platform such as linux/amd64, for images that don't ship your Mac's architecture. Apple silicon runs those under emulation.
  • cpus and memory ("4g", "512m") set what the service gets; omit them for the runtime's defaults. Worth setting for anything substantial — a service given too little memory tends to stop answering rather than fail outright, which is a slow way to find out. A compose import fills these in from mem_limit, cpus or deploy.resources.limits.

Two kinds of token may appear in image, env, volumes, publishPorts and command:

Token Replaced
${fieldKey} At create time, with what was entered on the form
${IP:serviceKey} At start time, with that service's address

A token matching neither is rejected when the document is imported, not part-way through creating a stack.

web

Optional. Marks which service has the browser-facing port, which gives the stack its Open in Browser button at http://localhost:<port field>.

Volumes and mounts

  • mydata:/path — a named volume, created if needed, and kept when the stack is deleted.
  • /Users/you/site:/path — a bind mount from your Mac. Add :ro for read-only.

Definitions of stacks you create

Every stack gets a definition saved for it, not just imported ones — including custom stacks built in the app. That's what makes Re-create work for a service that has gone missing, and what the address reconcile compares against.

A stack's log lives alongside it and records how it was built. It's shown by the Log button in the stack's detail pane when there's something to say.

Limitations

  • Services reach each other by address, not name. See how services find each other.
  • Environment is fixed at creation. Editing a definition or a .env afterwards changes nothing until the service is replaced (Replace… in the stack detail pane).
  • Image VOLUME contents aren't copied into fresh volumes. Some images expect a mounted directory to be pre-populated or owned by their runtime user; those may need an init service that fixes ownership before the main service starts.
  • depends_on conditions are approximated — see waiting for dependencies.

Clone this wiki locally