dockerexec

package
v0.4.18 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package dockerexec is the write-plane exec wrapper: it shells out to `docker compose` with STATIC ARGV only — never a shell, never string interpolation, always a `--` terminator before service names (plan §3, §5.6). It enforces the global one-docker-child semaphore and the ≥1 GB write-plane gate, and reaps the whole process group on context cancellation.

Index

Constants

This section is empty.

Variables

View Source
var ErrBusy = errors.New("dockerexec: another docker operation is in progress")

ErrBusy is returned when the one-docker-child semaphore could not be acquired.

View Source
var ErrWritePlaneDisabled = errors.New("dockerexec: write plane disabled (host below the 1 GB resource gate)")

ErrWritePlaneDisabled is returned when the host is below the §0 resource gate.

Functions

func WritePlaneGate

func WritePlaneGate(memTotal uint64) (bool, string)

WritePlaneGate decides whether the write plane is armed from the host's total RAM. memTotal==0 means unknown (non-Linux dev) → armed, with a caveat note.

Types

type Job

type Job struct {
	Project     string
	Dir         string
	ConfigFiles []string
	EnvFile     string   // optional 0600 --env-file rendered from the env store
	Action      []string // e.g. ["up","-d","--force-recreate"]
	Service     string   // optional; appended after a "--" terminator
}

Job is one `docker compose` invocation. Project/Dir/ConfigFiles come from the app's compose labels; they are passed as discrete argv elements (no shell), so they cannot inject commands.

type Runner

type Runner struct {
	// contains filtered or unexported fields
}

Runner executes Jobs under the gate + semaphore.

func NewRunner

func NewRunner(sem *Semaphore, writeAllowed bool, writeReason string) *Runner

NewRunner builds a Runner. writeAllowed/writeReason come from the §0 gate.

func (*Runner) PruneBuildCache added in v0.4.16

func (r *Runner) PruneBuildCache(ctx context.Context, keep string, onLine func(string)) error

PruneBuildCache reclaims BuildKit build cache, keeping at most `keep` of the most-recently-used cache (LRU eviction): `docker builder prune -a -f --keep-storage <keep>`. It runs under the §0 write gate + the one-docker-child semaphore, exactly like a deploy. `keep` is a validated size (e.g. "5GB") passed as a discrete argv element (no shell). Best-effort by design — callers log the outcome and never fail a deploy on error.

func (*Runner) Run

func (r *Runner) Run(ctx context.Context, job Job, onLine func(string)) error

Run executes the job, invoking onLine for each (truncated) output line. It acquires the semaphore (blocking on ctx), and on ctx cancellation kills the whole process group and reaps it. Returns the command error (incl. non-zero exit) or a gate/semaphore error.

func (*Runner) RunHeld

func (r *Runner) RunHeld(ctx context.Context, job Job, onLine func(string)) error

RunHeld is Run for a caller that ALREADY HOLDS the one-docker-child semaphore (the self-healing supervisor, which acquires it non-blocking via its safety gate so it never queues a docker child). It must not be called without holding the semaphore.

func (*Runner) RunInternal

func (r *Runner) RunInternal(ctx context.Context, job Job, onLine func(string)) error

RunInternal runs a Mooring-OWNED infrastructure job (bringing up the embedded read-only socket-proxy) REGARDLESS of the §0 write-plane resource gate — the read plane must come up even on a sub-1 GB box. It is NOT for app workloads: the caller passes a fixed, embedded, Mooring-authored compose (never operator input), so it bypasses the RAM gate while keeping the static-argv discipline, the one-docker-child semaphore, and process-group reaping. It acquires the semaphore (blocking on ctx) like Run.

func (*Runner) WriteAllowed

func (r *Runner) WriteAllowed() (bool, string)

WriteAllowed reports whether the write plane is armed, and why not if not.

type Semaphore

type Semaphore struct {
	// contains filtered or unexported fields
}

Semaphore caps concurrent `docker` children at 1 across the whole process (poller stats go through the proxy and don't count; only exec children do). Remediation/scale-up use TryAcquire (never queue — queuing children IS the OOM vector, plan §4).

func NewSemaphore

func NewSemaphore() *Semaphore

NewSemaphore returns the global one-docker-child semaphore.

func (*Semaphore) Acquire

func (s *Semaphore) Acquire(ctx context.Context) error

Acquire blocks until the slot is free or ctx is done.

func (*Semaphore) Release

func (s *Semaphore) Release()

Release frees the slot.

func (*Semaphore) TryAcquire

func (s *Semaphore) TryAcquire() bool

TryAcquire grabs the slot without blocking; false means held.

Jump to

Keyboard shortcuts

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