whail

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 26, 2026 License: MIT Imports: 16 Imported by: 0

README

whail

A reusable Docker engine wrapper with automatic label-based resource isolation. All operations — create, list, remove, build — are filtered through managed labels. Resources created outside whail are invisible; resources created by whail cannot escape.

Wraps github.com/moby/moby/client. No other package may import moby directly.

Quick Start

import "github.com/anthropics/clawker/pkg/whail"

engine, err := whail.New(ctx)
if err != nil {
    // Docker not running or unreachable
}

// All operations are auto-tagged and filtered
engine.ContainerCreate(ctx, opts)    // managed labels injected
engine.ContainerList(ctx, opts)      // only managed containers returned
engine.ImageBuild(ctx, reader, opts) // managed labels on image

Custom Configuration

engine, err := whail.NewWithOptions(ctx, whail.EngineOptions{
    LabelPrefix:  "com.myapp",   // Label key prefix (default: "")
    ManagedLabel: "managed",     // Managed label suffix (default: "managed")
    Labels: whail.LabelConfig{
        Default:   map[string]string{"team": "platform"},
        Container: map[string]string{"service": "api"},
        Volume:    map[string]string{"storage": "persistent"},
        Network:   map[string]string{"tier": "internal"},
        Image:     map[string]string{"build": "ci"},
    },
})

Wrapping an Existing Client

Use NewFromExisting to wrap a pre-configured moby client (useful for testing or custom transports):

engine := whail.NewFromExisting(existingClient, whail.EngineOptions{
    LabelPrefix:  "com.myapp",
    ManagedLabel: "managed",
})

Label Enforcement

Every operation automatically injects a managed label (<prefix>.<managed> = "true"). This label:

  • Cannot be overridden — even if callers pass the same key, whail forces "true"
  • Filters all reads — list, inspect, and prune operations only see managed resources
  • Rejects unmanaged access — inspecting an unmanaged resource returns "not found"

Label utility functions:

whail.MergeLabels(base, extra1, extra2)         // Merge label maps (later wins)
whail.LabelFilter("key", "value")               // Single filter map
whail.LabelFilterMultiple(filters)               // Multiple filters
whail.AddLabelFilter(existing, "key", "value")   // Append to existing
whail.MergeLabelFilters(filter1, filter2)        // Combine filter sets

BuildKit Extension

BuildKit support is isolated in a subpackage (pkg/whail/buildkit/) to avoid pulling moby/buildkit and its transitive dependencies (gRPC, protobuf, containerd, opentelemetry) into consumers who only need the core Docker wrapper.

Enabling BuildKit
import (
    "github.com/anthropics/clawker/pkg/whail"
    "github.com/anthropics/clawker/pkg/whail/buildkit"
)

engine, _ := whail.New(ctx)
engine.BuildKitImageBuilder = buildkit.NewImageBuilder(engine.APIClient)

// BuildKit builds with full label enforcement
engine.ImageBuildKit(ctx, whail.ImageBuildKitOptions{
    Tags:       []string{"myimage:latest"},
    ContextDir: "./build-context",
    Dockerfile: "Dockerfile",       // relative to ContextDir
    BuildArgs:  map[string]*string{"GO_VERSION": ptr("1.25")},
    Labels:     map[string]string{"version": "1.0"},
})

The ImageBuildKit method enforces managed labels identically to ImageBuild — labels are merged and the managed label is forced before delegating to the closure.

BuildKit Detection

Check whether the Docker daemon supports BuildKit before attempting a BuildKit build:

enabled, err := whail.BuildKitEnabled(ctx, engine.APIClient)
if err != nil {
    // Daemon unreachable
}
if enabled {
    engine.BuildKitImageBuilder = buildkit.NewImageBuilder(engine.APIClient)
}

Detection checks (in order):

  1. DOCKER_BUILDKIT env var (explicit override)
  2. Daemon ping BuilderVersion field
  3. Default: enabled on Linux/macOS, disabled on Windows/WCOW
How It Works

The buildkit subpackage connects to Docker's embedded BuildKit daemon via the /grpc and /session hijack endpoints — the same mechanism docker buildx uses internally. Builds use bkclient.Solve with the dockerfile.v0 frontend, supporting cache mounts, multi-stage targets, and all standard Dockerfile features.

ImageBuildKitOptions
Field Type Description
Tags []string Image tags (e.g., "myimage:latest")
ContextDir string Build context directory (required)
Dockerfile string Path relative to ContextDir (default: "Dockerfile")
BuildArgs map[string]*string --build-arg key=value pairs
NoCache bool Disable build cache
Labels map[string]string Image labels (managed labels auto-injected)
Target string Target build stage
Pull bool Force pulling base images
SuppressOutput bool Suppress build progress logging
NetworkMode string Network mode for RUN instructions

Error Handling

All errors are returned as *DockerError with structured fields:

type DockerError struct {
    Op        string     // Operation name (e.g., "build", "container.create")
    Err       error      // Underlying error
    Message   string     // User-friendly message
    NextSteps []string   // Remediation suggestions
}

Format for display with err.FormatUserError(). Error constructors include context-specific remediation steps — for example, ErrBuildKitNotConfigured() suggests wiring the builder closure and falling back to legacy builds.

Engine Operations

Container

ContainerCreate, ContainerStart, ContainerStop, ContainerRemove, ContainerList, ContainerListAll, ContainerListRunning, ContainerListByLabels, ContainerInspect, ContainerAttach, ContainerWait, ContainerLogs, ContainerResize, ContainerKill, ContainerPause, ContainerUnpause, ContainerRestart, ContainerRename, ContainerTop, ContainerStats, ContainerStatsOneShot, ContainerUpdate, ExecCreate, FindContainerByName, IsContainerManaged

Image

ImageBuild (legacy SDK), ImageBuildKit (BuildKit via closure), ImageRemove, ImageList, ImageInspect, ImagesPrune

Volume

VolumeCreate, VolumeRemove, VolumeInspect, VolumeExists, VolumeList, VolumeListAll, IsVolumeManaged, VolumesPrune

Network

NetworkCreate, NetworkRemove, NetworkInspect, NetworkExists, NetworkList, EnsureNetwork, IsNetworkManaged, NetworksPrune, NetworkConnect, NetworkDisconnect

Copy

CopyToContainer, CopyFromContainer, ContainerStatPath

Testing

The whailtest subpackage provides test infrastructure for whail without requiring Docker.

FakeAPIClient

Function-field test double implementing the full moby APIClient interface. Embeds a nil *client.Client — any unexpected call panics (fail-loud).

fake := whailtest.NewFakeAPIClient()
fake.ContainerStopFn = func(ctx context.Context, id string, opts container.StopOptions) error {
    return nil
}
engine := whail.NewFromExisting(fake, whailtest.TestEngineOptions())

whailtest.AssertCalled(t, fake, "ContainerStop")
whailtest.AssertNotCalled(t, fake, "ContainerRemove")
Faking BuildKit

Set the closure field directly — no interface needed:

// Inline closure
var captured whail.ImageBuildKitOptions
engine.BuildKitImageBuilder = func(_ context.Context, opts whail.ImageBuildKitOptions) error {
    captured = opts
    return nil
}

// Or use the capture helper
capture := &whailtest.BuildKitCapture{}
engine.BuildKitImageBuilder = whailtest.FakeBuildKitBuilder(capture)

engine.ImageBuildKit(ctx, opts)
assert.Equal(t, 1, capture.CallCount)
assert.Equal(t, expectedLabels, capture.Opts.Labels)

// Simulate errors
capture.Err = fmt.Errorf("build failed")
Resource Helpers
whailtest.ManagedContainerInspect(id)    // Inspect result with managed labels
whailtest.UnmanagedContainerInspect(id)  // Inspect result WITHOUT managed labels
// Also: ManagedVolumeInspect, ManagedNetworkInspect, ManagedImageInspect
// And:  UnmanagedVolumeInspect, UnmanagedNetworkInspect, UnmanagedImageInspect

Package Layout

pkg/whail/
    engine.go       Engine struct, constructors, label helpers
    image.go        ImageBuild (legacy), ImageBuildKit (BuildKit), ImageRemove, ImageList, etc.
    types.go        Re-exported Docker SDK types, ImageBuildKitOptions
    buildkit.go     BuildKitEnabled() detection (moby types only, not moby/buildkit)
    errors.go       DockerError type with 47 error constructors
    labels.go       MergeLabels, LabelFilter, filter utilities
    container.go    Container operations
    volume.go       Volume operations
    network.go      Network operations
    copy.go         CopyToContainer, CopyFromContainer
    buildkit/       Subpackage — only place that imports moby/buildkit
        builder.go  NewImageBuilder() — returns the Engine closure
        client.go   NewBuildKitClient() — connects via Docker's /grpc endpoint
        solve.go    toSolveOpt() — converts ImageBuildKitOptions to SolveOpt
        progress.go drainProgress() — logs build progress via zerolog
    whailtest/      Test infrastructure
        fake_client.go  FakeAPIClient with function-field fakes
        helpers.go      BuildKitCapture, resource fixtures, assertions

Documentation

Overview

Package whail provides a reusable Docker isolation library ("whale jail"). It wraps the Docker SDK with automatic label-based resource isolation, ensuring operations only affect resources managed by a specific application.

Package whail re-exports Docker SDK types as aliases. This allows higher-level packages to use these types without importing moby/client directly.

Index

Constants

View Source
const (
	// WaitConditionNotRunning is used to wait until a container is not running.
	WaitConditionNotRunning = container.WaitConditionNotRunning
	WaitConditionNextExit   = container.WaitConditionNextExit
	WaitConditionRemoved    = container.WaitConditionRemoved
)
View Source
const DefaultManagedLabel = "managed"

DefaultManagedLabel is the default label suffix for marking managed resources.

Variables

View Source
var ErrDockerNotAvailable = errors.New("docker not available")

ErrDockerNotAvailable is a sentinel error indicating the Docker daemon cannot be reached — either not installed or not running. Use errors.Is(err, ErrDockerNotAvailable) to detect this condition.

Functions

func AddLabelFilter

func AddLabelFilter(f client.Filters, key, value string) client.Filters

AddLabelFilter adds a label filter to an existing client.Filters. Returns a new Filters (immutable pattern).

func BuildKitEnabled

func BuildKitEnabled(ctx context.Context, p Pinger) (bool, error)

BuildKitEnabled checks whether BuildKit is available. Follows Docker CLI's detection: env var > daemon ping > OS heuristic.

func CleanStepName

func CleanStepName(name string) string

CleanStepName strips BuildKit noise from a step name for display. Removes --mount=type=cache and similar flags from RUN commands and collapses whitespace.

func FormatBuildDuration

func FormatBuildDuration(d time.Duration) string

FormatBuildDuration returns a compact duration string with sub-second precision.

func IsInternalStep

func IsInternalStep(name string) bool

IsInternalStep returns true for BuildKit housekeeping vertices that should be hidden in progress displays (load build definition, load .dockerignore, etc.).

func LabelFilter

func LabelFilter(key, value string) client.Filters

LabelFilter creates a Docker filter for a single label key=value. The key should include the prefix (e.g., "com.myapp.managed").

func LabelFilterMultiple

func LabelFilterMultiple(labels map[string]string) client.Filters

LabelFilterMultiple creates a Docker filter from multiple label key=value pairs. All labels must match (AND logic).

func MergeLabelFilters

func MergeLabelFilters(f client.Filters, labels map[string]string) client.Filters

MergeLabelFilters merges label filters into an existing client.Filters. Returns a new Filters (immutable pattern).

func MergeLabels

func MergeLabels(labelMaps ...map[string]string) map[string]string

MergeLabels merges multiple label maps, with later maps overriding earlier ones. Returns a new map containing all labels.

func ParseBuildStage

func ParseBuildStage(name string) string

ParseBuildStage extracts the build stage name from a step name like "[stage-2 3/7] RUN ...". Returns empty string if no stage bracket is found.

Types

type BuildProgressEvent

type BuildProgressEvent struct {
	// StepID uniquely identifies a build step (digest for BuildKit, "step-N" for legacy).
	StepID string

	// StepName is a human-readable label (e.g., "RUN npm install").
	StepName string

	// StepIndex is the 0-based ordinal position (-1 if unknown).
	StepIndex int

	// TotalSteps is the total number of steps (-1 if unknown).
	TotalSteps int

	// Status indicates the current state of this step.
	Status BuildStepStatus

	// LogLine contains a single output line (empty for status-only events).
	LogLine string

	// Error contains an error message (empty if no error).
	Error string

	// Cached indicates the step result was served from cache.
	Cached bool
}

BuildProgressEvent represents a single progress update from a build pipeline.

type BuildProgressFunc

type BuildProgressFunc func(event BuildProgressEvent)

BuildProgressFunc is a callback invoked by build pipelines to report step progress. Implementations must be safe for concurrent use.

type BuildStepStatus

type BuildStepStatus int

BuildStepStatus represents the state of a build step.

const (
	// BuildStepPending means the step has not started yet.
	BuildStepPending BuildStepStatus = iota

	// BuildStepRunning means the step is actively executing.
	BuildStepRunning

	// BuildStepComplete means the step finished successfully.
	BuildStepComplete

	// BuildStepCached means the step was served from cache.
	BuildStepCached

	// BuildStepError means the step failed.
	BuildStepError
)

type ContainerAttachOptions

type ContainerAttachOptions = client.ContainerAttachOptions

Container operation options. Note: ContainerCreateOptions is a custom whail struct defined in container.go. SDKContainerCreateOptions is the raw Docker SDK type for direct API calls.

type ContainerCreateOptions

type ContainerCreateOptions struct {
	// Container configuration
	Config     *container.Config
	HostConfig *container.HostConfig

	// NetworkingConfig holds container networking configuration.
	// Note: EnsureNetwork adds to this if specified.
	NetworkingConfig *network.NetworkingConfig

	// Platform specifies the platform for the container.
	Platform *ocispec.Platform

	// Name is the container name.
	Name string

	// ExtraLabels are additional labels merged with the engine's managed labels.
	ExtraLabels Labels

	// EnsureNetwork, if non-nil, ensures the named network exists (creating it
	// if necessary) and adds the container to it. The network is added in addition
	// to any networks already specified in NetworkingConfig.
	EnsureNetwork *EnsureNetworkOptions
}

ContainerCreateOptions embeds the Docker SDK's options and adds whail-specific fields. Using composition ensures forward compatibility as the SDK evolves.

type ContainerInspectOptions

type ContainerInspectOptions = client.ContainerInspectOptions

Container result types.

type ContainerInspectResult

type ContainerInspectResult = client.ContainerInspectResult

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ContainerListOptions

type ContainerListOptions = client.ContainerListOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ContainerLogsOptions

type ContainerLogsOptions = client.ContainerLogsOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ContainerRemoveOptions

type ContainerRemoveOptions = client.ContainerRemoveOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ContainerStartOptions

type ContainerStartOptions struct {
	client.ContainerStartOptions // Embedded: CheckpointID, CheckpointDir

	// ContainerID is the container ID or name (required).
	ContainerID string

	// EnsureNetwork, if non-nil, ensures the named network exists and connects
	// the container to it before starting. This is useful for connecting
	// existing containers to networks that may have been removed.
	EnsureNetwork *EnsureNetworkOptions
}

ContainerStartOptions embeds the Docker SDK's options and adds whail-specific fields.

type ContainerUpdateResult

type ContainerUpdateResult = client.ContainerUpdateResult

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type CopyFromContainerOptions

type CopyFromContainerOptions = client.CopyFromContainerOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type CopyToContainerOptions

type CopyToContainerOptions = client.CopyToContainerOptions

Copy operation options.

type DockerError

type DockerError struct {
	Op        string   // Operation that failed (e.g., "connect", "build", "run")
	Err       error    // Underlying error
	Message   string   // Human-readable message
	NextSteps []string // Suggested remediation steps
}

DockerError represents a user-friendly Docker error with remediation steps. It wraps underlying Docker SDK errors with context and actionable guidance.

func ErrAttachFailed

func ErrAttachFailed(err error) *DockerError

ErrAttachFailed returns an error for when attaching to a container fails.

func ErrBuildKitNotConfigured

func ErrBuildKitNotConfigured() *DockerError

ErrBuildKitNotConfigured returns an error when ImageBuildKit is called but no BuildKitImageBuilder closure has been set on the Engine.

func ErrContainerCreateFailed

func ErrContainerCreateFailed(err error) *DockerError

ErrContainerCreateFailed returns an error for when container creation fails.

func ErrContainerInspectFailed

func ErrContainerInspectFailed(name string, err error) *DockerError

ErrContainerInspectFailed returns an error for when container inspection fails.

func ErrContainerKillFailed

func ErrContainerKillFailed(name string, err error) *DockerError

ErrContainerKillFailed returns an error for when killing a container fails.

func ErrContainerListFailed

func ErrContainerListFailed(err error) *DockerError

ErrContainerListFailed returns an error for when listing containers fails.

func ErrContainerLogsFailed

func ErrContainerLogsFailed(name string, err error) *DockerError

ErrContainerLogsFailed returns an error for when fetching container logs fails.

func ErrContainerNotFound

func ErrContainerNotFound(name string) *DockerError

ErrContainerNotFound returns an error for when a container cannot be found.

func ErrContainerNotManaged

func ErrContainerNotManaged(name string) *DockerError

func ErrContainerPauseFailed

func ErrContainerPauseFailed(name string, err error) *DockerError

ErrContainerPauseFailed returns an error for when pausing a container fails.

func ErrContainerRemoveFailed

func ErrContainerRemoveFailed(name string, err error) *DockerError

ErrContainerRemoveFailed returns an error for when container removal fails.

func ErrContainerRenameFailed

func ErrContainerRenameFailed(name string, err error) *DockerError

ErrContainerRenameFailed returns an error for when renaming a container fails.

func ErrContainerResizeFailed

func ErrContainerResizeFailed(containerID string, err error) *DockerError

ErrContainerResizeFailed returns an error for when resizing a container TTY fails.

func ErrContainerRestartFailed

func ErrContainerRestartFailed(name string, err error) *DockerError

ErrContainerRestartFailed returns an error for when restarting a container fails.

func ErrContainerStartFailed

func ErrContainerStartFailed(name string, err error) *DockerError

ErrContainerStartFailed returns an error for when a container fails to start.

func ErrContainerStatPathFailed

func ErrContainerStatPathFailed(name string, err error) *DockerError

ErrContainerStatPathFailed returns an error for when stat'ing a path in a container fails.

func ErrContainerStatsFailed

func ErrContainerStatsFailed(name string, err error) *DockerError

ErrContainerStatsFailed returns an error for when getting container stats fails.

func ErrContainerStopFailed

func ErrContainerStopFailed(name string, err error) *DockerError

ErrContainerStopFailed returns an error for when a container fails to stop.

func ErrContainerTopFailed

func ErrContainerTopFailed(name string, err error) *DockerError

ErrContainerTopFailed returns an error for when getting container processes fails.

func ErrContainerUnpauseFailed

func ErrContainerUnpauseFailed(name string, err error) *DockerError

ErrContainerUnpauseFailed returns an error for when unpausing a container fails.

func ErrContainerUpdateFailed

func ErrContainerUpdateFailed(name string, err error) *DockerError

ErrContainerUpdateFailed returns an error for when updating container config fails.

func ErrContainerWaitFailed

func ErrContainerWaitFailed(name string, err error) *DockerError

ErrContainerWaitFailed returns an error for when waiting on a container fails.

func ErrCopyFromContainerFailed

func ErrCopyFromContainerFailed(name string, err error) *DockerError

ErrCopyFromContainerFailed returns an error for when copying from a container fails.

func ErrCopyToContainerFailed

func ErrCopyToContainerFailed(name string, err error) *DockerError

ErrCopyToContainerFailed returns an error for when copying to a container fails.

func ErrDockerHealthCheckFailed added in v0.2.1

func ErrDockerHealthCheckFailed(err error) *DockerError

ErrDockerHealthCheckFailed returns an error for when the Docker daemon health check (Ping) fails. The returned error wraps ErrDockerNotAvailable so callers can detect Docker connectivity failures via errors.Is(err, ErrDockerNotAvailable).

func ErrExecAttachFailed

func ErrExecAttachFailed(execID string, err error) *DockerError

ErrExecAttachFailed returns an error for when attaching to an exec instance fails.

func ErrExecCreateFailed

func ErrExecCreateFailed(name string, err error) *DockerError

ErrExecCreateFailed returns an error for when exec create fails.

func ErrExecStartFailed

func ErrExecStartFailed(execID string, err error) *DockerError

ErrExecStartFailed returns an error for when starting an exec instance fails.

func ErrImageBuildFailed

func ErrImageBuildFailed(err error) *DockerError

ErrImageBuildFailed returns an error for when image build fails.

func ErrImageListFailed

func ErrImageListFailed(err error) *DockerError

ErrImageListFailed returns an error for when listing images fails.

func ErrImageNotFound

func ErrImageNotFound(image string, err error) *DockerError

ErrImageNotFound returns an error for when an image cannot be found.

func ErrImageRemoveFailed

func ErrImageRemoveFailed(image string, err error) *DockerError

ErrImageRemoveFailed returns an error for when image removal fails.

func ErrImagesPruneFailed

func ErrImagesPruneFailed(err error) *DockerError

ErrImagesPruneFailed returns an error for when pruning images fails.

func ErrNetworkConnectFailed

func ErrNetworkConnectFailed(networkID, containerID string, err error) *DockerError

ErrNetworkConnectFailed returns an error for when connecting a container to a network fails.

func ErrNetworkCreateFailed

func ErrNetworkCreateFailed(name string, err error) *DockerError

ErrNetworkCreateFailed returns an error for when network creation fails.

func ErrNetworkDisconnectFailed

func ErrNetworkDisconnectFailed(networkID, containerID string, err error) *DockerError

ErrNetworkDisconnectFailed returns an error for when disconnecting a container from a network fails.

func ErrNetworkEnsureFailed

func ErrNetworkEnsureFailed(name string, err error) *DockerError

ErrNetworkEnsureFailed returns an error for when ensuring a network exists fails.

func ErrNetworkError

func ErrNetworkError(err error) *DockerError

ErrNetworkError returns an error for network-related failures.

func ErrNetworkListFailed

func ErrNetworkListFailed(err error) *DockerError

ErrNetworkListFailed returns an error for when listing networks fails.

func ErrNetworkNotFound

func ErrNetworkNotFound(name string, err error) *DockerError

func ErrNetworkRemoveFailed

func ErrNetworkRemoveFailed(name string, err error) *DockerError

ErrNetworkRemoveFailed returns an error for when network removal fails.

func ErrNetworksPruneFailed

func ErrNetworksPruneFailed(err error) *DockerError

ErrNetworksPruneFailed returns an error for when pruning networks fails.

func ErrVolumeCopyFailed

func ErrVolumeCopyFailed(err error) *DockerError

ErrVolumeCopyFailed returns an error for when copying to a volume fails.

func ErrVolumeCreateFailed

func ErrVolumeCreateFailed(name string, err error) *DockerError

ErrVolumeCreateFailed returns an error for when volume creation fails.

func ErrVolumeInspectFailed

func ErrVolumeInspectFailed(name string, err error) *DockerError

ErrVolumeInspectFailed returns an error for when volume inspection fails.

func ErrVolumeListFailed

func ErrVolumeListFailed(err error) *DockerError

ErrVolumeListFailed returns an error for when listing volumes fails.

func ErrVolumeNotFound

func ErrVolumeNotFound(name string, err error) *DockerError

ErrVolumeNotFound returns an error for when a volume cannot be found.

func ErrVolumeRemoveFailed

func ErrVolumeRemoveFailed(name string, err error) *DockerError

ErrVolumeRemoveFailed returns an error for when volume removal fails.

func ErrVolumesPruneFailed

func ErrVolumesPruneFailed(err error) *DockerError

ErrVolumesPruneFailed returns an error for when pruning volumes fails.

func (*DockerError) Error

func (e *DockerError) Error() string

func (*DockerError) FormatUserError

func (e *DockerError) FormatUserError() string

FormatUserError formats the error for display to users with next steps.

func (*DockerError) Is added in v0.2.1

func (e *DockerError) Is(target error) bool

Is supports sentinel error matching. A DockerError with Op "connect" matches ErrDockerNotAvailable, allowing errors.Is detection through any depth of fmt.Errorf wrapping without polluting the Err chain.

func (*DockerError) Unwrap

func (e *DockerError) Unwrap() error

type Engine

type Engine struct {
	// cli     *client.Client
	client.APIClient

	// BuildKitImageBuilder handles BuildKit image builds when set.
	// Label enforcement is applied by ImageBuildKit before delegating.
	// Wire via: engine.BuildKitImageBuilder = buildkit.NewImageBuilder(engine.APIClient)
	BuildKitImageBuilder func(ctx context.Context, opts ImageBuildKitOptions) error
	// contains filtered or unexported fields
}

Engine wraps the Docker client with automatic label-based resource isolation. All list operations automatically inject filters to only return resources managed by this engine (identified by the configured label prefix).

func New

func New(ctx context.Context) (*Engine, error)

New creates a new Engine with default options. The caller is responsible for calling Close() when done.

func NewFromExisting

func NewFromExisting(c client.APIClient, opts ...EngineOptions) *Engine

NewFromExisting wraps an existing APIClient (useful for testing with mocks).

func NewWithOptions

func NewWithOptions(ctx context.Context, opts EngineOptions) (*Engine, error)

NewWithOptions creates a new Engine with the given options. It connects to the Docker daemon and verifies the connection.

func (*Engine) ContainerAttach

func (e *Engine) ContainerAttach(ctx context.Context, containerID string, options client.ContainerAttachOptions) (client.ContainerAttachResult, error)

ContainerAttach attaches to a container's TTY. Only attaches to managed containers.

func (*Engine) ContainerCreate

ContainerCreate creates a container with managed labels automatically applied. If EnsureNetwork is specified, the network is created (if needed) and the container is connected to it. Does not mutate the caller's config - creates an internal copy.

func (*Engine) ContainerInspect

func (e *Engine) ContainerInspect(ctx context.Context, containerID string, options client.ContainerInspectOptions) (client.ContainerInspectResult, error)

ContainerInspect inspects a container. Only inspects managed containers.

func (*Engine) ContainerKill

func (e *Engine) ContainerKill(ctx context.Context, containerID, signal string) (client.ContainerKillResult, error)

ContainerKill sends a signal to a container. Only kills managed containers. Default signal is SIGKILL.

func (*Engine) ContainerList

ContainerList lists containers matching the filter. The managed label filter is automatically injected.

func (*Engine) ContainerListAll

func (e *Engine) ContainerListAll(ctx context.Context) ([]container.Summary, error)

ContainerListAll lists all containers (including stopped) with the managed filter.

func (*Engine) ContainerListByLabels

func (e *Engine) ContainerListByLabels(ctx context.Context, labels map[string]string, all bool) ([]container.Summary, error)

ContainerListByLabels lists containers matching additional label filters. The managed label filter is automatically injected.

func (*Engine) ContainerListRunning

func (e *Engine) ContainerListRunning(ctx context.Context) ([]container.Summary, error)

ContainerListRunning lists only running containers with the managed filter.

func (*Engine) ContainerLogs

func (e *Engine) ContainerLogs(ctx context.Context, containerID string, options client.ContainerLogsOptions) (client.ContainerLogsResult, error)

ContainerLogs streams container logs. Only returns logs for managed containers.

func (*Engine) ContainerPause

func (e *Engine) ContainerPause(ctx context.Context, containerID string) (client.ContainerPauseResult, error)

ContainerPause pauses a running container. Only pauses managed containers.

func (*Engine) ContainerRemove

func (e *Engine) ContainerRemove(ctx context.Context, containerID string, force bool) (client.ContainerRemoveResult, error)

ContainerRemove overrides to only remove managed containers.

func (*Engine) ContainerRename

func (e *Engine) ContainerRename(ctx context.Context, containerID, newName string) (client.ContainerRenameResult, error)

ContainerRename renames a container. Only renames managed containers.

func (*Engine) ContainerResize

func (e *Engine) ContainerResize(ctx context.Context, containerID string, height, width uint) (client.ContainerResizeResult, error)

ContainerResize resizes a container's TTY. Only resizes managed containers.

func (*Engine) ContainerRestart

func (e *Engine) ContainerRestart(ctx context.Context, containerID string, timeout *int) (client.ContainerRestartResult, error)

ContainerRestart restarts a container with an optional timeout. If timeout is nil, the Docker default is used. Only restarts managed containers.

func (*Engine) ContainerStart

ContainerStart starts a container with managed label verification. If EnsureNetwork is specified, the network is created (if needed) and the container is connected to it before starting. This is useful for reconnecting existing containers to networks that may have been removed.

func (*Engine) ContainerStatPath

func (e *Engine) ContainerStatPath(ctx context.Context, containerID string, opts client.ContainerStatPathOptions) (client.ContainerStatPathResult, error)

ContainerStatPath returns stat info for a path inside a container. Only works on managed containers.

func (*Engine) ContainerStats

func (e *Engine) ContainerStats(ctx context.Context, containerID string, stream bool) (client.ContainerStatsResult, error)

ContainerStats returns resource usage statistics for a container. If stream is true, stats are streamed until the context is cancelled. Only returns stats for managed containers.

func (*Engine) ContainerStatsOneShot

func (e *Engine) ContainerStatsOneShot(ctx context.Context, containerID string) (client.ContainerStatsResult, error)

ContainerStatsOneShot returns a single snapshot of container stats. The caller is responsible for closing the Body in the returned io.ReadCloser. Only returns stats for managed containers.

func (*Engine) ContainerStop

func (e *Engine) ContainerStop(ctx context.Context, containerID string, timeout *int) (client.ContainerStopResult, error)

ContainerStop stops a container with an optional timeout. If timeout is nil, the Docker default is used. Only stops managed containers.

func (*Engine) ContainerTop

func (e *Engine) ContainerTop(ctx context.Context, containerID string, args []string) (client.ContainerTopResult, error)

ContainerTop returns the running processes in a container. Only returns processes for managed containers.

func (*Engine) ContainerUnpause

func (e *Engine) ContainerUnpause(ctx context.Context, containerID string) (client.ContainerUnpauseResult, error)

ContainerUnpause unpauses a paused container. Only unpauses managed containers.

func (*Engine) ContainerUpdate

func (e *Engine) ContainerUpdate(ctx context.Context, containerID string, resources *container.Resources, restartPolicy *container.RestartPolicy) (client.ContainerUpdateResult, error)

ContainerUpdate updates a container's resource constraints. Only updates managed containers.

func (*Engine) ContainerWait

func (e *Engine) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) client.ContainerWaitResult

ContainerWait waits for a container to exit. Only waits for managed containers.

func (*Engine) CopyFromContainer

func (e *Engine) CopyFromContainer(ctx context.Context, containerID string, opts client.CopyFromContainerOptions) (client.CopyFromContainerResult, error)

CopyFromContainer copies content from a container. Returns a tar archive reader and file stat info. The caller is responsible for closing the reader. Only copies from managed containers.

func (*Engine) CopyToContainer

func (e *Engine) CopyToContainer(ctx context.Context, containerID string, opts client.CopyToContainerOptions) (client.CopyToContainerResult, error)

CopyToContainer copies content to a container. The content should be a tar archive. Only copies to managed containers.

func (*Engine) EnsureNetwork

func (e *Engine) EnsureNetwork(ctx context.Context, opts EnsureNetworkOptions) (string, error)

EnsureNetwork creates a network if it doesn't exist. Returns the network ID.

func (*Engine) ExecCreate

func (e *Engine) ExecCreate(ctx context.Context, containerID string, opts client.ExecCreateOptions) (client.ExecCreateResult, error)

ExecCreate creates an exec instance. Only creates exec instances for managed containers.

func (*Engine) FindContainerByName

func (e *Engine) FindContainerByName(ctx context.Context, name string) (*container.Summary, error)

FindContainerByName finds a managed container by exact name. Returns ErrContainerNotFound if not found. Only returns containers with the managed label.

func (*Engine) HealthCheck

func (e *Engine) HealthCheck(ctx context.Context) error

HealthCheck verifies the Docker daemon is reachable.

func (*Engine) ImageBuild

func (e *Engine) ImageBuild(ctx context.Context, buildContext io.Reader, options client.ImageBuildOptions) (client.ImageBuildResult, error)

ImageBuild builds an image from a build context. Labels are applied via the build options.

func (*Engine) ImageBuildKit

func (e *Engine) ImageBuildKit(ctx context.Context, opts ImageBuildKitOptions) error

ImageBuildKit builds an image using BuildKit via the configured closure. Labels are merged identically to ImageBuild — managed labels are injected and cannot be overridden by caller-supplied labels.

Returns ErrBuildKitNotConfigured if BuildKitImageBuilder is nil.

func (*Engine) ImageInspect

func (e *Engine) ImageInspect(ctx context.Context, imageRef string) (client.ImageInspectResult, error)

ImageInspect inspects an image.

func (*Engine) ImageList

func (e *Engine) ImageList(ctx context.Context, options client.ImageListOptions) (client.ImageListResult, error)

ImageList lists images matching the filter. The managed label filter is automatically injected.

func (*Engine) ImageRemove

func (e *Engine) ImageRemove(ctx context.Context, imageID string, options client.ImageRemoveOptions) (client.ImageRemoveResult, error)

ImageRemove removes an image.

func (*Engine) ImageTag

func (e *Engine) ImageTag(ctx context.Context, opts ImageTagOptions) (ImageTagResult, error)

ImageTag adds a tag to an existing managed image. The source image must have the managed label or the operation is rejected.

func (*Engine) ImagesPrune

func (e *Engine) ImagesPrune(ctx context.Context, dangling bool) (client.ImagePruneResult, error)

ImagesPrune removes all unused managed images. The managed label filter is automatically injected to ensure only managed images are affected. The dangling parameter controls whether to only remove dangling images (untagged) or all unused images.

func (*Engine) IsContainerManaged

func (e *Engine) IsContainerManaged(ctx context.Context, containerID string) (bool, error)

IsContainerManaged checks if a container has the managed label.

func (*Engine) IsNetworkManaged

func (e *Engine) IsNetworkManaged(ctx context.Context, name string) (bool, error)

IsNetworkManaged checks if a network has the managed label.

func (*Engine) IsVolumeManaged

func (e *Engine) IsVolumeManaged(ctx context.Context, name string) (bool, error)

IsVolumeManaged checks if a volume has the managed label.

func (*Engine) ManagedLabelKey

func (e *Engine) ManagedLabelKey() string

ManagedLabelKey returns the full managed label key (e.g., "com.myapp.managed").

func (*Engine) ManagedLabelValue

func (e *Engine) ManagedLabelValue() string

ManagedLabelValue returns the managed label value (always "true").

func (*Engine) NetworkConnect

func (e *Engine) NetworkConnect(ctx context.Context, network, containerID string, config *network.EndpointSettings) (client.NetworkConnectResult, error)

NetworkConnect connects a container to a network. Only connects to managed networks.

func (*Engine) NetworkCreate

func (e *Engine) NetworkCreate(ctx context.Context, name string, options client.NetworkCreateOptions, extraLabels ...map[string]string) (client.NetworkCreateResult, error)

NetworkCreate creates a new network with managed labels automatically applied. The provided labels are merged with the engine's configured labels.

func (*Engine) NetworkDisconnect

func (e *Engine) NetworkDisconnect(ctx context.Context, network, containerID string, force bool) (client.NetworkDisconnectResult, error)

NetworkDisconnect disconnects a container from a network. Only disconnects from managed networks.

func (*Engine) NetworkExists

func (e *Engine) NetworkExists(ctx context.Context, name string) (bool, error)

NetworkExists checks if a managed network exists. Delegates to IsNetworkManaged so that unmanaged networks are treated as "not found". This is consistent with NetworkInspect and NetworkRemove which also enforce the managed label.

func (*Engine) NetworkInspect

func (e *Engine) NetworkInspect(ctx context.Context, name string, options client.NetworkInspectOptions) (client.NetworkInspectResult, error)

NetworkInspect inspects a network.

func (*Engine) NetworkList

func (e *Engine) NetworkList(ctx context.Context, extraFilters ...map[string]string) (client.NetworkListResult, error)

NetworkList lists networks matching the filter. The managed label filter is automatically injected.

func (*Engine) NetworkRemove

func (e *Engine) NetworkRemove(ctx context.Context, name string) (client.NetworkRemoveResult, error)

NetworkRemove removes a network.

func (*Engine) NetworksPrune

func (e *Engine) NetworksPrune(ctx context.Context) (client.NetworkPruneResult, error)

NetworksPrune removes all unused managed networks. The managed label filter is automatically injected to ensure only managed networks are affected.

func (*Engine) Options

func (e *Engine) Options() EngineOptions

Options returns the engine options.

func (*Engine) VolumeCreate

func (e *Engine) VolumeCreate(ctx context.Context, options client.VolumeCreateOptions, extraLabels ...map[string]string) (client.VolumeCreateResult, error)

VolumeCreate creates a new volume with managed labels automatically applied. The provided labels are merged with the engine's configured labels.

func (*Engine) VolumeExists

func (e *Engine) VolumeExists(ctx context.Context, volumeID string) (bool, error)

VolumeExists checks if a managed volume exists. Delegates to IsVolumeManaged so that unmanaged volumes (e.g. Docker-auto-created volumes without labels) are treated as "not found". This is consistent with VolumeInspect and VolumeRemove which also enforce the managed label.

func (*Engine) VolumeInspect

func (e *Engine) VolumeInspect(ctx context.Context, volumeID string) (client.VolumeInspectResult, error)

VolumeInspect inspects a volume. Only inspects managed volumes.

func (*Engine) VolumeList

func (e *Engine) VolumeList(ctx context.Context, extraFilters ...map[string]string) (client.VolumeListResult, error)

VolumeList lists volumes matching the filter. The managed label filter is automatically injected.

func (*Engine) VolumeListAll

func (e *Engine) VolumeListAll(ctx context.Context) (client.VolumeListResult, error)

VolumeListAll lists all managed volumes.

func (*Engine) VolumeRemove

func (e *Engine) VolumeRemove(ctx context.Context, volumeID string, force bool) (client.VolumeRemoveResult, error)

VolumeRemove removes a volume. Only removes managed volumes.

func (*Engine) VolumesPrune

func (e *Engine) VolumesPrune(ctx context.Context, all bool) (client.VolumePruneResult, error)

VolumesPrune removes all unused managed volumes. The managed label filter is automatically injected to ensure only managed volumes are affected. If all is true, prunes all unused volumes including named ones. If all is false, only prunes anonymous volumes (Docker's default behavior).

type EngineOptions

type EngineOptions struct {
	// LabelPrefix is the prefix for all managed labels (e.g., "com.myapp").
	// Used to construct the managed label key: "{LabelPrefix}.{ManagedLabel}".
	LabelPrefix string

	// ManagedLabel is the label key suffix that marks resources as managed.
	// Default: "managed". Combined with LabelPrefix to form the full key.
	// Example: with LabelPrefix="com.myapp" and ManagedLabel="managed",
	// the full key is "com.myapp.managed=true".
	ManagedLabel string

	// Labels configures labels for different resource types.
	Labels LabelConfig
}

EngineOptions configures the behavior of the Engine.

type EnsureNetworkOptions

type EnsureNetworkOptions struct {
	client.NetworkCreateOptions // Embedded: Driver, Options, Labels, Scope, etc.

	Name        string // Network name (required)
	Verbose     bool   // Verbose output during ensure
	ExtraLabels Labels // Additional labels to merge with managed labels
}

EnsureNetworkOptions configures network creation/ensure behavior. Embeds Docker SDK's NetworkCreateOptions for forward compatibility.

type ExecAttachOptions

type ExecAttachOptions = client.ExecAttachOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ExecCreateOptions

type ExecCreateOptions = client.ExecCreateOptions

Exec operation options and results.

type ExecInspectOptions

type ExecInspectOptions = client.ExecInspectOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ExecInspectResult

type ExecInspectResult = client.ExecInspectResult

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ExecResizeOptions

type ExecResizeOptions = client.ExecResizeOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ExecStartOptions

type ExecStartOptions = client.ExecStartOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type Filters

type Filters = client.Filters

Filters wraps Docker client.Filters for filtering resources.

type HijackedResponse

type HijackedResponse = client.HijackedResponse

Connection types.

type ImageBuildKitOptions

type ImageBuildKitOptions struct {
	// Tags are the image tags to apply (e.g., "myimage:latest").
	Tags []string

	// ContextDir is the build context directory (required).
	ContextDir string

	// Dockerfile is the path relative to ContextDir (default: "Dockerfile").
	Dockerfile string

	// BuildArgs are --build-arg key=value pairs.
	BuildArgs map[string]*string

	// NoCache disables build cache.
	NoCache bool

	// Labels are applied to the built image. Managed labels are injected
	// automatically and cannot be overridden.
	Labels map[string]string

	// Target sets the target build stage.
	Target string

	// Pull forces pulling base images.
	Pull bool

	// SuppressOutput suppresses build output logging.
	SuppressOutput bool

	// NetworkMode sets the network mode for RUN instructions.
	NetworkMode string

	// OnProgress receives build progress events when non-nil.
	// Called from the progress-draining goroutine — must be safe for concurrent use.
	OnProgress BuildProgressFunc
}

ImageBuildKitOptions configures a BuildKit-based image build. Labels are injected automatically by Engine.ImageBuildKit — callers should set application-specific labels only.

type ImageBuildOptions

type ImageBuildOptions = client.ImageBuildOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ImageListOptions

type ImageListOptions = client.ImageListOptions

Image operation options.

type ImageListResult

type ImageListResult = client.ImageListResult

Image result types.

type ImagePullOptions

type ImagePullOptions = client.ImagePullOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ImageRemoveOptions

type ImageRemoveOptions = client.ImageRemoveOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ImageSummary

type ImageSummary = image.Summary

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ImageTagOptions

type ImageTagOptions = client.ImageTagOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type ImageTagResult

type ImageTagResult = client.ImageTagResult

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type LabelConfig

type LabelConfig struct {
	// Default labels applied to all resource types (containers, volumes, networks, images)
	Default map[string]string

	// Container-specific labels (merged with Default)
	Container map[string]string

	// Volume-specific labels (merged with Default)
	Volume map[string]string

	// Network-specific labels (merged with Default)
	Network map[string]string

	// Image-specific labels (merged with Default)
	Image map[string]string
}

LabelConfig defines labels to apply to different resource types. All labels are optional - if a map is nil, no labels are applied for that resource type.

func (*LabelConfig) ContainerLabels

func (c *LabelConfig) ContainerLabels(extra ...map[string]string) map[string]string

ContainerLabels returns the merged labels for containers.

func (*LabelConfig) ImageLabels

func (c *LabelConfig) ImageLabels(extra ...map[string]string) map[string]string

ImageLabels returns the merged labels for images.

func (*LabelConfig) NetworkLabels

func (c *LabelConfig) NetworkLabels(extra ...map[string]string) map[string]string

NetworkLabels returns the merged labels for networks.

func (*LabelConfig) VolumeLabels

func (c *LabelConfig) VolumeLabels(extra ...map[string]string) map[string]string

VolumeLabels returns the merged labels for volumes.

type Labels

type Labels []map[string]string

Labels represents a collection of label maps to be merged. Each map in the slice is merged in order, with later maps taking precedence. This is the official type for label maps throughout whail.

func (Labels) Merge

func (l Labels) Merge() map[string]string

Merge merges the Labels into a single map. Later maps take precedence over earlier ones.

type NetworkCreateOptions

type NetworkCreateOptions = client.NetworkCreateOptions

Network operation options and results.

type NetworkCreateResult added in v0.5.0

type NetworkCreateResult = client.NetworkCreateResult

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type NetworkInspectOptions

type NetworkInspectOptions = client.NetworkInspectOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type NetworkInspectResult added in v0.5.0

type NetworkInspectResult = client.NetworkInspectResult

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type Pinger

type Pinger interface {
	Ping(ctx context.Context, options client.PingOptions) (client.PingResult, error)
}

Pinger is the subset of the Docker API needed for BuildKit detection.

type Resources

type Resources = container.Resources

Container configuration types.

type RestartPolicy

type RestartPolicy = container.RestartPolicy

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type SDKContainerCreateOptions

type SDKContainerCreateOptions = client.ContainerCreateOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type SDKContainerStartOptions

type SDKContainerStartOptions = client.ContainerStartOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type SDKContainerWaitOptions

type SDKContainerWaitOptions = client.ContainerWaitOptions

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type UpdateConfig

type UpdateConfig = container.UpdateConfig

Type aliases for Docker SDK types. These allow packages to use whail as their single import for Docker interactions.

type VolumeCreateOptions

type VolumeCreateOptions = client.VolumeCreateOptions

Volume operation options.

type WaitCondition

type WaitCondition = container.WaitCondition

Wait Condition

Directories

Path Synopsis
Package buildkit provides BuildKit client connectivity for whail.
Package buildkit provides BuildKit client connectivity for whail.
Package whailtest provides test doubles and helpers for testing code that uses the whail engine.
Package whailtest provides test doubles and helpers for testing code that uses the whail engine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL