Documentation
¶
Overview ¶
Package dockerruntime is the single Docker runtime adapter (PRD §18.1, ADR-004, ADR-051): every Docker Engine API call AkerDock makes — from the control plane's jobs and handlers or from the server agent — goes through the Runtime interface. Business logic never talks to a transport, a shell or the SDK client directly, so where an operation executes (the agent's local socket today, the typed command channel of ADR-052 tomorrow) is decided entirely by which implementation a caller is handed (ADR-001).
The method set is the strict subset of the Engine API the codebase uses. Deliberately absent: ImageBuild — build contexts live on the target server (git clone on the host), so builds are driven server-side (BuildKit via the agent, ADR-051 §scope) and never through this interface.
Index ¶
- Constants
- func CPUPercent(s container.StatsResponse) *float64
- func Demux(r io.Reader, tty bool, onOutput func(string)) error
- func IsConflict(err error) bool
- func IsNotFound(err error) bool
- func IsNotModified(err error) bool
- func IsUnavailable(err error) bool
- func MemoryUsage(s container.StatsResponse) (used, limit *int64, percent *float64)
- type AttachStream
- type CommandSender
- type Hijacker
- type Local
- type Runtime
- type Source
Constants ¶
const DefaultSocket = "/var/run/docker.sock"
DefaultSocket is the local Docker Engine API socket (ADR-004: standalone Docker is the only runtime).
Variables ¶
This section is empty.
Functions ¶
func CPUPercent ¶
func CPUPercent(s container.StatsResponse) *float64
CPUPercent computes the CPU column from the sample and its precpu predecessor. It needs a stream=false snapshot: one-shot stats leave precpu_stats empty and the delta is incomputable.
func Demux ¶
Demux copies a Docker log/attach stream to onOutput until EOF. The Engine multiplexes stdout and stderr with an 8-byte frame header unless the container has a TTY; tty says which framing r carries. Chunks are forwarded in arrival order, merged into one stream — the contract sshexec.RunStream gives job code today, so migrated call sites keep their onOutput callbacks unchanged.
func IsConflict ¶
IsConflict reports a state conflict — name already taken, container not stopped before removal, network still in use.
func IsNotFound ¶
IsNotFound reports the daemon's "no such object" answer — the API equivalent of the CLI's "No such container/volume/network". Removal and inspection paths treat it as "nothing to do", the way `|| true` did.
func IsNotModified ¶
IsNotModified reports the daemon's 304 — start of an already-running or stop of an already-stopped container. The SDK swallows most of these as success; the predicate exists for the paths where it surfaces.
func IsUnavailable ¶
IsUnavailable reports the mandatory-agent failure mode (ADR-051): the server's command channel is not there. The remedy is the agent's reconciliation, never a fallback.
func MemoryUsage ¶
func MemoryUsage(s container.StatsResponse) (used, limit *int64, percent *float64)
MemoryUsage computes used/limit/percent. Used excludes the reclaimable page cache, like the CLI: inactive_file on cgroup v2, total_inactive_file on v1.
Types ¶
type AttachStream ¶
type AttachStream interface {
io.ReadWriteCloser
CloseWrite() error
}
AttachStream is the bidirectional stream of an attached exec: reads carry its output, writes its stdin, CloseWrite ends the stdin without ending the output.
type CommandSender ¶
type CommandSender interface {
Command(ctx context.Context, method string, params any) (json.RawMessage, error)
Stream(ctx context.Context, method string, params any) (io.ReadCloser, error)
Attach(ctx context.Context, method string, params any) (AttachStream, error)
}
CommandSender is the control-plane handle on one server's agent channel (ADR-052): it carries a typed command and returns its result, opens the command's output stream, or attaches to the one bidirectional command. internal/handlers implements it on the live WebSocket; this package never sees the transport.
type Hijacker ¶
type Hijacker interface {
DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error)
}
Hijacker is the raw connection upgrade the SDK client exposes — the rail the agent's BuildKit session rides (ADR-055 phase 2: /grpc for the build gRPC, /session for the attachables). Only the LOCAL implementation has it; a remote runtime deliberately does not — builds execute where the context lives, never across the channel.
type Local ¶
Local is the Runtime served by the official SDK client over a local unix socket — the implementation the agent (and the waker) runs against /var/run/docker.sock. Remote execution reaches this same implementation through the typed command channel (ADR-052).
func NewLocal ¶
NewLocal builds a Runtime over the unix socket (DefaultSocket when empty). apiVersion optionally pins the Engine API version (e.g. "1.45"); empty — the default — negotiates with the daemon, so a client newer than the daemon still works. Pinning a version newer than the daemon supports makes every call fail ("client version too new"), so we do not pin by default.
type Runtime ¶
type Runtime interface {
// Containers.
ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error)
ContainerStart(ctx context.Context, container string, options container.StartOptions) error
ContainerStop(ctx context.Context, container string, options container.StopOptions) error
ContainerRestart(ctx context.Context, container string, options container.StopOptions) error
ContainerRename(ctx context.Context, container, newContainerName string) error
ContainerRemove(ctx context.Context, container string, options container.RemoveOptions) error
ContainerInspect(ctx context.Context, container string) (container.InspectResponse, error)
ContainerWait(ctx context.Context, container string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error)
ContainerList(ctx context.Context, options container.ListOptions) ([]container.Summary, error)
ContainerLogs(ctx context.Context, container string, options container.LogsOptions) (io.ReadCloser, error)
// ContainerStats with stream=false is the metrics snapshot: unlike the
// one-shot variant, it fills precpu_stats, without which CPU% cannot be
// computed (ADR-034). stream=true is not carried by the agent channel.
ContainerStats(ctx context.Context, container string, stream bool) (container.StatsResponseReader, error)
ContainersPrune(ctx context.Context, pruneFilters filters.Args) (container.PruneReport, error)
// Exec — one-shot (ContainerExecStart) and attached/interactive
// (ContainerExecAttach returns the hijacked bidirectional stream; resize
// serves the container terminal's PTY).
ContainerExecCreate(ctx context.Context, container string, options container.ExecOptions) (container.ExecCreateResponse, error)
ContainerExecStart(ctx context.Context, execID string, options container.ExecStartOptions) error
ContainerExecAttach(ctx context.Context, execID string, options container.ExecAttachOptions) (types.HijackedResponse, error)
ContainerExecInspect(ctx context.Context, execID string) (container.ExecInspect, error)
ContainerExecResize(ctx context.Context, execID string, options container.ResizeOptions) error
// Images. Pull/push authenticate per request (options.RegistryAuth) —
// nothing is persisted in the host's docker config for API-path
// operations, unlike the CLI login/logout dance.
ImagePull(ctx context.Context, ref string, options image.PullOptions) (io.ReadCloser, error)
ImagePush(ctx context.Context, ref string, options image.PushOptions) (io.ReadCloser, error)
ImageTag(ctx context.Context, image, ref string) error
ImageInspect(ctx context.Context, image string, options ...client.ImageInspectOption) (image.InspectResponse, error)
ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error)
ImageRemove(ctx context.Context, image string, options image.RemoveOptions) ([]image.DeleteResponse, error)
ImagesPrune(ctx context.Context, pruneFilter filters.Args) (image.PruneReport, error)
// Volumes.
VolumeCreate(ctx context.Context, options volume.CreateOptions) (volume.Volume, error)
VolumeInspect(ctx context.Context, volumeID string) (volume.Volume, error)
VolumeList(ctx context.Context, options volume.ListOptions) (volume.ListResponse, error)
VolumeRemove(ctx context.Context, volumeID string, force bool) error
VolumesPrune(ctx context.Context, pruneFilter filters.Args) (volume.PruneReport, error)
// Networks.
NetworkCreate(ctx context.Context, name string, options network.CreateOptions) (network.CreateResponse, error)
NetworkConnect(ctx context.Context, network, container string, config *network.EndpointSettings) error
NetworkDisconnect(ctx context.Context, network, container string, force bool) error
NetworkInspect(ctx context.Context, network string, options network.InspectOptions) (network.Inspect, error)
NetworkList(ctx context.Context, options network.ListOptions) ([]network.Summary, error)
NetworkRemove(ctx context.Context, network string) error
NetworksPrune(ctx context.Context, pruneFilter filters.Args) (network.PruneReport, error)
// System.
Events(ctx context.Context, options events.ListOptions) (<-chan events.Message, <-chan error)
Info(ctx context.Context) (system.Info, error)
ServerVersion(ctx context.Context) (types.Version, error)
DiskUsage(ctx context.Context, options types.DiskUsageOptions) (types.DiskUsage, error)
RegistryLogin(ctx context.Context, auth registry.AuthConfig) (registry.AuthenticateOKBody, error)
Ping(ctx context.Context) (types.Ping, error)
Close() error
}
Runtime is the Engine API surface AkerDock relies on. Signatures mirror the official SDK client verbatim so the local implementation is the SDK itself and a typed command frame (ADR-052) maps 1:1 onto a method — the SDK types ARE the Engine API wire types.
Error discipline: implementations surface the SDK's typed errors; callers branch with IsNotFound/IsConflict/IsNotModified from this package, never by matching message text. Streaming returns (io.ReadCloser, hijacked connections, channels) are bounded by the caller's ctx — implementations must not impose a global timeout, which would kill a follow stream mid-flight.
func NewAgentRuntime ¶
func NewAgentRuntime(s CommandSender) Runtime
NewAgentRuntime returns the Runtime that executes every call as a typed command on the server's agent channel. The agent is mandatory (ADR-051): there is no fallback below this — a dead channel surfaces as an IsUnavailable error and the caller's remedy is repairing the agent.