Skip to main content
The same image can produce very different machines. Declare what you need at creation time instead of maintaining a derived image for each variation.

What you can set

The fields below are forwarded through **kwargs to the underlying BoxOptions in wrapper classes such as SimpleBox/CodeBox, and can also be used directly with BoxOptions(...).
SimpleBox’s convenience parameters only cover image / rootfs_path / memory_mib / cpus / runtime / name / auto_remove / reuse_existing; env / entrypoint / cmd / user / working_dir and so on are forwarded through **kwargs to BoxOptions, so their names and types follow BoxOptions (for example Python’s working_dir, and the construction-time env being a list of tuples).

Quick Example

The shortest path: use SimpleBox to inject environment variables, run as a non-root user, set the working directory, and then run a command to verify.

The relationship between entrypoint and cmd

An OCI image has two directives: ENTRYPOINT (the executable) and CMD (default arguments). The final startup command is the concatenation of the two: ENTRYPOINT + CMD.
  • Set only cmd: replace the default arguments, keep the image’s ENTRYPOINT.
  • Set only entrypoint: replace the executable.
  • Set both: fully customize the startup behavior.
Note: some images (such as python:alpine) put the default command in CMD rather than ENTRYPOINT. To pass arguments like -c, you must explicitly set entrypoint=["python3"], otherwise the arguments have nothing to attach to.
Important: entrypoint + cmd becomes the box’s main command, so the box stops when it exits. Keep it long-running if you want to exec afterwards, as the example below does. See The main command for the rules that follow.

Overriding cmd drops the image’s working directory

Setting cmd replaces the image’s command but does not inherit the WORKDIR it was written against. Relative paths in the image’s own start command then fail — usually as a missing-file or module error naming a path that does exist:
Two fixes, in order of preference:

user: running as non-root

user accepts a username or a UID, in the format <name|uid>[:<group|gid>]. Non-numeric usernames are resolved from the container’s /etc/passwd / /etc/group.
You can also override the user/directory/environment per-exec (env here is a dict):

Return value: ExecResult

box.exec(...) returns an ExecResult (a dataclass in the Python wrapper layer). Node’s ExecResult fields are exitCode / stdout / stderr.

Troubleshooting

Passing a string as the volume’s third element causes a TypeError

A volume’s third element is the boolean read_only; the strings "ro"/"rw" are CLI-only and raise TypeError here. See Volumes.

Construction-time env passed as a dict reports a type error (Python)

SimpleBox(env=...) / BoxOptions(env=...) requires list[tuple[str, str]] at construction time:
box.exec(env=...) uses a dict at execution time. The distinction: a list at construction time, a dict at exec time.

cmd arguments take no effect / the image has no ENTRYPOINT

If the image’s default command is in CMD (not ENTRYPOINT), setting cmd=["-c", ...] alone leaves the arguments with no executable to attach to. Explicitly set entrypoint=["python3"] (or the target executable); see the entrypoint example above.

After setting entrypoint + cmd to a short-lived command, exec reports incompatible container status: Stopped

The box stopped when its main command exited:
Fix: keep the main command long-running (sleep, or a service), or treat the box as single-shot and do not exec again. The main command covers the rules, and Exit codes covers how to read what it exited with.

working_dir pointing to a nonexistent directory makes exec raise RuntimeError

working_dir (or exec(cwd=...)) must be a directory that already exists in the image. When it points to a nonexistent directory (e.g. setting working_dir="/work" on alpine), the box still creates successfully, but the first exec raises:
Fix: use a directory that ships with the image (alpine has /tmp, /root), or create one first via exec from an existing working directory:

exec exits non-zero without raising

This is expected behavior: when exec fails (the command returns non-zero) it does not raise but returns an ExecResult with exit_code != 0. Always check result.exit_code (Node: result.exitCode).

A missing command / image pull failure raises a standard exception

  • Missing command: raises a standard RuntimeError (Python) / a bare Error (Node), not a BoxliteError subclass.
  • Image pull network flakiness: raises a RuntimeError, which you can retry after try/except.
When catching, use a broad except Exception rather than only catching BoxliteError.

No hardware virtualization causes startup failure

BoxLite requires hardware virtualization (an environment constraint):
  • Linux: requires KVM (/dev/kvm available); under WSL2 the user must be in the kvm group.
  • macOS: uses Apple Hypervisor.framework, no /dev/kvm required (macOS arm64 supported).
  • No virtualization: startup fails on async with entry. The process does not crash and can be caught with try/except to report the issue.

working_dir and exec(cwd=...) fail at different moments

Both require a directory that already exists in the image, but they fail in different places, which changes how you recover. A missing working_dir fails when the box is created — before any command runs:
A missing exec(cwd=...) fails only that call, and the box stays usable:
So a bad working_dir costs you the box; a bad cwd costs you one command. Alpine ships /tmp; create anything else first with exec("mkdir", "-p", "/work").