runner
Run an image the way the platform does, through the docker command.
The platform's runner renders :class:AnalysisSandboxConfig into its
container runtime's terms; this module renders the same model into
docker run flags, adds the resource limits and thread-count variables
the platform sets, mounts the fixture where the platform mounts an
allocation, and passes the one argument the contract allows. Nothing here
depends on a Docker SDK: the command line is the interface, so the check
runs wherever docker does.
Every run also reports the peak memory the container used, read from its
cgroup, without assuming anything about the language inside. The image's
own entrypoint runs as a child of /bin/sh, which keeps its exit status
and output and, once it has exited, writes the peak into the output
directory: memory.peak under cgroup v2, memory.max_usage_in_bytes
under cgroup v1. An image without /bin/sh or an entrypoint, or a kernel
that exposes neither file, runs as it would otherwise and reports why its
peak is missing.
The peak counts page cache charged to the container. With
stage_recording the recording is first copied into a volume by a
separate container, so that its page cache is charged to that copy, as it is
to whatever wrote the file on the platform, and the peak is what the
analysis holds itself.
DockerRunner
¶
Runs images through the docker command line.
__init__(*, sandbox=None, platform=None, docker='docker', measure_peak=True, stage_recording=False)
¶
Configure the runner.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sandbox
|
AnalysisSandboxConfig | None
|
The confinement to apply. Defaults to the platform's. |
None
|
platform
|
str | None
|
A |
None
|
docker
|
str
|
The docker binary. |
'docker'
|
measure_peak
|
bool
|
Report each run's peak memory. False runs the image's entrypoint directly. |
True
|
stage_recording
|
bool
|
Copy the recording into a volume with the
image's |
False
|
available(docker='docker')
staticmethod
¶
Whether the docker command exists on this machine.
inspect(image, *, pull)
¶
Describe an image, pulling it first when asked.
memory_total_mib()
¶
Return the memory the docker engine has, in MiB; None when it does not say.
peak_support(image)
¶
Decide once per image whether its runs can report their peak.
Returns:
| Type | Description |
|---|---|
list[str] | None
|
The entrypoint to wrap and an empty reason, or None and why the |
str
|
peak cannot be measured. |
run(image, *, alloc_dir, local_dir, cores, memory_mib, timeout_seconds)
¶
Run the image once; kill it when the timeout passes.
ImageInfo
dataclass
¶
What the image says about itself.
RunResult
dataclass
¶
What happened when the container ran.
peak_memory_mib
property
¶
The peak in MiB, rounded up; None when it was not measured.
Runner
¶
docker_run_args(image, *, sandbox, alloc_dir, local_dir, cores, memory_mib, name, platform=None, docker='docker', wrap=None, recording_volume=None, selinux_relabel=False, command=None)
¶
Render one docker run command line equivalent to the platform's task.
The mapping from the sandbox model is one flag per measure: no network
is --network none, dropping capabilities is --cap-drop ALL, the
read-only root is --read-only with a tmpfs at /tmp, and the user
is --user. Memory is a hard limit with swap disabled, as the
platform enforces it; cores become --cpus and the thread variables.
With wrap, the image's entrypoint, the container starts /bin/sh
with :data:PEAK_SCRIPT instead, which runs that entrypoint with the same
one argument and then records the peak memory. With recording_volume
that volume is mounted over the recording's directory. With
selinux_relabel the job's directories are relabelled for this
container alone (:Z), which an SELinux-enforcing host needs before a
confined container may read or write them; elsewhere it changes nothing.
With command, the image's entrypoint gets those arguments in place of
the manifest's path, under the same sandbox: a runner's ingest runs its
own image so. It cannot be combined with wrap.
read_peak(path)
¶
Read the peak a wrapped run left behind, and remove the file.
Returns:
| Type | Description |
|---|---|
int | None
|
The peak in bytes (or None), the cgroup file it came from, and why it |
str
|
is missing when it is. |