Commands
wctr
The client. It finds the daemon at -H unix:///path, else $WCTR_HOST, else
unix:///var/run/wctr.sock.
| Command | Flags |
|---|---|
pull IMAGE | IMAGE is a registry reference or oci:<dir>[:<ref.name>] |
images | -q |
run IMAGE [COMMAND] [ARG...] | --rm, -d/--detach, --name, -e/--env KEY=value (or KEY from the shell), --entrypoint, -w/--workdir, -m/--memory, -v NAME:/path[:ro] (v0.8.0), --network NAME (v0.10.0), --network-alias NAME (v0.14.0), --gpu (v0.13.0), --gpu-memory SIZE (v0.32.0; the GPU memory quota of the container’s batched contexts, 256m by default, at most 1.5g, refused without --gpu), -p/--publish [ip:][hostPort:]containerPort[/tcp|udp] (the ip defaults to 127.0.0.1), -P/--publish-all, --expose PORT[/proto] (v0.22.0), --restart no|always|unless-stopped|on-failure[:N] (v0.25.0; not with --rm; see Restart policies), --health-cmd and the other --health-* flags, --no-healthcheck (v0.28.0), -i/--interactive, -t/--tty, --detach-keys (v0.30.0; see “Terminals and input” below) |
attach [--no-stdin] [--detach-keys K] CONTAINER | this terminal to a running container: its output, and its input if it was created with -i; Ctrl-P Ctrl-Q detaches and leaves it running; exits with its status when it stops (v0.30.0) |
port CONTAINER [PRIVATE_PORT[/PROTO]] | where a running container’s ports are published, e.g. 80/tcp -> 127.0.0.1:8080 (v0.22.0) |
ps | -a/--all, -q; a PORTS column as Docker writes it (v0.22.0) |
logs CONTAINER | -f/--follow |
rm CONTAINER... | -f/--force |
rmi IMAGE... | -f/--force |
commit CONTAINER [REPO[:TAG]] | -m/--message, -a/--author, -c/--change (CMD, ENTRYPOINT, ENV, EXPOSE, LABEL, ONBUILD, STOPSIGNAL, USER, VOLUME, WORKDIR): the container’s changes as one OCI layer on the parent’s, with a history entry; without a name, a <none> image addressable by ID (v0.12.0) |
tag SOURCE TARGET | another name for an image; a tag that moves leaves the old image as <none> (v0.12.0) |
inspect NAME|ID... | containers, then images |
build, compose | wctr build and wctr compose, built into wctr since cmd/wctr v0.1.0; they use wctr’s -H, which goes before the subcommand |
exec [-d] [-i] [-t] [-e K=V] [-w DIR] CONTAINER CMD... | a further process in a running container, in its process group; needs --wasi engine; exits with the command’s status; -t gives it a terminal (the engine does the line editing and echo); -u accepts only root or 0 (engine v0.20.0). In the browser executor since v0.26.0: the process runs in its own worker inside the container’s process group, counts against its limits and is killed with it. -t follows window resizes since v0.27.0: SIGWINCH on unix, a 2 Hz size sampling on Windows, wasip1 and js |
kill CONTAINER... | |
start CONTAINER... | -a/--attach (one container: prints this run’s output and exits with its status) and -i (also sends this terminal’s input, for a container created with -i) (v0.30.0); -a/--all (v0.5.0) |
stop CONTAINER... | -t, accepted and ignored (v0.5.0) |
restart CONTAINER... | -t, accepted and ignored (v0.5.0) |
diff CONTAINER | (v0.4.0) |
events | --since, --until, filters on type, event, container, image, volume and label (v0.6.0) |
stats | (v0.7.0) |
volume create|ls|inspect|rm|prune | (v0.8.0) |
network create|ls|inspect|rm | (v0.10.0) |
network connect [--alias NAME] NETWORK CONTAINER | a running container at once (v0.14.0) |
network disconnect [-f] NETWORK CONTAINER | (v0.14.0) |
network prune [-f] [--filter label=K[=V]] | unused networks (v0.14.0) |
system df | -v (v0.4.0) |
system prune | -a, -f (v0.4.0) |
version | |
completion bash|zsh|fish|powershell | prints the completion script for that shell (v0.3.0) |
wctr run pulls an image it does not have.
A WebAssembly guest has no signals, so wctr stop kills the container at once:
-t is accepted for compatibility and ignored. In the API, /attach is a plain
streamed response, not a hijacked connection.
Terminals and input (v0.30.0)
wctr run -i/-t, wctr attach and wctr start -ai give a container’s first
process its own stdin and terminal. They use Docker’s fields Config.Tty,
Config.OpenStdin, Config.StdinOnce and HostConfig.ConsoleSize.
- A container’s first process can get a stdin that attached clients write into.
With
-tit also gets a terminal: the engine handles line editing, echo and CR LF, and keeps keys typed ahead when a program switches to raw mode (the hand-over of the typed line is engine v0.29.2). POST /containers/{id}/attachacceptsstdin=1anddetachKeys. Like exec start, it does not hijack the connection: the request body carries stdin and the response streams the output.POST /containers/{id}/resizeis new.- Ctrl-P Ctrl-Q detaches; detach keys use Docker’s format.
- It works in both executors, the native one and the browser’s. No host call blocks on stdin (v0.29.1).
- These commands are in engine v0.30.0’s
clipackage.cmd/wctrv0.2.0 required engine v0.22.0 and does not have them;cmd/wctrv0.3.0 requires engine v0.30.0 and does. The daemon (wctrdv0.31.0) serves the API.
For builders (v0.12.0, API only for now)
POST /images/loadtakes an OCI image layout as a tar; eachindex.jsonentry is named byio.containerd.image.nameororg.opencontainers.image.ref.name, else<none>. It is checked as a pull is, and nothing is read from the host.PUT /containers/{id}/archive?path=DIRextracts a tar into a container (relative clean names only, no devices, paths resolved inside the container, its quota applies), andGETreturns a tar of a path. These two routes accept uploads up to 1 GiB by default; every other request is limited to 1 MiB.GET /images/{name}/jsonshows the full image config, the history, andRootFS.Layersasdiff_ids. Dangling images appear as<none>.HEADon the archive route returns only the path’s stat, without building a tar (v0.14.0).- The Go client filters lists through
ContainersFiltered,NetworksFilteredandVolumesFiltered, which take anapi.Filters. v0.18.0 had changed the signatures ofContainers,NetworksandVolumesto take filters, which broke the dashboard; v0.21.0 restored them, and a new CI job compiles downstream modules against the engine. - A start refused before the process exists (a port, a network, a volume) is
recorded as an exit with code 128 and the reason, as Docker records it: a
run --rmreturns at once and its container is removed (v0.22.0). Since v0.23.0,wctr runexits 125 when the daemon refuses the start. - Other modules add commands to
wctrthrough an extension hook,cli.Options.Extra;wctr buildandwctr composeuse it.wctr buildneeds awctrdof v0.12.0 or later (v0.17.0 for shell-formRUN).
Events (v0.6.0)
wctr events and GET /events stream NDJSON. --since and --until bound
the range, and the filters are type, event, container, image, volume, network and label.
The last 1024 events are kept, and a reader that is too slow is cut off.
Stats (v0.7.0)
wctr stats and the stats endpoint report memory against its limit, bytes
written, layer and log size, and pids. CPU is not measured: a WebAssembly
guest gives no CPU accounting, so it is shown as --.
Volumes (v0.8.0)
wctr volume create|ls|inspect|rm|prune, and wctr run -v NAME:/path[:ro].
Only named volumes exist: a host path is refused. A volume is shared between
containers, :ro is enforced, and volumes survive a restart and a page reload.
They appear in system df and in inspect.
Persistence (v0.4.0)
Containers survive a wctrd restart: they are kept under --data-root in
containers/ (state, exit code, logs and written files). A container that was
running comes back exited with code 137, and a --rm container is removed. An
entry that is corrupted is dropped and reported.
Exit status of wctr run
The container’s own, or:
| Code | Meaning |
|---|---|
| 125 | the CLI or the daemon failed |
| 126 | not a WebAssembly module |
| 127 | module not found |
| 134 | the module trapped |
| 137 | killed, or the wall-clock timeout |
A guest’s own proc_exit code is a Docker status (engine v0.30.1): 0 to 255 is kept, so a
guest that exits 126, 127 or 130 reports exactly that. A code outside that
range (os.Exit(-1) arrives as 4294967295, or 256 and above) is reported as 1,
which is also what wasmtime reports for it. wasmtime additionally turns 126 to
255 into 1; the engine does not, because Docker is the target.
Standard input, output and error are reported to the guest as a character
device only under run -t or exec -t (a pipe is no longer reported as one since engine v0.30.1); otherwise (a pipe) they are of type
unknown, as in wasmtime, so isatty() and Go’s terminal checks answer false
for piped input.
Restart policies
run --restart and HostConfig.RestartPolicy (engine v0.25.0), as Docker’s:
alwaysrestarts a container whenever it exits, and starts it with the engine;unless-stoppeddoes the same, except that the engine leaves it stopped if a user stopped it;on-failure[:N]restarts it when it exits with a code other than 0, at most N times (0: no bound);nois the default.
A user’s stop or kill ends the policy until the next start, which counts from
zero. Each restart waits first: 100 ms, doubled after every run shorter than 10 s, at
most a minute. Meanwhile the container is restarting: ps lists it as Restarting (code) … ago, and rm needs -f. A start the engine refuses (a volume, a network, a
port) is not retried. inspect shows HostConfig.RestartPolicy, RestartCount and
State.Restarting. A policy cannot be combined with --rm.
Health checks
run --health-cmd CMD, --health-interval, --health-timeout,
--health-start-period, --health-start-interval, --health-retries and
--no-healthcheck (engine v0.28.0), as well as an image’s HEALTHCHECK and
Config.Healthcheck. The test (CMD argv, CMD-SHELL through /bin/sh -c, or
NONE) runs inside the running container through the exec machinery, every interval
(default 30 s; 5 s during the start period), and is killed after the timeout
(default 30 s, exit code −1). A pass makes the container healthy; retries
consecutive failures (default 3) make it unhealthy; failures in the start period do
not count. Fields left empty are taken from the image’s check. inspect shows
State.Health (Status, FailingStreak, and the last 5 results with at most 4 KiB
of output each), ps shows Up … (healthy), and each change of status is a
health_status event (healthy or unhealthy; --filter event=health_status).
Probes stop with the container and are not exec events. Unlike Docker, an interval or
timeout below 100 ms is refused. A CMD-SHELL probe needs a /bin/sh in the
image (the shell image has one).
For embedders. An in-process engine must register wasi.WASIX in its
HostModules, as wctrd does, to run the shell image or health checks.
wctrd
| Flag | Meaning | Default |
|---|---|---|
-H, --host unix:///path | the socket to serve (unix only; TCP is refused, the API has no authentication) | unix:///var/run/wctr.sock |
--data-root | where images are kept | $XDG_DATA_HOME/wasmcontainers, else ~/.local/share/wasmcontainers |
--memory | linear-memory limit per container | 256m |
--run-timeout | wall-clock limit per run (0 = none) | 10m |
--storage-quota | bytes a container may write | 256m |
--max-containers | containers at once | 256 |
--insecure-registry host:port | allow plain HTTP to that registry (loopback registries are always plain HTTP) | none |
Bounds on untrusted content
| What | Bound |
|---|---|
| blob | 512 MiB |
| image | 1 GiB, 128 layers |
| unpacked layers | 1 GiB, 131072 files |
| gzip expansion ratio | 200:1 |
| logs kept | 8 MiB per container |
Created on by tannevaled
Modified on by tannevaled