Documentation
¶
Index ¶
- Constants
- func BuildTagFor(dockerfile string, contextHashes []string) string
- func IsLocalOnlyImageRef(imageRef string) bool
- func WithSandboxID(parent context.Context, sandboxID string) context.Context
- type BuildImageRequest
- type BuiltImage
- type Client
- func (c *Client) ApplyNetworkBlockAll(containerIP string) error
- func (c *Client) ApplyNetworkBlockIngress(containerIP string) error
- func (c *Client) BuildImage(ctx context.Context, req BuildImageRequest) error
- func (c *Client) ClearNetworkBlockEgress(containerIP string) error
- func (c *Client) ClearNetworkBlockIngress(containerIP string) error
- func (c *Client) ClearNetworkRules(containerIP string) error
- func (c *Client) ConfigureMirror(cfg MirrorConfig, ring *secrets.UpstreamWrapKeyRing)
- func (c *Client) ContainerPID(ctx context.Context, containerRef string) (int, error)
- func (c *Client) Create(ctx context.Context, req models.CreateSandboxRequest, sandboxID string, ...) (*SandboxRuntime, error)
- func (c *Client) CreateSnapshot(ctx context.Context, containerRef, imageRef string) (string, error)
- func (c *Client) Destroy(ctx context.Context, sandbox *models.Sandbox) error
- func (c *Client) ExecCreate(ctx context.Context, containerID string, cmd []string, env []string, ...) (string, error)
- func (c *Client) ExecInspect(ctx context.Context, execID string) (exitCode int, running bool, err error)
- func (c *Client) ExecResize(ctx context.Context, execID string, height, width int) error
- func (c *Client) ExecStart(ctx context.Context, execID string, tty bool) (*ExecSession, error)
- func (c *Client) ImageExists(ctx context.Context, imageRef string) (bool, error)
- func (c *Client) Inspect(ctx context.Context, containerRef string) (*SandboxRuntime, error)
- func (c *Client) ListBuiltImages(ctx context.Context) ([]BuiltImage, error)
- func (c *Client) ListManaged(ctx context.Context) (map[string]*SandboxRuntime, error)
- func (c *Client) Ping(ctx context.Context) error
- func (c *Client) PushAllowedPorts(ctx context.Context, containerIP, toolboxToken string, ports []int) error
- func (c *Client) PushImage(ctx context.Context, req PushImageRequest) (string, error)
- func (c *Client) RefreshTag(ctx context.Context, fullRef string) error
- func (c *Client) RemoveImage(ctx context.Context, imageRef string) error
- func (c *Client) Resize(ctx context.Context, containerRef string, req models.ResizeSandboxRequest) error
- func (c *Client) SetPullObserver(obs PullObserver)
- func (c *Client) Start(ctx context.Context, containerRef string) (*SandboxRuntime, error)
- func (c *Client) Stop(ctx context.Context, containerRef string) error
- func (c *Client) StreamEvents(ctx context.Context, out chan<- DockerEvent) error
- type DockerEvent
- type ExecSession
- type MirrorConfig
- type MirrorRewrite
- type MirrorUpstream
- type PullObserver
- type PushImageRequest
- type SandboxRuntime
Constants ¶
const BuiltImageNamespace = "aerolvm-build"
BuiltImageNamespace is the local image-name prefix every Daytona-facade build is tagged with. Keeping every built image under a single namespace makes them trivially identifiable by image GC (pkg/docker/image_gc.go) and keeps them out of the way of pulled images.
Variables ¶
This section is empty.
Functions ¶
func BuildTagFor ¶ added in v0.1.7
BuildTagFor returns the deterministic local image tag for a given Dockerfile + optional context hash list. Same input → same tag → docker build is a no-op on the second call, which is what makes the createImage path idempotent under retries.
func IsLocalOnlyImageRef ¶ added in v0.2.1
func WithSandboxID ¶ added in v0.2.3
WithSandboxID returns a context derived from parent that carries the sandbox identifier the pull is being executed on behalf of. Used by the Create path so the PullObserver fired after a successful private mirror pull can flag the correct row. Empty IDs are ignored.
Types ¶
type BuildImageRequest ¶ added in v0.1.7
type BuildImageRequest struct {
Tag string
DockerfileContent string
ContextTar []byte
OnLog func(line string)
}
BuildImageRequest is the input to (*Client).BuildImage.
DockerfileContent is mandatory. ContextTar is optional — when nil, the build context contains just the Dockerfile. Tag is the image name to tag the result with; it should already be qualified (e.g. registry/name:tag) if the caller intends to push it.
type BuiltImage ¶ added in v0.1.7
type BuiltImage struct {
// Tag is one of the image's RepoTags, qualified (e.g.
// "aerolvm-build/abc123:latest").
Tag string
// LastTagTime is when the daemon last (re)tagged the image, UTC. Used
// instead of Image.Created because content-addressed builds can hit the
// docker layer cache and return an image whose Created timestamp is
// arbitrarily old. The tag itself, in contrast, is fresh: every
// successful BuildImage with t=<tag> bumps LastTagTime to "now", and
// callers that only had a cache-hit explicitly call RefreshTag below.
LastTagTime time.Time
}
BuiltImage is the slice of Docker's image-list payload that the built-image janitor needs: one of the locally-built image's RepoTags (always in the BuiltImageNamespace) plus when the daemon last (re)tagged it. Multiple RepoTags per image are possible if the same content was tagged twice; we surface each tag as its own BuiltImage so the GC decision is per-tag.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
func (*Client) ApplyNetworkBlockAll ¶ added in v0.1.5
ApplyNetworkBlockAll installs the per-IP egress DROP rule. Idempotent — the underlying rule manager checks for an existing match before inserting. Called on Create (initial install), StartSandbox (after a Stop+Start cycle drops the rule on the stop event), and reconcile (to heal after host-side state loss).
func (*Client) ApplyNetworkBlockIngress ¶ added in v0.1.7
ApplyNetworkBlockIngress installs the per-IP ingress DROP rule used by the network-quota enforcer when net_bytes_in_limit is crossed. Idempotent.
func (*Client) BuildImage ¶ added in v0.1.7
func (c *Client) BuildImage(ctx context.Context, req BuildImageRequest) error
BuildImage drives `POST /build` against the local Docker daemon and tags the resulting image with req.Tag. Streams build progress as NDJSON; if req.OnLog is set, each `stream` chunk is forwarded line-by-line.
Idempotent: tagging the same Dockerfile content+context twice with the same tag is a no-op for the daemon — it returns the cached image hash.
func (*Client) ClearNetworkBlockEgress ¶ added in v0.1.7
ClearNetworkBlockEgress removes the per-IP egress DROP rule. Symmetric to ApplyNetworkBlockAll. The underlying rule is shared with NetworkBlockAll, so the service must consult sandbox.NetworkBlockAll before invoking this on a quota-clear path — otherwise it would silently undo the operator's egress block.
func (*Client) ClearNetworkBlockIngress ¶ added in v0.1.7
ClearNetworkBlockIngress removes the per-IP ingress DROP rule. Service layer only calls this when the inbound limit is raised above current usage.
func (*Client) ClearNetworkRules ¶
ClearNetworkRules releases any per-IP network rules previously attached to a sandbox. Used by the event-driven path when a container exits or is destroyed out-of-band, since Destroy() handles this for us during normal teardown. Clears both egress (NetworkBlockAll / quota egress) and ingress (quota ingress) rules — once the IP is gone there is nothing left to firewall on.
func (*Client) ConfigureMirror ¶ added in v0.2.3
func (c *Client) ConfigureMirror(cfg MirrorConfig, ring *secrets.UpstreamWrapKeyRing)
ConfigureMirror installs the AOCR mirror policy onto an existing Client. Both arguments are optional: a zero MirrorConfig disables rewriting, and a nil key ring disables identity-token wrapping (the pull falls back to raw username/password in X-Registry-Auth). main() is expected to load the wrap key ring exactly once at startup and hand it in here.
func (*Client) ContainerPID ¶ added in v0.1.7
ContainerPID returns the host PID of a running container's init process. The PID is the entry point into the container's network namespace — /proc/<pid>/net/dev is per-netns, so the netstats poller reads byte counters straight from there with no nsenter / veth-iflink dance. Returns 0 when the container is not running (Docker reports Pid:0 in that case).
func (*Client) Create ¶
func (c *Client) Create(ctx context.Context, req models.CreateSandboxRequest, sandboxID string, toolboxToken string, hostMounts []mounts.ContainerBind) (*SandboxRuntime, error)
Create provisions and starts a managed container. The caller chooses the sandbox ID up-front; we set it as the container's Docker name so the name is the canonical sandbox identifier end-to-end (the container ID is an internal detail). Host-side mounts are passed as bind sources prepared by the mounts manager; sandboxd never writes a mounts.json into the container.
func (*Client) CreateSnapshot ¶ added in v0.1.7
func (*Client) ExecCreate ¶
func (c *Client) ExecCreate(ctx context.Context, containerID string, cmd []string, env []string, workdir string, tty bool) (string, error)
ExecCreate creates an exec instance attached to the given container. The returned exec ID must be passed to ExecStart to actually run the command.
func (*Client) ExecInspect ¶
func (c *Client) ExecInspect(ctx context.Context, execID string) (exitCode int, running bool, err error)
ExecInspect returns the exit code and running state of an exec instance. Call this after the hijacked stream closes to learn the process exit code.
func (*Client) ExecResize ¶
ExecResize forwards a window-resize event to a running PTY exec.
func (*Client) ExecStart ¶
ExecStart starts a previously-created exec and hijacks the connection so the caller can pipe stdin/stdout directly. The returned ExecSession owns the underlying net.Conn — close it when done.
func (*Client) ImageExists ¶ added in v0.1.7
ImageExists reports whether the named image already exists in the local daemon. Used by the daytona facade to short-circuit redundant builds.
func (*Client) ListBuiltImages ¶ added in v0.1.7
func (c *Client) ListBuiltImages(ctx context.Context) ([]BuiltImage, error)
ListBuiltImages returns every locally-built image (tags in BuiltImageNamespace) the daemon currently holds. The janitor uses this to find candidates for unreferenced-and-old removal.
We filter server-side by reference so the API call only returns matching images — much cheaper than pulling the whole image list and filtering client-side on a daemon that may hold hundreds of base images. Each candidate is then individually inspected to read Metadata.LastTagTime, which the cheaper /images/json list endpoint does not return.
func (*Client) ListManaged ¶
func (*Client) PushAllowedPorts ¶
func (c *Client) PushAllowedPorts(ctx context.Context, containerIP, toolboxToken string, ports []int) error
PushAllowedPorts updates the toolbox's in-memory allowlist of ports that /proxy/<port>/... is permitted to reach. The list should match the sandbox's currently exposed ports. Best-effort: callers log on failure.
func (*Client) PushImage ¶ added in v0.1.7
PushImage tags SourceTag as DestRef and pushes the result to the destination registry. Returns the canonical "repo:tag" that was pushed.
Credentials are passed through per-call via X-Registry-Auth; nothing is written to the daemon's auth config and nothing is logged. The local SourceTag is preserved after a successful push so a follow-up sandbox create still hits the local fast path.
func (*Client) RefreshTag ¶ added in v0.1.7
RefreshTag re-applies an image's existing repo:tag, which causes the daemon to bump Metadata.LastTagTime to "now". The built-image janitor uses LastTagTime as the "this tag was used recently, don't GC it" signal, so callers that hand out a cached tag (without running BuildImage) must call this to keep the GC clock from running on a tag that's actively in use. Idempotent and cheap — Docker treats re-tagging an existing tag as a no-op aside from the metadata bump.
func (*Client) RemoveImage ¶
RemoveImage deletes an image from the local Docker daemon by reference (name:tag or digest). 404 (already gone) and 409 (still in use) are treated as success: the goal is "image is no longer occupying disk on our account", and a 409 means another container raced ahead and started using the image between the caller's eligibility check and this call — leaving it is correct, not an error. Other failures are returned for the caller to log.
func (*Client) SetPullObserver ¶ added in v0.2.3
func (c *Client) SetPullObserver(obs PullObserver)
SetPullObserver installs a single observer. Calling again replaces the previous one. Pass nil to disable. main() is expected to set this once at startup to wire the post-pull AutoImportPending flag.
func (*Client) StreamEvents ¶
func (c *Client) StreamEvents(ctx context.Context, out chan<- DockerEvent) error
StreamEvents subscribes to Docker's /events feed for managed containers and pushes normalized events to out. It blocks until ctx is cancelled or the stream errors. Callers are expected to reconnect on error.
type DockerEvent ¶
type DockerEvent struct {
ContainerID string
SandboxID string
Action string // "die", "destroy", "oom", "start", "stop"
ExitCode int // populated on "die" when reported by Docker
Time time.Time
}
DockerEvent is a normalized container lifecycle event from the Docker engine, scoped to containers carrying our managed label.
type ExecSession ¶
ExecSession is a hijacked Docker exec stream. With Tty=true the byte stream is unframed (raw); with Tty=false it follows Docker's stdin/stdout/stderr multiplexing. The SSH gateway only uses Tty=true for shells and Tty=false for one-shot exec, where stderr framing isn't decoded — stdout+stderr both reach the SSH client through the merged stream as the SSH side expects.
func (*ExecSession) Close ¶
func (e *ExecSession) Close() error
Close releases the hijacked connection. Idempotent.
type MirrorConfig ¶ added in v0.2.3
type MirrorConfig struct {
Host string
PushHost string
Upstreams []MirrorUpstream
}
MirrorConfig is the per-node mirror policy. A zero value disables all rewriting — pullImage behaves exactly as it did before. This is the safety hatch for any node that isn't running with AOCR mirror enabled.
`Host` is the mirror vhost (e.g. `mirror.aocr.aerol.ai`). `PushHost` is the AOCR push vhost (e.g. `aocr.aerol.ai`); we recognize both so already-rewritten refs and cluster-snapshot refs pass through unchanged — important on the failover path where a sandbox's stored `RegistryRef` may already point at the AOCR side.
func (MirrorConfig) Enabled ¶ added in v0.2.3
func (c MirrorConfig) Enabled() bool
Enabled reports whether mirror rewriting is active. Returns false for any zero/empty config so callers can short-circuit without parsing.
type MirrorRewrite ¶ added in v0.2.3
type MirrorRewrite struct {
// RewrittenRef is what should actually be pulled. When Rewritten=false
// this equals the original input.
RewrittenRef string
// OriginalRef is the user-visible ref (what to store on the sandbox
// row for trace/display). Always equals the input.
OriginalRef string
// Rewritten=true means the ref was redirected to the mirror.
Rewritten bool
// UpstreamHost / UpstreamRepo / UpstreamTag are the components AOCR's
// auth service needs to validate a wrapped credential and probe the
// upstream. They are populated only when Rewritten=true.
UpstreamHost string
// UpstreamRepo is the *mirror-side* repo path, e.g.
// `aocr/ghcr/aerol-ai/sandbox` — this matches the Distribution scope
// string AOCR's `route.ts` parses. For Docker Hub passthrough or
// non-rewritten refs this is empty.
UpstreamRepo string
UpstreamTag string
}
MirrorRewrite is the structured result of `RewriteImageRefForMirror`. All fields are populated even when no rewrite happened so the caller has a single value to plumb through (no nil checks).
func RewriteImageRefForMirror ¶ added in v0.2.3
func RewriteImageRefForMirror(ref string, cfg MirrorConfig) MirrorRewrite
RewriteImageRefForMirror is a pure function: no I/O, no globals. It inspects an image reference and decides whether to redirect it through the AOCR mirror vhost.
Rules (in order):
- Empty / unparseable refs are passed through.
- Refs that already point at the mirror or push vhost are passed through (idempotency — re-running a rewrite is a no-op).
- Refs whose host matches a configured `MirrorUpstream.Host` are rewritten to `<mirrorHost>/aocr/<short>/<repo>:<tag>`.
- Docker Hub refs (host=docker.io, or no host prefix at all) pass through — the Docker daemon handles them via `registry-mirrors`.
- Refs with an unknown host pass through, so private registries the operator didn't configure as mirror upstreams keep working.
type MirrorUpstream ¶ added in v0.2.3
MirrorUpstream maps an upstream registry host to the short prefix the AOCR mirror uses to disambiguate it in its URL path.
Example: `{Host: "ghcr.io", Shortname: "ghcr"}` causes `ghcr.io/aerol-ai/sandbox:v1` to be rewritten to `mirror.aocr.aerol.ai/aocr/ghcr/aerol-ai/sandbox:v1`. The `aocr/` prefix is a reserved namespace owned by the AOCR mirror; AOCR's auth route helper (`auth/src/upstreamAuth/route.ts`) strips `aocr/<short>/` back off when routing scope strings to the upstream probe.
Why `aocr` and not `_`: Docker's reference grammar (distribution/reference) requires each path component to match `[a-z0-9]+([._-][a-z0-9]+)*`. The bare `_` segment that early drafts of the mirror used is NOT a valid component, and Docker daemon rejects refs like `mirror.aocr.aerol.ai/_/ghcr/...` with "invalid reference format" before they ever leave the client.
Docker Hub is intentionally absent from this list: it's handled by the Docker daemon's `registry-mirrors` daemon.json setting (which only supports DockerHub), not by client-side rewriting. Refs that resolve to `docker.io` pass through unchanged here.
type PullObserver ¶ added in v0.2.3
PullObserver is invoked exactly once per successful pull that BOTH went through a mirror rewrite AND used non-anonymous upstream credentials — the precondition for the F21 auto-import flow. The sandboxID is whatever the caller stashed on the context with WithSandboxID; empty IDs skip the observer call (no row to flag).
Errors inside the observer are the caller's problem: pullImage does not surface them, so the observer must not panic and should handle its own retry/logging. The observer runs synchronously on the pull goroutine; keep it fast.
type PushImageRequest ¶ added in v0.1.7
type PushImageRequest struct {
SourceTag string
DestRef string
Auth models.RegistryAuth
OnLog func(line string)
// OnDigest is invoked once with the manifest digest the registry
// returned for the pushed tag (e.g. "sha256:abc..."), if the daemon
// surfaced one in the push stream's `aux` payload. Optional —
// callers that don't care about the digest can leave it nil.
OnDigest func(digest string)
}
PushImageRequest is the input to (*Client).PushImage. SourceTag is the local image (typically an aerolvm-build/<sha>:latest tag returned by BuildImage). DestRef is the fully-qualified destination, e.g. "ghcr.io/my-org/my-image:v1.2.3"; if no ":tag" is present, "latest" is used. Auth is request-scoped credentials — they are sent to the daemon as a one-shot X-Registry-Auth header and never persisted.
type SandboxRuntime ¶
type SandboxRuntime = models.SandboxRuntimeState
SandboxRuntime is the Docker-layer alias of the canonical models.SandboxRuntimeState type. The alias keeps every existing reference in pkg/docker compiling unchanged while letting non-Docker runtime implementations import only pkg/models.