Skip to content
Docker apps & stacks Deploy 1-click Marketplace apps and Compose stacks, manage env, build from git with Dockerfile or Nixpacks, roll back releases, and reach apps through the proxy.

Docker apps & stacks

MZPanel runs containerized workloads on your servers two ways: single apps (one image) and stacks (a full docker compose file). You manage both from a server’s Apps section (/servers/:id/apps) — a Stacks, Containers and Resources view with one shared Deploy drawer — and deploy catalog apps from the account-level Marketplace. These features are gated to Pro and up.

The Marketplace is one catalog of apps and extensions. Pick an app — n8n, Ghost, an AI UI, and more — choose a target server, give it a domain, and deploy. The Marketplace is state-aware: it shows what’s already installed on each server (an “Installed N/M” badge) and lets you update or remove in place, so the full lifecycle lives in one screen.

Deploying an app from the catalog provisions the container, wires up the nginx vhost, and issues SSL — the same flow you’d get configuring it by hand, without the steps.

A stack is a docker compose file you deploy as a unit from the Deploy stack action on the Stacks tab. MZPanel validates the compose (docker compose config) before bringing it up, so YAML and missing-variable errors surface inline instead of failing halfway. Day-2 actions include Update images (pull + recreate), health-depth (it reads the real failing healthcheck reason and restart count, not a guess), and per-service inspection — click a service to open its container drawer.

Stacks back up as a unit too — a DB-consistent backup captures the compose file, logical database dumps, and non-database volumes for a full restore.

In the Deploy drawer, pick From Git to point an app or stack at a repository. MZPanel clones and builds it on the box, then runs it. The Builder choice controls how:

  • Auto (default) — uses your repo’s Dockerfile if one is present; otherwise it auto-detects the stack with Nixpacks (Node, Python, Go, Ruby, and more) and installs Nixpacks on demand, so you don’t need a Dockerfile at all.
  • Dockerfile — force building your Dockerfile (set a custom path if it isn’t Dockerfile at the repo root).
  • Nixpacks — force Nixpacks even if a Dockerfile exists.

Pushing a new commit can trigger an automatic rebuild via a connected repo webhook. Builds run a RAM/disk preflight first so a low-memory VPS isn’t pushed over the edge (override with force only when you know it fits). Connect repos once under Git connections to build private repositories without pasting a token.

Set environment variables per app or stack from the Env tab — no SSH editing of .env files. Values are encrypted at rest on the box (sealed with the agent’s own key; only the key name stays readable for the list) and unsealed only into a transient in-memory --env-file when the container runs, so a stray disk snapshot or backup never leaks them. In the list, values are masked with a reveal action, survive rebuilds, and stay out of build logs.

Each successful build is kept as a release. If a deploy goes bad, roll back to a previous release instantly from the Releases view — it reuses the already-built image, so there’s no rebuild.

Apps and stacks built from git can get a throwaway preview environment per pull request, torn down when the PR closes. This mirrors the site preview flow — see Staging & deploys for how previews are triggered and the fork-PR safety rule.

Admin UIs like phpMyAdmin, pgAdmin, and webmail open as real pages on a MZPanel domain — not an iframe — through a reverse proxy that tunnels HTTP over the agent’s existing WebSocket to the app listening on localhost on your box.

Because the app only listens on 127.0.0.1 and your box opens no public port for it, the box hostname and IP stay fully hidden — there’s nothing to scan or attack. A proxy session is owner-scoped and time-limited; large data transfers (such as database export/import) go through native tools, not the proxy.

Actions dispatch app.* and stack.* jobs to the server’s agent, which runs them natively (never calling mz):

ActionJobAgent runs
Deploy catalog / image appapp.createapp create <name> --domain … --image …
Build app from gitapp.buildpreflight → git clone --depth 1 → Dockerfile or nixpacks build → run
Rebuild / rollbackapp.rebuild / app.rollbackrebuild from saved repo, or re-point at a kept release
Env storeapp.env-set / -listseals values at rest; unseals to a tmpfs env-file at run
Deploy stackstack.deployvalidates docker compose config, then brings it up
Update stack imagesstack.pullpull + recreate
Stack build from gitstack.buildclones + builds Compose services from source

The container, image, release history and sealed env live on the box; MZPanel’s control plane records only the connected repo/branch and proxy session wiring.

Each action maps to an mz app / mz stack command on the box — the same engine the dashboard drives. SSH in and run them, or let an on-box AI (ClaudeCode) run them:

Terminal window
mz app build web --git https://github.com/you/app --branch main --builder auto --json
mz app releases web --json
mz app rollback web --to <seq>
mz app env set web KEY=value --json # sealed at rest
mz stack list --json
mz stack rebuild db --json

Pass a sub-action and --json for machine output. See The mz CLI and the command catalog.

  • Auto builder needs neither a Dockerfile nor Nixpacks pre-installed. With no Dockerfile, MZPanel installs Nixpacks on the box on first use and auto-detects your stack; force Dockerfile or Nixpacks in the Deploy drawer to override.
  • Build preflight can refuse on a small VPS. A low-RAM/disk box is guarded so a build doesn’t OOM it — free space or use the force override only if the build fits.
  • Rollback reuses the built image. It’s instant and skips the rebuild, but it won’t undo external changes (databases, volumes) made since that release.
  • The app proxy is not for bulk data. It’s for admin UIs; database export/import and large transfers use native tools, not the tunnel.
  • Needs the agent online. Deploy, build, env changes and the proxy all run through the agent; when the server is offline these actions are unavailable.