src/docker is the Docker CLI adapter layer for stackctl. It provides small typed wrappers around
Docker, Docker Compose, and Docker Swarm commands so higher level modules do not build or execute
Docker command lines directly.
The module is responsible for:
- Deploying a Swarm stack with
docker stack deploy. - Removing a Swarm stack with
docker stack rm. - Listing stack services and tasks with JSON formatted
docker stack servicesanddocker stack psoutput. - Streaming service logs through
docker service logs. - Updating a Swarm service through
docker service update. - Scaling a Swarm service through
docker service scale <name>=<replicas>. - Shutting a Swarm service down through
shutdownServiceinservice.ts, which scales an exact full service name to zero replicas and returns a structured result (scaled,would-scale,invalid, orerrorwith amissingflag for unknown services). - Evaluating deployed stack health through
checkStackHealthinhealth.ts, which derives unhealthy services from replica count mismatches (theReplicas"running/desired" field, unhealthy on any mismatch including running above desired) and failed or rejected taskCurrentStatevalues. Evaluation fails closed: malformed service/task JSON lines and unparseableReplicasvalues are recorded as errors and mark the affected stack and overall result unhealthy. This evaluation is read-only and command-driven; it never mutates Swarm state. - Reading Docker daemon information with
docker info. - Deriving Swarm activation status from
docker infoJSON output. - Normalizing Compose configuration with
docker compose -f <file> config.
- ProcessRunner boundary: Every external command is executed through the injected
ProcessRunner. This keeps the module deterministic in tests and prevents direct process spawning from Docker wrappers. - Thin command wrappers: Each exported function maps one Docker CLI operation to a
Promise<ProcessResult>or a parsed status object. The wrappers do not own business rules beyond command assembly and minimal result parsing. - Typed option objects: Optional CLI flags are represented by narrow interfaces such as
DockerDeployOptions,DockerLogsOptions, andDockerServiceUpdateOptions. - Argument vector construction: Commands are constructed as string arrays, not shell strings. This avoids shell interpolation and keeps command arguments explicit. Optional flags are appended conditionally before positional arguments such as stack names, service names, and compose file paths.
- JSON output contract: Commands that need machine readable output include
--format {{json .}}where Docker supports it.dockerSwarmStatusparses the JSON produced bydocker infoand converts it into a small domain specific result.
- A caller passes a
ProcessRunner, required identifiers such asstackName,serviceName, orcomposeFile, and optional typed settings. - The wrapper creates a command vector beginning with
dockerand the relevant subcommands. - Optional settings add flags in Docker CLI order. Examples include
--prune,--detach,--resolve-image,--force,--image,--tail,--since, and--timestamps. - Positional arguments are appended last, for example the stack name or service name.
- Most functions call
runner.run(cmd)and return the resultingProcessResultunchanged. dockerServiceLogscallsrunner.stream(cmd)because log following is a streaming operation. The--followflag is enabled by default and omitted only whenfollowis explicitlyfalse.dockerSwarmStatuscallsdocker info --format {{json .}}, checks command success, parsesstdoutas JSON, readsSwarm.LocalNodeState, and returns{ active: true, nodeId }only when the local node state isactive. Failed commands, invalid JSON, or inactive states return{ active: false }.shutdownService(inservice.ts) validates the service name against the Swarm name pattern, returnswould-scalewithout executing in dry-run mode, otherwise runsdocker service scale <name>=0and maps the result. Failed commands returnerror; a "No such service" stderr additionally flags the target asmissing.checkStackHealth(inhealth.ts) runsdockerStackServicesanddockerStackPsper stack, parses one JSON object per line, computesrunning/desiredfrom theReplicasfield, and collects tasks whoseCurrentStatestarts withFailedorRejected. A service is unhealthy when the parsed replica counts differ (including running above desired) or it has failed tasks. Malformed JSON lines and unparseableReplicasvalues fail closed: they are recorded inHealthCheckResult.errorsand mark the affected stack and overall result unhealthy, so the CLI exits nonzero. Query failures are handled the same way.
src/process: SuppliesProcessRunnerandProcessResult. Production code uses the real runner, while tests can inject fakes.src/compose: Produces compose files and rendered stack definitions that are later passed into Docker wrappers such asdockerStackDeployanddockerComposeConfig.src/cli: Orchestrates user facing commands and delegates Docker operations to this module instead of invoking Docker directly.- Docker CLI and Docker Swarm: The wrappers assume the
dockerexecutable is available in the runtime environment and preserve Docker's stdout, stderr, success state, and exit code throughProcessResultunless a function explicitly parses the output.