Skip to main content
Build an image from a Dockerfile. Each directive runs against the contree API and produces a new image layer; successful layers are materialised as branches named layer:<chain-hash> so re-running the same Dockerfile reuses prior work.

Synopsis

  • CONTEXT – build context directory (default .).
  • --dockerfile PATH – override the default <CONTEXT>/Dockerfile.
  • --tag NAME[:TAG] – tag the final image via PATCH /v1/images/{uuid}/tag.
  • --build-arg KEY=VALUE – supply a value for an ARG declared in the Dockerfile (repeatable).
  • --no-cache – ignore existing layer:<hash> branches and rebuild.
  • --timeout SEC – per-RUN operation timeout in seconds (default 600).

Help output

$ contree build —help
usage: contree build [-h] [—dockerfile PATH] [—tag NAME[:TAG]] [—build-arg KEY=VALUE]
[—no-cache] [-t TIMEOUT]
[context]

Build an image from a Dockerfile.

Reads the Dockerfile at the given path (default “<CONTEXT>/Dockerfile“)
and applies each directive against an isolated build session keyed by
the absolute path of the context directory. Successful layers are
materialised as branches named “layer:<chain-hash>“ so that
re-running the same Dockerfile reuses prior work.

Supported directives (MVP): FROM (multistage via “FROM … AS name“),
RUN, COPY (including “—from=<alias|index|image>“), ADD (local
files/dirs and http(s) URLs; no tar auto-extraction, no “—from“),
WORKDIR, ENV, ARG, USER. Other Dockerfile directives parse cleanly but
are skipped with a warning (CMD, ENTRYPOINT, LABEL, EXPOSE, VOLUME,
STOPSIGNAL, MAINTAINER, HEALTHCHECK, ONBUILD, SHELL).

Multistage notes: “COPY —from“ exports the source path from the
referenced stage image as a tar archive, uploads it once (content
deduplicated) and unpacks it with an extraction RUN inside the target
sandbox. For now this means the target image must provide “/bin/sh“,
“tar“, “cp“ and “mv“ (busybox suffices; “FROM scratch“ targets
cannot receive “COPY —from“). This is a temporary limitation of the
client-side extraction and will be lifted in a future release once the
backend unpacks archives itself. Unlike docker, ARG/ENV live in one
global namespace across stages.

positional arguments:
context Build context directory (default: .)

options:
-h, —help show this help message and exit
—dockerfile PATH Dockerfile path (default: <context>/Dockerfile) (default: )
—tag NAME[:TAG] Tag the final image (default: )
—build-arg KEY=VALUE
Build-time variable (repeatable)
—no-cache Ignore cached layers and rebuild
-t, —timeout TIMEOUT
Timeout in seconds for each RUN step (default: 600)

examples:
contree build .
contree build . —tag myimage:latest
contree build —dockerfile ./Dockerfile.test ./app
contree build —build-arg VERSION=1.2 .
contree build —no-cache .

for coding agents:
mutating command, may create operations against the API
layer cache is per-context (session keyed by abspath(context))
use —no-cache to bypass cached layers and rebuild from scratch
multistage supported: FROM … AS name + COPY —from=<name|index|image>
COPY —from unpacks a tar inside the target: needs sh/tar/cp/mv there
(temporary limitation, to be lifted in a future release)

agent note:
Before using this command in an automated workflow, read:
contree agent

Examples

Supported directives (MVP)

COPY --from=stage is a Phase 2 feature; in MVP it warns and skips.

Sessions and layer cache

Builds run in a dedicated session keyed by the absolute path of the context directory: build:<sha16(abspath(context))>. Re-running the same Dockerfile in the same context reuses cached layers across invocations of contree build; switching to --no-cache rebuilds everything. Layers are stored as branches whose names are the chain-hash of:
To inspect the resulting branches:
build is project-scoped from the user’s point of view: it does not bind to the agent’s -S <key> session. Passing -S is harmless but does not move that key’s image. After a successful build, attach the result to your normal agent session by tag:

.dockerignore

contree build reads <CONTEXT>/.dockerignore and filters every COPY/ADD walk. Rules are matched in order against POSIX-style paths relative to the context root; the last matching rule wins, so ! re-includes a previously ignored path.
Globs:
  • * matches a single path segment (does not cross /).
  • ** matches zero or more path components.
  • ? matches one character.
  • [abc] is a character class.
  • Trailing / matches a directory and everything below it.
The default exclude list from run --file (.git, *.pyc, __pycache__, .venv, node_modules, dist, build, etc.) is always applied on top of .dockerignore.

Variable substitution

$VAR and ${VAR} are expanded in FROM, RUN, COPY/ADD arguments, WORKDIR, ENV values, and USER. The value source is:
  1. --build-arg KEY=VALUE (highest priority for declared ARG names).
  2. ENV directives processed so far.
  3. ARG defaults.
  4. Empty string for unknown names.

End-to-end demo

A small example lives in docs/examples/build-demo/. The Dockerfile exercises FROM, ARG, ENV, WORKDIR, two COPY directives (file and directory), and two RUN directives. A .dockerignore filters log files and __pycache__ from the upload.
The ADD line streams the zip straight from GitHub into the contree API (no local temp file). The subsequent RUN steps unpack it, pip install the project, and prove the installed contree binary works inside the built image.
Build and tag it:
Expected output (truncated):
Re-running the same command without --no-cache produces layer cache hits, and the ADD URL step short-circuits at the HEAD probe (look for URL cache hit (HEAD validators match) in the log) – no body download, no upload.

See also