docker¶
The docker package provides image building, Compose orchestration, and file staging for workflows that run containers on a remote parent host.
Docker support for otto.
This package provides a library API that the CLI (otto docker ...) and
project instructions/suites both call into. Anything the CLI can do, an
instruction can do too:
from otto.docker import build_images, compose_up, compose_down, composed
@instruction()
async def smoke():
async with composed(repo, lab, own=True) as containers:
await containers["api"].run("./run-tests")
See the design notes in docs/design/docker_hosts.md for the full
architecture (parent-delegation pattern, hop inheritance, naming scheme).
-
async otto.docker.build_images(repo: Repo, parent: Host, *, image_names: Iterable[str] | None =
None, rebuild: bool =False) dict[str, tuple[Status, str]]¶ Build all (or selected) images for repo on parent.
- Parameters:¶
repo – The
Repowhose[docker]settings declare the images.parent – A docker-capable lab host. Builds happen here.
image_names – Optional filter — only build images whose
nameis in this iterable.Nonebuilds everything declared.rebuild – When
True, skip the context-hash existence check and always invokedocker build.
- Returns:¶
Mapping of image name to
(Status, message_or_tag). Status isSkippedfor images that already existed,Successfor fresh builds, and a failure status otherwise. The message is the full tag on success/skip, or the captured stderr on failure.
-
async otto.docker.compose_down(repo: Repo, lab: Lab, *, on: str | None =
None, project_name: str | None =None, stop_timeout: int =1) Status¶ Tear down repo’s compose stack and unregister its container hosts.
stop_timeout is the per-container graceful-shutdown grace period in seconds passed to
docker compose down --timeout. Defaults to 1s rather than docker’s default of 10s — otto’s typical workload is integration tests with disposable stacks where waiting 10s on every teardown adds up fast (4 tests × 10s = 40s of wall time on the serializeddocker_e2egroup). Pass a larger value for stacks where graceful shutdown matters.
- async otto.docker.compose_ps(parent: Host) list[dict[str, Any]]¶
Return a list of dicts describing running containers on parent.
Uses
docker ps --format '{{json .}}'so the output is structured.
-
async otto.docker.compose_up(repo: Repo, lab: Lab, *, on: str | None =
None, project_name: str | None =None, build: bool =True) dict[str, DockerContainerHost]¶ Bring up repo’s compose stack on a parent host.
Idempotent at the project-name level: if a stack with the same project_name is already running on parent, this becomes a lookup instead of a fresh
up. Either way, returns a dict mapping each declared service to itsDockerContainerHost, with the hosts also registered inlab.hostsso--list-hostsandotto host <id>see them.- Parameters:¶
build – When True (the default) and the repo declares
[[docker.images]], runbuild_images()first so locally- built images exist on the parent before compose tries to pull them. The build is idempotent via the context-hash skip, so this is cheap when nothing changed. Passbuild=Falseif the compose file references only published images (or if you already built explicitly).
-
otto.docker.composed(repo: Repo, lab: Lab, *, on: str | None =
None, project_name: str | None =None, own: bool =False, build: bool =True) AsyncIterator[dict[str, DockerContainerHost]]¶ Context manager wrapping
compose_up/compose_down.By default the stack is not torn down on exit if it was already running on entry — this lets a suite-level fixture hold the stack while inner instructions also call
composedwithout yanking it from each other. Passown=Trueto force teardown.build is forwarded to
compose_up().
- otto.docker.context_hash(image: DockerImage) str¶
Return a stable sha256 hex digest of image’s build inputs.
- otto.docker.get_container_host(host_id: str) DockerContainerHost¶
Look up a registered container host by id. Raises if not present.
-
otto.docker.get_user_compose_project(repo_name: str, suffix: str | None =
None) str¶ Return a compose project name unique enough to coexist with other runs.
Format:
otto-<repo>-<suffix>. suffix defaults to the OS username, orOTTO_COMPOSE_SUFFIXif set in the environment. Lowercase only — compose project names must be lowercase.
- otto.docker.image_full_tag(registry_url: str, project: str, image: DockerImage, hash_hex: str) str¶
Construct the
<project>-<image>:<hash>tag (with registry prefix when non-default).
- otto.docker.image_latest_tag(registry_url: str, project: str, image: DockerImage) str¶