Skip to content
Apps (Docker) Deploy and run Docker containers and compose stacks on a single server — catalog apps, custom images, build-from-git, and resource cleanup.

Apps (Docker)

The Apps section of a server (/servers/:id/apps) is the box-level home for Docker: everything containerized that runs on this machine. It’s organised like a condensed Portainer into three tabs — Containers, Stacks and Resources (images, volumes and networks). Docker is gated to Pro and above.

For the account-wide roll-up across every server, use fleet Apps; this page is where you do the deep, per-box work.

  1. On the Containers tab, click the dashed Deploy card (or Deploy stack on the Stacks tab) — both open the same deploy drawer.
  2. Pick a source:
    • Catalog — a one-click app or stack template (n8n, Ghost, an AI UI, and more). Fill in the template’s fields (domain, and any app-specific values).
    • Custom — bring your own image (a single container) or paste a compose file (a stack).
    • Git — point at a Git repository and MZPanel builds it on the box (see below).
  3. Give it a name and a domain. For a container, set the internal port the app listens on; MZPanel wires up the nginx vhost and issues SSL for you.
  4. Click Deploy. Output streams live; when it finishes the drawer closes and the owning tab remounts to show the new app.

Containers tab

  • Lifecycle — start, stop, restart, pause/unpause and remove any container, with an inline row spinner and error banner (no toasts).
  • Logs — tail recent output, or follow it live.
  • Console (exec) — run a shell command inside a container.
  • Stats — live CPU/memory for a running container, plus a metrics history chart.
  • Manage (for MZPanel apps) — edit and redeploy in place (image, env, port, memory), build from git, view releases and roll back, manage the env store, and set up per-PR previews.
  • Adopt — a container created outside MZPanel (raw docker run) shows an Adopt button to bring it under management.
  • Clear stopped — prune exited containers.

Stacks tab

  • Lifecycle — start (up), stop (down), restart and delete a stack.
  • Update images — pull newer images and recreate.
  • Edit compose — read the current compose, edit it, and redeploy.
  • Env / Build / Releases — the same env store, build-from-git and rollback as apps, when the stack was built from git.
  • Adopt — an external compose project (started outside MZPanel) can be adopted under management while keeping its original project name.
  • Open a service — click a stack’s service to jump to its container drawer.

Resources tab

  • Images — list, pull (with optional private-registry auth), scan, and remove; prune dangling images.
  • Volumes — create, remove and prune.
  • Networks — create (driver + subnet), remove and prune.
  • Disk usagedocker df plus a system prune to reclaim space.

Every action dispatches a job to this server’s agent, which runs it natively in Go (the agent shells out to docker/docker compose directly, never to a helper script). The tabs read live inventory that the agent pushes to the control plane:

TabReads (inventory kind)Mutations (job kinds)
Containersdockerdocker.start/stop/restart/pause/unpause/remove/logs/logs-follow/stats/exec, container.prune, and app.* for managed apps
Stacksstacksstack.list/deploy/up/down/restart/delete/pull/get/update/adopt (+ stack.build/releases/rollback/env-* for git stacks)
Resourcesimages, volumes, networksimage.*, volume.*, network.*, docker.df, docker.system-prune

State lives on the box, not in MZPanel’s database:

  • Single-container apps are registered at /etc/mz/apps/<name>.conf.
  • Stacks live under /etc/mz/stacks/<name>/ (compose file, .env, releases).
  • Build-from-git clones and builds on the VPS — with a Dockerfile it builds that; without one it uses Nixpacks auto-detect (Node, Python, Go, Ruby, …). A RAM/disk preflight runs first so a low-memory box isn’t pushed over the edge.

Reads come from the cached inventory (instant), and each mutation triggers a re-push so the list reflects the new state.

Everything here maps to an mz command on the box — the same engine the dashboard drives. SSH in and run them directly, or let an on-box AI (ClaudeCode) run them:

Terminal window
mz docker status --json # every container on the box
mz app create myapp --domain app.example.com --image ghost:5 --port 2368 --json
mz stack list --json # every compose stack
mz stack create mystack --domain s.example.com --port 8080 --compose-b64 <b64> --json

Container lifecycle is mz docker start|stop|restart|remove <container>; managed apps use mz app start|stop|restart|delete <name>; stacks use mz stack up|down|restart|delete <name>. Pass --json for machine output. See The mz CLI and the command catalog.

  • Offline servers show a preview. When the agent is offline this section renders a representative mock behind a Preview banner and lifecycle edits stay local — they don’t reach the box. Bring the agent online to run real Docker actions.
  • Docker must be installed first. A box with no Docker engine has nothing to list. Install it from the server’s tools/extensions before deploying.
  • Custom compose needs a resolvable web port. If your pasted stack should get a public URL and SSL, map its HTTP service to __MZ_PORT__ — otherwise MZPanel has no port to proxy and SSL to.
  • Adopt keeps the original name. Adopting an external container or compose project preserves its name/project (zero-downtime) rather than renaming it, so running services aren’t disrupted.
  • Builds spike the box. Build-from-git runs on your VPS, so a build is a short CPU/RAM spike; the preflight guard blocks it if the box is too tight on memory.
  • Removing a running container forces it. Remove on a running or paused container passes --force; stop it first if you want a graceful shutdown.
  • Docker apps & stacks — the full concept guide: catalog, env store, build-from-git, rollback, app proxy.
  • Fleet Apps — the account-wide roll-up across every server.
  • The mz CLI — driving the box from the command line.