Deploy
Build
ant haul # build for deployment "local"
ant haul dev # build for deployment "dev"
ant haul --release 20260101T120000Z
Compose projects are built with docker compose build; everything else runs the
selected builder. build: none has nothing to build and is rejected with a hint
to use ant trail deploy.
Deploy and manage
ant trail deploy # build + run (defaults to "local")
ant trail deploy dev
ant trail deploy local --no-caddy # skip local domain routing
ant trail deploy --image ghcr.io/acme/api:1.4.2 --machine prod --port 8080
ant trail status [deployment] [--json]
ant trail logs [deployment] [service] [-f] [--tail N]
ant trail restart [deployment]
ant trail down [deployment]
ant trail destroy [deployment] --yes [--keep-images]
ant trail exec [deployment] -- <command> [args...]
ant trail env [deployment] # resolved KEY=VALUE pairs
ant trail doctor [deployment] # docker, ports, ant.yaml
ant trail history # recorded deploys (--project, --machine, --limit, --json)
ant trail rollback # redeploy the previous release (--to, --steps)
# Machine resources (this host, or a nest with --machine):
ant nest containers list | start NAME | stop NAME | restart NAME | rm NAME --yes
ant nest volume list | rm NAME [--force] --yes
Lifecycle commands accept an optional deployment name and default to local.
ant nest containers and ant nest volume are machine-scoped: they operate on
this host or, with --machine M, on a remote nest.
ant trail deploy --image REF runs a pre-built image on a machine (use
--from-tar to upload a docker save archive, --pull to fetch from a
registry, plus --app/--name, --env, --domain, --network, --restart,
and --publish-all). ant trail rollback redeploys the previous release's image
without rebuilding; it refuses compose projects, which may be redeployed with an
explicit --release.
Rolling out
A local deploy can stage the new container before replacing the old one
(zero_downtime: true). On a remote nest the worker always stages first: it
starts the new image on ephemeral ports with the deploy's read-only mounts
and waits for the health_check, then swaps. A deploy whose mounts are
writable (a live data volume, or a bind the app needs to boot) cannot be
staged safely and is replaced in place instead, with a post-start check that
fails a container which exits immediately.
ant trail destroy tears everything down. On this host: the container or stack,
the working directory under ~/.ant/local, and the images Ant built for the app
(images built or pulled outside Ant are never removed; --keep-images keeps the
app's images). On a machine: the container, compose project, or stack, plus its
Caddy routes; the machine's images stay for the build cache.
Reclaim disk
Nothing is removed unless you ask. Categories are independent, and each has a
--skip-* counterpart:
ant trail prune --all --skip-volumes # everything except volumes
ant trail prune --images --dangling # just those two
ant trail prune --images --dry-run # show what would go
| Category | Flag | Removes |
|---|---|---|
| Old app images | --images | This app's tags beyond deploy.keep_images (or rollback.keep_releases; default 10) |
| Dangling images | --dangling | Untagged intermediate layers |
| Build cache | --cache | The BuildKit cache |
| Volumes | --volumes | Unused volumes |
| Stopped containers | --stopped | Exited Ant-managed containers |
--keep-images N overrides the retention; --app/--deployment scope the
image category; --yes skips the confirmation. Every category has a --skip-*
counterpart, and --dry-run prints what would be removed.
Manage one volume
ant trail prune --volumes removes only unused volumes. To see every volume
on a machine and remove a specific one:
ant nest volume list # name, driver, scope, in-use
ant nest volume list --json
ant nest volume rm api_data --yes # refuse if a container uses it
ant nest volume rm api_data --yes --force # remove despite a stopped container
--force overrides a stopped container's reference; Docker still refuses to
remove a volume a running container is using. The dashboard shows the same
list on a machine's page, with a remove button. See
Volume management.
Local domains
Domains are opt-in: add one with ant nest edit domain add (or the dashboard's
Domains tab) and Caddy routes it to the running container. Opt out entirely with
--no-caddy, or disable Caddy for the machine in config.json.
Existing projects
Bringing a project, an image, or a machine that Ant did not create under management (including the cutover recipe for a hand-managed compose stack) is covered in Existing projects.