Help us shape the future of Go! Take the 2026 Go Developer Survey

docker

package
v1.4.15 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Index

Constants

View Source
const (
	HealthyTimeout = 60 * time.Second
	RunningTimeout = 30 * time.Second
)

Gate timeouts by service kind (D17): healthcheck or one-shot exit, else running (and still the same run one poll later).

View Source
const ImageOverrideFile = ".nself/state/image-overrides.yml"
View Source
const MaxHealthTimeout = 10 * time.Minute

MaxHealthTimeout caps ServiceSpec.HealthTimeout: a healthcheck declared with a huge retries or interval must not stall a deploy for hours.

View Source
const MinComposeVersion = "2.20.0"

MinComposeVersion is the oldest docker compose that reads every compose.env value nSelf writes.

View Source
const StateNotRestarted = "not-restarted"

StateNotRestarted marks an exited container that has not started since the baseline (see FreshStates).

Variables

View Source
var (
	ErrOneShotFailed  = errors.New("one-shot service exited non-zero")
	ErrServiceCrashed = errors.New("service exited non-zero or is restarting")
	ErrGateTimeout    = errors.New("service did not reach its ready state in time")
	ErrStateRead      = errors.New("could not read container state")
)

Gate failures. ErrOneShotFailed and ErrServiceCrashed map to E250 (the service is broken), ErrGateTimeout to E251 (too slow), ErrStateRead and ErrStateTimeout to no service code at all: docker could not answer, which says nothing about the service.

View Source
var ErrImageNotFound = errors.New("image not found locally")

ErrImageNotFound means the image is not present locally. Match with errors.Is.

View Source
var ErrNotIndex = errors.New("reference is not an image index")

ErrNotIndex means the reference resolves to a single manifest, not an index.

View Source
var ErrServiceContainerAmbiguous = errors.New("service container is ambiguous")

ErrServiceContainerAmbiguous is returned (wrapped, naming every candidate) when more than one running container matches a ServiceMatch. Match with errors.Is.

View Source
var ErrServiceContainerNotFound = errors.New("service container not found")

ErrServiceContainerNotFound is returned (wrapped) when no running container matches a ServiceMatch. Match with errors.Is.

View Source
var ErrStateTimeout = errors.New("docker gave no answer in time")

ErrStateTimeout is wrapped by a state read whose own bound fired. It is not context.DeadlineExceeded on purpose: callers outside the gate class it as a state-read failure, not as the user's interrupt.

View Source
var ReservedPorts = []int{
	80, 443, 5432, 8080, 4000, 6379,
	9000, 9001, 7700, 3021, 1025, 8025,
	3008, 5000,
}

ReservedPorts lists ports used by the nSelf stack that must be checked for conflicts before starting services.

Functions

func CheckPort

func CheckPort(port int) (bool, error)

CheckPort probes a single TCP port on localhost using DialTimeout. It returns true when the port is in use (connection succeeded) and false when the port is available (connection refused or timed out).

func ComposeConfigHashes added in v1.4.13

func ComposeConfigHashes(ctx context.Context, files, envFiles []string, projectDir string) (map[string]string, error)

ComposeConfigHashes runs `docker compose <-f ...> <--env-file ...> --project-directory <dir> config --hash '*'` and returns service -> hash.

Inputs: the -f files and --env-file files in the order `start` passes them, and the project directory relative paths resolve against. Outputs: one entry per service in the merged configuration. A failure to run compose, or a compose too old to know --hash, is an error: the caller decides whether that means "impact unknown".

func ComposeServiceNames added in v1.3.6

func ComposeServiceNames(composeFilePaths []string) (map[string]struct{}, error)

ComposeServiceNames reads every compose file in composeFilePaths (the base docker-compose.yml plus any plugin compose fragments — the same file set `docker compose -f ... -f ...` is invoked with, see build.ReadComposeManifest) and returns the union of all service names they define. This is the "desired state" DetectOrphans compares live containers against.

Inputs: composeFilePaths — absolute paths to YAML files; missing files are

skipped (best-effort — a plugin fragment can be removed from disk
independently of the manifest that references it).

Outputs: the union of service keys across all readable files, and the

first hard parse error encountered (a file that exists but is not
valid YAML is a real problem, not a missing-file gap).

Constraints: pure I/O + YAML parsing, no docker daemon access.

func ComposeTooOldMessage added in v1.4.15

func ComposeTooOldMessage(v string) string

ComposeTooOldMessage explains a too-old compose version and the fix.

func ComposeVersion added in v1.4.15

func ComposeVersion(ctx context.Context) (string, error)

ComposeVersion returns the output of `docker compose version --short`, trimmed. It fails when docker or the compose plugin is missing.

func ContainerNetworks added in v1.4.15

func ContainerNetworks(ctx context.Context, name string) ([]string, error)

ContainerNetworks returns the names of the networks the container is on, sorted.

func ContainerVolume added in v1.4.15

func ContainerVolume(ctx context.Context, container, dest string) (string, error)

ContainerVolume returns the name of the named volume mounted at dest in the container, "" when nothing named is mounted there.

func DeclaredHostPorts added in v1.3.4

func DeclaredHostPorts(ctx context.Context, workdir string, envFiles []string, composeFiles ...string) ([]int, map[int]string, error)

DeclaredHostPorts returns the host ports the given compose files publish, together with a port -> service name map for error messages.

This exists because checking a fixed list of default ports is wrong for any stack that was configured off the defaults. A second nSelf project on one host must move its ports (POSTGRES_PORT=5433, HASURA_PORT=8181, ...); with a fixed list it is then blocked by the first project holding 5432 and 8080, ports it was never going to bind. That is what kept a staging stack down.

An error here means "could not determine", never "binds nothing". The caller must fall back to a conservative default list rather than check nothing. envFiles are passed as --env-file. Without them an installed plugin's docker-compose.plugin.yml cannot resolve ${DOCKER_NETWORK} and docker rejects the project as invalid, so this returns an error and the caller silently falls back to the default port list.

func DefaultCommand

func DefaultCommand(service string) []string

DefaultCommand returns the default shell or client command for a given service. Recognized services get their native CLI; everything else falls back to /bin/sh.

func DefaultPortServiceNames added in v1.3.4

func DefaultPortServiceNames() map[int]string

DefaultPortServiceNames maps the ReservedPorts defaults to human names. Used only on the fallback path, when the published ports could not be read from compose; the normal path names services from the compose config itself, so a project on custom ports still gets "Port 8181 (hasura)" and not "unknown service".

func Diagnose added in v1.4.13

func Diagnose(message string) string

Diagnose turns Docker and registry errors into stable operator diagnoses.

func EnsureComposeImages added in v1.4.13

func EnsureComposeImages(ctx context.Context, workdir string, c *Compose, refs []LockedImage) (bool, error)

EnsureComposeImages checks every locked image used by the resolved stack on every start, including after a lock change on a previously started project. It writes or removes the mirror override and reports whether the file changed.

func EnsureImage added in v1.4.13

func EnsureImage(ctx context.Context, ref LockedImage) (string, error)

EnsureImage inspects the exact upstream digest, then pulls upstream and the same digest from its mirror in that order. It never tags a digest reference.

func Exec

func Exec(ctx context.Context, container string, cmd []string, opts ExecOptions) error

Exec runs a command inside a running container, attaching stdin/stdout/stderr for interactive sessions.

func ExecCapture added in v1.4.13

func ExecCapture(ctx context.Context, container string, cmd []string) (stdout, stderr string, err error)

ExecCapture runs `docker exec <container> <cmd...>` and returns the output.

func ExecStdin added in v1.4.13

func ExecStdin(ctx context.Context, container string, cmd []string, stdin io.Reader) (stdout, stderr string, err error)

ExecStdin runs `docker exec [-i] <container> <cmd...>` with stdin (nil: no stdin, no -i) and returns the captured output. A non-zero exit returns the exec error as is; stderr is returned alongside for the caller to quote.

func FindServiceContainer added in v1.4.13

func FindServiceContainer(ctx context.Context, m ServiceMatch) (string, error)

FindServiceContainer returns the name of the single running container that matches m. Zero matches return an error wrapping ErrServiceContainerNotFound; several return one wrapping ErrServiceContainerAmbiguous that names them. Docker being unreachable returns a different error, so callers can tell "not running" from "cannot tell".

func GetContainerLogs

func GetContainerLogs(ctx context.Context, name string, tail int) (string, error)

GetContainerLogs shells out to `docker logs --tail N` and returns the combined output.

func GetHealthStatus

func GetHealthStatus(ctx context.Context, name string) (string, error)

GetHealthStatus returns the health status of a container: "healthy", "unhealthy", "starting", "none" (no healthcheck configured), or "not_found".

func HealthGate added in v1.4.13

func HealthGate(ctx context.Context, spec ServiceSpec, states StateSource, clock Clock) error

HealthGate waits until spec's containers are ready for their kind (D17). Any kind fails at once on a container that exited non-zero or is restarting. Healthcheck declared -> every container healthy within HealthyTimeout (checked first, even with restart "no"). One-shot (restart "no", no healthcheck) -> every container exited 0 within HealthyTimeout. Otherwise -> every container running within RunningTimeout and seen running on two polls in a row with the same StartedAt (a crash loop passes one poll); a service with no restart line that exited 0 is done, as Docker treats it. A healthcheck service waits max(HealthyTimeout, spec.HealthTimeout). Each state read is bounded (see gateReadGrace); a read that gets no answer wraps ErrGateTimeout. A cancelled ctx returns ctx's error; a failed state read wraps ErrStateRead. A nil clock means SystemClock.

func HealthTimeout added in v1.4.14

func HealthTimeout(name string, interval, timeout, startPeriod, retries json.RawMessage) (time.Duration, error)

HealthTimeout is healthTimeout for callers that parse the resolved compose config themselves (internal/deploy's copy of this parser), so both compute the same wait.

func ImageIndexRaw added in v1.4.13

func ImageIndexRaw(ctx context.Context, ref string) ([]byte, error)

ImageIndexRaw returns the raw index JSON of ref via `docker buildx imagetools inspect --raw`.

func ImageRepoDigests added in v1.4.14

func ImageRepoDigests(ctx context.Context, ref string) ([]string, error)

ImageRepoDigests returns the RepoDigests ("repo@sha256:<hex>") of the local image ref. An image without any (built locally, never pushed) returns an empty slice and no error.

func InspectState added in v1.4.15

func InspectState(ctx context.Context, name string) (string, error)

InspectState returns the Docker state of the named container.

func LocalRepoDigest added in v1.4.14

func LocalRepoDigest(ctx context.Context, ref string) string

LocalRepoDigest returns "sha256:<hex>" when the local image for ref has exactly one distinct digest recorded for ref's own repository, else "". A digest recorded for another repository (a retagged image) never counts.

func ManifestInspect added in v1.4.13

func ManifestInspect(ctx context.Context, ref string, verbose bool) ([]byte, error)

ManifestInspect runs `docker manifest inspect [--verbose] ref` and returns its stdout.

func NetworkConnect added in v1.4.15

func NetworkConnect(ctx context.Context, network, container string) error

NetworkConnect connects container to network. A container that is already on the network is left alone (no docker connect call).

func NetworkDisconnect added in v1.4.15

func NetworkDisconnect(ctx context.Context, network, container string) error

NetworkDisconnect disconnects container from network. A container that is not on the network, an absent network and an absent container are success.

func NetworkExists added in v1.4.15

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

NetworkExists reports whether a network with exactly this name exists.

func OwnedHostPorts added in v1.0.2

func OwnedHostPorts(ctx context.Context, workdir string, envFiles []string, composeFiles ...string) (map[int]bool, error)

OwnedHostPorts queries the running compose stack in workdir and returns the set of host-side port numbers currently bound by nself's own containers. These ports should not be reported as conflicts on startup — they are already owned by nself and will be reused by docker compose up.

envFiles are passed to docker compose as --env-file. They are REQUIRED once any plugin compose file is in play: an installed plugin's docker-compose.plugin.yml refers to ${DOCKER_NETWORK}, and without the env file that resolves to empty, so docker rejects the whole project with "service X refers to undefined network : invalid compose project" and this query fails.

If the query fails the error is RETURNED rather than swallowed. Reporting "nothing is owned" on a failure turns "I could not tell" into a confident wrong answer: every port the project itself already binds is then reported as a conflict, and `nself start` aborts against its own running stack.

func ParseComposeVersion added in v1.4.15

func ParseComposeVersion(s string) (major, minor, patch int, ok bool)

ParseComposeVersion reads "2.29.7", "v2.29.7", "2.29.7-desktop.1", "2.21.0+azure-1" or "2.20" (patch 0). It reports ok=false for anything else.

func ProjectEnvFiles added in v1.4.15

func ProjectEnvFiles(workdir string) []string

ProjectEnvFiles returns the --env-file list for the project in workdir by the rule of build.ComposeEnvFiles: the project .env (when present) then .nself/compose.env, or nil when compose.env is absent (compose then reads .env on its own). It serves packages that may not import internal/build; cmd/commands dev_test.go pins the two functions to each other.

func RegisterPreDownHook added in v1.4.15

func RegisterPreDownHook(h PreDownHook) (unregister func())

RegisterPreDownHook adds h to the hooks ComposeDown runs and returns the function that removes it again.

func Regressed added in v1.4.13

func Regressed(before, after []ContainerState) error

Regressed compares the containers a service's gate saw (before) with a later read (after). It returns ErrServiceCrashed, with the container named, when:

  • an after container is restarting, exited non-zero, or is not in before (a replica replaced or added after the gate);
  • a container that was running at its gate started again (a new StartedAt) or is now paused or dead;
  • Docker reports any after container unhealthy, whatever the gate waited for, or a container that was healthy at its gate is no longer running and healthy;
  • any before container, in any state, is missing from after.

Containers match by ID, or by Name when the ID is empty (old compose). Rows without a StartedAt cannot be compared by start time and are judged on state, identity and health. Exited 0 for a container that was never healthy is a finished run, not a crash; running/starting staying running/starting is fine.

func RemoveContainer added in v1.4.15

func RemoveContainer(ctx context.Context, name string) error

RemoveContainer force-removes the named container. An absent container is success.

func RemoveOrphans added in v1.3.6

func RemoveOrphans(ctx context.Context, orphans []OrphanContainer) []error

RemoveOrphans force-removes each orphan container by ID (docker rm -f — same primitive cleanup.go's forceRemoveContainer uses for init/zombie containers) and returns one error per failed removal. Never called unless the caller opted in (e.g. `nself build --remove-orphans`); detection alone never removes anything.

func RestartContainer added in v1.4.13

func RestartContainer(ctx context.Context, name string) error

func RunOneShot added in v1.4.13

func RunOneShot(ctx context.Context, spec RunSpec) (stdout, stderr string, err error)

RunOneShot runs spec to completion (`docker run --rm`) and returns what the container wrote to stdout and stderr. A non-zero exit returns the captured output together with an error that quotes the last stderr line.

func RunPostStartCleanup

func RunPostStartCleanup(ctx context.Context, projectName string) error

RunPostStartCleanup runs the full post-startup cleanup sequence:

  1. Init container cleanup, repeated 3 times with 500ms delays (handles race conditions where containers are still being marked as exited).
  2. Zombie container cleanup for containers stuck in "created" state.

func RunPreDownHooks added in v1.4.15

func RunPreDownHooks(ctx context.Context, workdir string)

RunPreDownHooks runs every registered hook for workdir.

func RunPreStartCleanup added in v1.2.2

func RunPreStartCleanup(ctx context.Context, projectName string) error

RunPreStartCleanup removes stale artifacts that would break `docker compose up`: hash-prefixed rename-leftover containers (which hold ports and shadow clean container names). Run before compose up.

func ServerVersion added in v1.4.13

func ServerVersion(ctx context.Context) (string, error)

func SetExecHook added in v1.4.13

func SetExecHook(fn func(container string, cmd []string)) (restore func())

SetExecHook installs fn to be called once per ExecStdin call (test seam for exec counting) and returns a function that restores the previous hook.

func StartContainer added in v1.4.15

func StartContainer(ctx context.Context, name string) error

StartContainer starts a stopped container (a running one is left alone by docker).

func StatefulServices added in v1.4.13

func StatefulServices(files []string) (map[string]bool, error)

StatefulServices returns the services that mount a named volume in any of the compose files (EPIC D7: a stateful service is one whose data lives in a named volume). A bind mount (a path) or tmpfs is not stateful. Missing files are skipped; a file that is not valid YAML is an error.

func StopContainer added in v1.4.15

func StopContainer(ctx context.Context, name string) error

StopContainer stops a container; a stopped one is not an error.

func VolumeCreate added in v1.4.15

func VolumeCreate(ctx context.Context, name string, labels map[string]string) error

VolumeCreate creates the named volume with the given labels. Creating a volume that exists with the same driver is a no-op in docker.

func VolumeExists added in v1.4.15

func VolumeExists(ctx context.Context, name string) (bool, error)

VolumeExists reports whether the named volume exists.

func VolumeLabels added in v1.4.15

func VolumeLabels(ctx context.Context, name string) (labels map[string]string, exists bool, err error)

VolumeLabels returns the labels of the named volume; exists is false when the volume is absent.

func VolumeRemove added in v1.4.15

func VolumeRemove(ctx context.Context, name string) error

VolumeRemove removes the named volume. An absent volume is success.

Types

type Clock added in v1.4.13

type Clock interface {
	Now() time.Time
	Sleep(ctx context.Context, d time.Duration) error
}

Clock is the time source of the gate. Sleep returns early with the context's error when ctx is cancelled.

type Compose

type Compose struct {
	// DockerPath overrides the docker binary location. Empty uses PATH lookup.
	DockerPath string

	// ComposeFiles lists compose file paths passed as -f flags.
	// Order matters: first file is the base, subsequent files extend/override.
	// If empty, no -f flags are added and Docker uses its default discovery.
	ComposeFiles []string

	// EnvFiles lists env file paths passed as --env-file flags for ${VAR}
	// interpolation (secrets are env-templated out of the generated compose
	// YAML — see internal/build secret templating). Order matters: later
	// files win on conflict. If empty, Docker Compose falls back to its
	// default .env discovery.
	EnvFiles []string
}

Compose shells out to `docker compose` for lifecycle operations.

func NewCompose

func NewCompose(files ...string) *Compose

NewCompose returns a Compose instance configured with the given compose files. If no files are provided, Docker Compose uses its default file discovery.

func (*Compose) ComposeConfig

func (c *Compose) ComposeConfig(ctx context.Context, workdir string) error

ComposeConfig runs `docker compose config` in the given workdir to validate the compose configuration. Returns nil on success.

func (*Compose) ComposeDown

func (c *Compose) ComposeDown(ctx context.Context, workdir string, opts DownOptions) error

ComposeDown runs `docker compose down` with the given options in the given workdir.

func (*Compose) ComposePs

func (c *Compose) ComposePs(ctx context.Context, workdir string) ([]ContainerInfo, error)

ComposePs runs `docker compose ps --format json` and parses the output into a slice of ContainerInfo.

Docker Compose v2 prints either one JSON array or one JSON object per stdout line (NDJSON), depending on the release.

Both formats are handled: the raw output is first attempted as a JSON array; if that fails (or yields nothing), the output is re-scanned line by line as NDJSON. This makes the function version-agnostic.

func (*Compose) ComposePull

func (c *Compose) ComposePull(ctx context.Context, workdir string) error

ComposePull runs `docker compose pull` in the given workdir, pulling images for all services defined in the compose file.

func (*Compose) ComposePullDiagnosed added in v1.4.13

func (c *Compose) ComposePullDiagnosed(ctx context.Context, workdir string) error

ComposePullDiagnosed retains a bounded stderr tail for first-run diagnosis. The general Compose runner can lose that tail when its pipe reader races process exit; a pull failure must preserve the registry's actual message.

func (*Compose) ComposePullService added in v1.1.3

func (c *Compose) ComposePullService(ctx context.Context, workdir, service string) error

ComposePullService runs `docker compose pull <service>` in the given workdir, pulling a fresh image only for the named service.

func (*Compose) ComposeRestart

func (c *Compose) ComposeRestart(ctx context.Context, workdir string, services ...string) error

ComposeRestart runs `docker compose restart [services...]` in the given workdir.

func (*Compose) ComposeScale added in v1.1.3

func (c *Compose) ComposeScale(ctx context.Context, workdir, service string, replicas int) error

ComposeScale runs `docker compose up -d --scale <service>=<n>` in the given workdir, adjusting the replica count for the named service.

func (*Compose) ComposeServiceNames added in v1.4.13

func (c *Compose) ComposeServiceNames(ctx context.Context, workdir string) ([]string, error)

ComposeServiceNames returns `docker compose config --services` over the manifest and env files, in docker's order.

func (*Compose) ComposeServiceStates added in v1.4.13

func (c *Compose) ComposeServiceStates(ctx context.Context, workdir, service string) ([]ContainerState, error)

ComposeServiceStates returns every replica (running or stopped) of service. Stopped containers matter: a one-shot is only visible once it has exited. One-off `compose run` containers are dropped. The read is bounded by stateCallTimeout.

func (*Compose) ComposeStop added in v1.1.3

func (c *Compose) ComposeStop(ctx context.Context, workdir string, services ...string) error

ComposeStop runs `docker compose stop [services...]` in the given workdir. Unlike ComposeDown, this stops containers without removing them, preserving their state for a subsequent ComposeUp.

func (*Compose) ComposeUp

func (c *Compose) ComposeUp(ctx context.Context, workdir string, services ...string) error

ComposeUp runs `docker compose up -d [services...]` in the given workdir.

func (*Compose) ComposeUpBuild added in v1.4.15

func (c *Compose) ComposeUpBuild(ctx context.Context, workdir string, services ...string) error

ComposeUpBuild runs `docker compose up -d --no-deps --build [services...]`: rebuild the named services' images and recreate only those containers.

func (*Compose) ComposeUpNoDeps added in v1.3.0

func (c *Compose) ComposeUpNoDeps(ctx context.Context, workdir string, services ...string) error

ComposeUpNoDeps runs `docker compose up -d --no-deps [services...]`.

This is the primitive that means "make these containers match the compose file": Compose recreates a container whose definition changed and leaves an unchanged one alone. `restart` does neither — it bounces the existing container and never re-reads the file. --no-deps keeps the operation scoped to the named services instead of pulling their dependencies up with them.

func (*Compose) FreshStates added in v1.4.13

func (c *Compose) FreshStates(ctx context.Context, workdir, service string, baseline map[string]string) ([]ContainerState, error)

FreshStates is ComposeServiceStates plus StartedAt on every running or exited container. An exited container whose StartedAt still equals its baseline mark is reported as StateNotRestarted, so a stale exit cannot pass the one-shot gate. No ID (old compose) means no mark and no StartedAt. A container removed between the ps and its inspect is dropped from the result (the gate polls again; Regressed reports it gone). The whole read shares one stateCallTimeout.

func (*Compose) OutputProject added in v1.4.15

func (c *Compose) OutputProject(ctx context.Context, workdir string, p ProjectRun, args ...string) ([]byte, error)

OutputProject runs args against p.Project in workdir and returns stdout. p.Stdout and p.Stderr are ignored: stderr is kept for the error, which carries its last line.

func (*Compose) Run

func (c *Compose) Run(ctx context.Context, workdir string, args ...string) error

Run executes a docker command with the given arguments, setting the working directory and inheriting the context for cancellation. Output is forwarded to os.Stdout/os.Stderr via goroutine-owned pipes rather than direct fd inheritance.

Direct fd inheritance (cmd.Stdout = os.Stdout) passes the test binary's stdout file descriptor to docker compose and all its children. The docker daemon, which is a separate long-lived process, may hold that fd open via IPC even after the docker compose process is killed — causing "*** Test I/O incomplete N s after exiting" in the Go test harness. Piped copying breaks the inheritance chain: the subprocess gets the write end of a pipe; our goroutine owns the read end and copies to os.Stdout. When the subprocess exits (or is killed), it closes the write end, the goroutine finishes, and the test binary's stdout fd is never held by any docker process.

WaitDelay gives the subprocess up to 5 seconds to drain pending I/O after the context is cancelled and the process is killed.

Setpgid places docker compose in its own process group so SIGKILL from the Cancel hook propagates to all spawned child processes, not just the top-level docker process.

func (*Compose) RunProject added in v1.4.15

func (c *Compose) RunProject(ctx context.Context, workdir string, p ProjectRun, args ...string) error

RunProject runs args against p.Project in workdir. A failure carries the tail of compose's stderr.

func (*Compose) StartMarks added in v1.4.13

func (c *Compose) StartMarks(ctx context.Context, workdir, service string) (map[string]string, error)

StartMarks maps container ID to StartedAt for each exited container of service. Taken before `up`, it lets FreshStates tell a one-shot that ran again (same container, new start time) from an old exit. The whole read (ps and every inspect) shares one stateCallTimeout.

type ComposeVerdict added in v1.4.15

type ComposeVerdict int

ComposeVerdict is the outcome of comparing a version with MinComposeVersion.

const (
	// ComposeOK means the version is at least MinComposeVersion.
	ComposeOK ComposeVerdict = iota
	// ComposeTooOld means the version is below MinComposeVersion.
	ComposeTooOld
	// ComposeUnknown means the string could not be parsed.
	ComposeUnknown
)

func CheckComposeVersion added in v1.4.15

func CheckComposeVersion(s string) ComposeVerdict

CheckComposeVersion compares s with MinComposeVersion.

type Container

type Container struct {
	ID      string
	Name    string
	Service string
	State   string // running, exited, paused, etc.
	Health  string // healthy, unhealthy, starting, none
	Ports   []string
}

Container represents a running or stopped container from ComposePs.

type ContainerInfo

type ContainerInfo struct {
	ID        string
	Name      string
	Service   string // Docker Compose service name (e.g. "postgres", "hasura")
	Image     string
	ImageRef  string // the reference the container was created from (Config.Image), e.g. postgres:16-alpine
	State     string
	Health    string
	Ports     []string
	Env       map[string]string
	Labels    map[string]string
	CreatedAt string
	StartedAt string
	Mounts    []Mount
}

ContainerInfo holds detailed inspection data for a single container.

func InspectContainer

func InspectContainer(ctx context.Context, name string) (*ContainerInfo, error)

InspectContainer shells out to `docker inspect` and returns parsed ContainerInfo.

type ContainerState added in v1.4.13

type ContainerState struct {
	ID        string `json:"ID"`
	Name      string `json:"Name"`
	State     string `json:"State"`  // running, exited, restarting, ...
	Health    string `json:"Health"` // healthy, unhealthy, starting, or empty
	ExitCode  int    `json:"ExitCode"`
	StartedAt string `json:"-"` // daemon StartedAt; set by FreshStates, empty from a plain read

	// Labels is a map or one "k=v,k=v" string, depending on the compose release.
	Labels json.RawMessage `json:"Labels,omitempty"`
}

ContainerState is one container as `compose ps -a` reports it.

func (ContainerState) OneOff added in v1.4.13

func (s ContainerState) OneOff() bool

OneOff reports a container created by `docker compose run`. It is not a replica of the service, so the gate must not wait on it.

type DownOptions

type DownOptions struct {
	RemoveVolumes bool
	RemoveImages  bool // --rmi all
	RemoveOrphans bool
	Timeout       int // seconds; 0 uses Docker default
}

DownOptions configures behavior for ComposeDown.

type ExecOptions

type ExecOptions struct {
	Interactive bool
	TTY         bool
	User        string
	WorkDir     string
	Env         []string
}

ExecOptions configures behavior for container exec operations.

type Executor

type Executor interface {
	ComposeUp(ctx context.Context, services ...string) error
	ComposeDown(ctx context.Context, opts DownOptions) error
	ComposePs(ctx context.Context) ([]Container, error)
	ComposeLogs(ctx context.Context, service string, follow bool, tail int) (io.ReadCloser, error)
	Inspect(ctx context.Context, container string) (*ContainerInfo, error)
	Exec(ctx context.Context, container string, cmd []string) error
}

Executor abstracts Docker Compose and container operations for testability.

type IndexInfo added in v1.4.13

type IndexInfo struct {
	// MediaType is the index media type as published.
	MediaType string
	// Digest is "sha256:<hex>" of the raw index bytes (the index digest).
	Digest string
	// Platforms maps "linux/amd64", "linux/arm64", "linux/arm/v7" to the
	// per-platform manifest digest.
	Platforms map[string]string
}

IndexInfo is the parsed form of an image index.

func ParseIndex added in v1.4.13

func ParseIndex(raw []byte) (IndexInfo, error)

ParseIndex computes the index digest of raw and extracts the per-platform digests. A trailing newline added by the CLI is not part of the digest.

type LockedImage added in v1.4.13

type LockedImage struct {
	Name, Repository, Version, IndexDigest string
	Mirror                                 *string
}

LockedImage is the Docker-facing projection of an image-lock entry. Keeping this value here preserves the L0 Docker funnel's dependency direction.

func (LockedImage) String added in v1.4.13

func (r LockedImage) String() string

type Mount

type Mount struct {
	Source      string
	Destination string
	Type        string // bind, volume, tmpfs
	ReadOnly    bool
}

Mount represents a container volume mount.

func ContainerMounts added in v1.4.13

func ContainerMounts(ctx context.Context, name string) ([]Mount, error)

ContainerMounts returns the mounts of the named container via docker inspect, as Mount values (Source, Destination, Type, ReadOnly).

type OrphanContainer added in v1.3.6

type OrphanContainer struct {
	ID      string
	Name    string
	Service string // may be empty if the container somehow lacks the label
	State   string
}

OrphanContainer describes a running-or-stopped container that belongs to this project (by compose project label) but has no matching service in the freshly generated compose files.

func DetectOrphans added in v1.3.6

func DetectOrphans(ctx context.Context, projectName string, defined map[string]struct{}) ([]OrphanContainer, error)

DetectOrphans lists every container belonging to projectName (by compose project label — see the package-level scoping note above) and returns the ones whose service is not present in defined. Returns an error only when the docker CLI itself could not be run (daemon unreachable, binary missing); callers should treat that as advisory-only and skip reporting rather than failing the caller's own command (a `nself build` run in a docker-less CI image must still succeed).

type PortConflict

type PortConflict struct {
	Port  int
	InUse bool
}

PortConflict records whether a specific port is already in use.

func CheckAllPorts

func CheckAllPorts(ports []int) ([]PortConflict, error)

CheckAllPorts probes every port in the slice and returns only the entries where the port is already in use. A nil slice means no conflicts were found.

func CheckAllPortsFiltered added in v1.0.2

func CheckAllPortsFiltered(ctx context.Context, portList []int, workdir string, envFiles []string, composeFiles ...string) ([]PortConflict, error)

CheckAllPortsFiltered probes every port in the slice and returns only entries where the port is in use by a process that is NOT part of nself's own running compose stack. This prevents false positives where nself's own containers (e.g. postgres bound to 127.0.0.1:5432) are reported as conflicts on restart.

workdir, envFiles and composeFiles are forwarded to OwnedHostPorts. If that query fails the error is returned rather than degrading to unfiltered behaviour: unfiltered means the project's own ports read as conflicts, which blocks a legitimate start instead of catching a real one.

type PreDownHook added in v1.4.15

type PreDownHook func(ctx context.Context, workdir string)

PreDownHook runs before `docker compose down` in workdir.

type ProjectRun added in v1.4.15

type ProjectRun struct {
	Project string    // -p value; empty keeps compose's default project name
	Env     []string  // KEY=VALUE pairs appended to the inherited environment
	Stdout  io.Writer // nil discards
	Stderr  io.Writer // nil discards; the stderr tail still reaches the error
}

ProjectRun scopes one compose call to a named compose project with extra process environment (blue/green runs a second copy of the stack under its own -p name).

type RunSpec added in v1.4.13

type RunSpec struct {
	// Image is the full image reference (a digest-pinned one for production use).
	Image string
	// Args are the arguments handed to the image's entrypoint.
	Args []string
	// EnvPass maps an environment variable name to its value. Only the name
	// reaches argv (`-e NAME`); the value is set in the docker client's env.
	EnvPass map[string]string
	// Mounts are bind mounts; Source is a host path, Destination the in-container path.
	Mounts []Mount
	// User is "uid:gid"; empty leaves the image default.
	User string
	// Network is a docker network name; empty leaves the default bridge.
	Network string
	// PullNever refuses to pull a missing image (`--pull never`): the image must already exist locally.
	PullNever bool
	// ReadOnly mounts the root filesystem read-only (`--read-only`).
	ReadOnly bool
	// CapDrop lists capabilities to drop (`--cap-drop X`); "ALL" drops every one.
	CapDrop []string
	// SecurityOpt lists `--security-opt` values, e.g. "no-new-privileges:true".
	SecurityOpt []string
	// Name is the container name (`--name`); a caller that sets one can remove a
	// container a killed run left behind (RemoveContainer).
	Name string
	// Labels are `--label key=value` pairs, rendered in key order.
	Labels map[string]string
}

RunSpec describes one `docker run --rm` invocation.

type RunningService added in v1.4.13

type RunningService struct {
	Name       string
	Service    string
	State      string
	ConfigHash string // empty when the container has no config-hash label
}

RunningService is one container of the project as the daemon reports it.

func RunningConfigHashes added in v1.4.13

func RunningConfigHashes(ctx context.Context, projectName string) ([]RunningService, error)

RunningConfigHashes lists every container (any state) carrying the compose project label, with its service and config-hash labels. An error means the daemon could not be asked.

type ServiceMatch added in v1.4.13

type ServiceMatch struct {
	Service     string
	WorkingDirs []string
	Project     string
	AnyState    bool
}

ServiceMatch selects a compose service's container. A container matches when its com.docker.compose.service label equals Service and either its com.docker.compose.project.working_dir label is one of WorkingDirs or its com.docker.compose.project label equals Project (ignored when empty). Only running containers match unless AnyState is set.

type ServiceSpec added in v1.4.13

type ServiceSpec struct {
	Name           string `json:"name"`
	HasHealthcheck bool   `json:"has_healthcheck"`
	Restart        string `json:"restart"`

	// HealthTimeout is how long Docker may take to declare the healthcheck
	// failed: start_period + retries*(interval+timeout). 0 without a healthcheck
	// or when unknown (a spec built elsewhere). The latest Docker can still
	// report healthy before it would declare the container unhealthy.
	HealthTimeout time.Duration `json:"-"`
}

ServiceSpec is what the resolved compose model says about one service.

func ComposeServiceSpecs added in v1.4.13

func ComposeServiceSpecs(ctx context.Context, compose *Compose, workdir string) ([]ServiceSpec, error)

ComposeServiceSpecs reads the resolved config JSON over the compose's manifest and env files: one ServiceSpec per service, sorted by name.

func (ServiceSpec) OneShot added in v1.4.13

func (s ServiceSpec) OneShot() bool

OneShot reports a service that is meant to run once and exit: restart "no" and no healthcheck. A declared healthcheck wins (D17 order): such a service is long-running and is gated on healthy, never on exit.

type StateSource added in v1.4.13

type StateSource func(ctx context.Context) ([]ContainerState, error)

StateSource reads the service's containers; a remote host supplies its own. StartedAt on a running container lets the gate see a restart between polls; a source that leaves it empty still gets the two-poll check.

type SystemClock added in v1.4.13

type SystemClock struct{}

SystemClock is the real Clock.

func (SystemClock) Now added in v1.4.13

func (SystemClock) Now() time.Time

Now returns the wall clock time.

func (SystemClock) Sleep added in v1.4.13

func (SystemClock) Sleep(ctx context.Context, d time.Duration) error

Sleep waits d or until ctx is done.

Directories

Path Synopsis
Package dockertest decides whether a test that needs a Linux docker daemon runs, skips or fails on the current host (D-0286).
Package dockertest decides whether a test that needs a Linux docker daemon runs, skips or fails on the current host (D-0286).

Jump to

Keyboard shortcuts

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