Skip to content

ContainerImpl

Defined in: packages/runtime/src/container/container.ts:140

Concrete implementation of Container (and the internal ContainerInspectable).

Owns one kernel-per-container (Decision #10) and enforces the lifecycle state machine from state-machine.ts. Rarely constructed directly — callers obtain instances via ContainerRuntime.create or ContainerManager.create.

Internals exposed via ContainerInspectable (env(), namespaceMounts(), pid1(), exitContext(), log/cons subscriptions) are consumed by containerFS to surface /dev/container/* views — not part of the public API.

  • ContainerInspectable

new ContainerImpl(spec, caps, tty?, logBufferSize?, hooks?, containerId?): ContainerImpl

Defined in: packages/runtime/src/container/container.ts:168

ContainerSpec

PlatformCapabilities

TtyConfig

number

ContainerHooks

number = 0

ContainerImpl

readonly containerId: number

Defined in: packages/runtime/src/container/container.ts:144

Synthetic container ID assigned by ContainerManager.

ContainerInspectable.containerId


readonly createdAt: number

Defined in: packages/runtime/src/container/container.ts:143

Timestamp (ms since epoch) when the container was created.

ContainerInspectable.createdAt


readonly name: string

Defined in: packages/runtime/src/container/container.ts:141

Container name — unique within the manager registry.

ContainerInspectable.name


readonly spec: ContainerSpec

Defined in: packages/runtime/src/container/container.ts:142

The spec this container was created from. Frozen.

ContainerInspectable.spec

get exitCode(): ExitCode | undefined

Defined in: packages/runtime/src/container/container.ts:189

PID-1 exit code. undefined until PID 1 exits.

ExitCode | undefined

ContainerInspectable.exitCode


get state(): ContainerState

Defined in: packages/runtime/src/container/container.ts:188

Current lifecycle state. Snapshot — may change concurrently with async ops.

ContainerState

ContainerInspectable.state

[asyncDispose](): Promise<void>

Defined in: packages/runtime/src/container/container.ts:861

Promise<void>

ContainerInspectable.[asyncDispose]


appendLog(msg): void

Defined in: packages/runtime/src/container/container.ts:760

Append a line to the container’s log buffer (used by health runner).

string

void


commit(): Promise<Layer>

Defined in: packages/runtime/src/container/container.ts:675

Freeze the writable upper layer, store it, and swap in a fresh upper.

Docker-commit semantics while the container stays running: the current writable upper becomes an immutable Layer on top of the parent’s layer stack, then a new empty upper takes its place. Subsequent writes accumulate in the new upper; previous writes are preserved as a reusable layer in the layer store.

Promise<Layer>

the newly created Layer (also stored in layerStore).

ContainerStateError if not running, if the namespace isn’t built, or if the image didn’t provide a layer store.

ContainerInspectable.commit


consSubscribeRaw(): LogSubscription

Defined in: packages/runtime/src/container/container.ts:840

Subscribe to raw output lines (unformatted, for cons reads).

LogSubscription

ContainerInspectable.consSubscribeRaw


consWrite(data): Promise<number>

Defined in: packages/runtime/src/container/container.ts:845

Write to child’s stdin (cons bridge). Throws ENOTCONN if not running.

Uint8Array

Promise<number>

ContainerInspectable.consWrite


drain(timeout?): Promise<void>

Defined in: packages/runtime/src/container/container.ts:488

Send SIGUSR1 for in-process drain, then force-kill on timeout.

Contract with PID 1: SIGUSR1 is the agreed “finish current work then exit” signal (not SIGTERM — which is shutdown-now semantics). If PID 1 doesn’t exit within timeout we escalate to _shutdown(0) (immediate SIGKILL) to guarantee forward progress.

number = 5000

Promise<void>

ContainerInspectable.drain


env(): Readonly<Record<string, string>>

Defined in: packages/runtime/src/container/container.ts:800

Merged env from namespace construction. Empty record if not yet started.

Readonly<Record<string, string>>

ContainerInspectable.env


exec(bin, argv?, opts?): Promise<ExitCode>

Defined in: packages/runtime/src/container/container.ts:572

Run a one-shot process inside the running container, teeing output into the container log buffer.

Env composition: container’s merged env (built at start()) then opts.env overrides — callers can inject one-off vars (e.g. DEBUG=1) without mutating the container’s base env. TTY handling (opts.tty === true) toggles raw mode on /dev/cons via the ctl file; see the inline comment at the ctl write for why this lives here and not in the exec’d bin.

string

string[]

ExecOpts

Promise<ExitCode>

ContainerInspectable.exec


execHealthProbe(check): Promise<number>

Defined in: packages/runtime/src/container/container.ts:773

Execute a health probe — spawn the cmd inside the container, return exit code.

Defensive: every abnormal path (non-cmd check, empty cmd, not-running, spawn failure) returns 1 to match shell failure convention, so the health runner can key off exit-code alone without special-casing “probe couldn’t run” versus “probe said unhealthy”. Discrimination between the two belongs in log lines, not the return channel.

HealthCheck

Promise<number>


exitContext(): ContainerExitContext | undefined

Defined in: packages/runtime/src/container/container.ts:818

Structured exit context. undefined while running.

ContainerExitContext | undefined

ContainerInspectable.exitContext


getNamespace(): Namespace | undefined

Defined in: packages/runtime/src/container/container.ts:826

Live Namespace object. undefined when container not started or stopped. Used by nsenter.

Namespace | undefined

ContainerInspectable.getNamespace


kill(): Promise<void>

Defined in: packages/runtime/src/container/container.ts:466

Immediate SIGKILL to PID 1 and all descendants. No grace period.

Promise<void>

Valid from running or draining.

ContainerInspectable.kill


logs(): string

Defined in: packages/runtime/src/container/container.ts:751

Snapshot of the container’s merged stdout/stderr log buffer.

string

ContainerInspectable.logs


logSubscribe(): LogSubscription

Defined in: packages/runtime/src/container/container.ts:835

Subscribe to formatted log lines (new lines only).

LogSubscription

ContainerInspectable.logSubscribe


namespaceMounts(): ReadonlyMap<string, string>

Defined in: packages/runtime/src/container/container.ts:804

Mount table: path → fileserver type name. Empty map if not yet started.

ReadonlyMap<string, string>

ContainerInspectable.namespaceMounts


pid1(): number | undefined

Defined in: packages/runtime/src/container/container.ts:814

PID of process 1 — persists after exit for audit/log correlation.

number | undefined

ContainerInspectable.pid1


remove(): void

Defined in: packages/runtime/src/container/container.ts:548

Dispose namespace resources and log buffer; transitions to removed.

void

Not valid while running or draining — stop first.

Idempotent on removed.

ContainerInspectable.remove


restart(): Promise<void>

Defined in: packages/runtime/src/container/container.ts:534

Stop (if running) then start — used by restart policies and user verbs.

The intermediate state check catches the pathological case where stop() raced something exotic (e.g. removed) — in practice very rare, but without this guard we’d call start() from an invalid state and throw a less-informative error from there.

Promise<void>

ContainerInspectable.restart


setAuditHook(hook): void

Defined in: packages/runtime/src/container/container.ts:192

Set the audit hook before start(). Called by ContainerManager when —audit=on.

AuditHookFn | undefined

void


start(): Promise<void>

Defined in: packages/runtime/src/container/container.ts:218

Build the namespace, construct a fresh kernel, mount consFS, and spawn PID 1.

Handles both first-start (from created) and restart (from stopped / failed) — the restart path disposes the previous namespace and resets per-run state but deliberately preserves the log buffer (see file header). On failure anywhere past namespace build, the error message is written into the log buffer before re-throwing so post-mortem tooling can read it.

Internally split into three phases for readability: _preflightStart (state + spec + namespace + kernel + tty validation + cons mount), _bootContainer (PID-1 spawn + resource-limit guard), and _postflightStart (field commit + state transition + exit handler).

Promise<void>

ContainerStateError from an illegal starting state, when the spec omits namespace.image, when the image is a manifest (M2 NYI), or when devices.tty === 'inherit' with no tty provided.

ContainerInspectable.start


stop(timeout?): Promise<void>

Defined in: packages/runtime/src/container/container.ts:449

Graceful shutdown: SIGTERM → wait timeout ms → SIGKILL on holdouts.

Idempotent on stopped/failed so the manager’s destroy() path and user-driven stop() can interleave without extra guarding. _explicitStop is flipped before _shutdown so the exit handler doesn’t reclassify a zero-code exit as a natural stop when the caller forced it.

number = 5000

Promise<void>

ContainerInspectable.stop


wait(): Promise<ExitCode>

Defined in: packages/runtime/src/container/container.ts:737

Resolve with PID-1’s exit code.

Promise<ExitCode>

If PID 1 already exited, resolves with the cached code. If never started, throws. Otherwise waits for PID 1 to exit.

ContainerInspectable.wait