The hub no longer probes a node's Docker on tcp :2375, holds compose files
for a node, or runs compose against another machine's Docker. hubStacks,
nodeDocker, taskOnHub and the hub-side /api/nodes/{node}/docker/... routes
are gone; the generic node proxy hands those requests to the node's own
Ham Lab. Stack.remote / held_by and compose.Spec.Remote are removed.
New stacks default to <data dir>/stacks on every machine. Folders with two
or more deployed stacks are still offered, after it, never as default.
The ~/stacks fallback is gone. A missing home is skipped without a sudo find.
A schedule saved earlier with a tcp target is refused with a message
instead of being run against this machine's Docker.
PORTABILITY.md 3.1, 3.2, 3.3 and 9.2 done; 3.5 checked, no change needed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
43 lines
1.5 KiB
Go
43 lines
1.5 KiB
Go
// Package compose runs docker compose the way a stack was deployed — which is not always
|
|
// simply "on this host". A stack deployed by an orchestrator running inside its own
|
|
// container records paths in that container's filesystem, so compose has to run in there.
|
|
// Both the console and the scheduled updates it writes must invoke it identically, or a
|
|
// redeploy from one would not match the other's labels. Compose always drives this
|
|
// machine's own Docker: a stack's files and its containers are on the same box.
|
|
package compose
|
|
|
|
import (
|
|
"context"
|
|
"os/exec"
|
|
"path/filepath"
|
|
)
|
|
|
|
// Spec is everything needed to run compose for one stack.
|
|
type Spec struct {
|
|
Project string // -p
|
|
Files []string // -f, in order
|
|
Via string // a container to run compose inside; "" is this host
|
|
Tool string // "docker" or "podman"
|
|
}
|
|
|
|
// Cmd builds the command. args are compose's own, e.g. "pull" or "up", "-d".
|
|
func Cmd(ctx context.Context, s Spec, args ...string) *exec.Cmd {
|
|
tool := s.Tool
|
|
if tool == "" {
|
|
tool = "docker"
|
|
}
|
|
base := []string{"compose", "-p", s.Project}
|
|
for _, f := range s.Files {
|
|
base = append(base, "-f", f)
|
|
}
|
|
if s.Via != "" {
|
|
// The CLI inside the orchestrator's container is its own `docker`, whatever this host runs.
|
|
return exec.CommandContext(ctx, tool, append(append([]string{"exec", s.Via, "docker"}, base...), args...)...)
|
|
}
|
|
cmd := exec.CommandContext(ctx, tool, append(base, args...)...)
|
|
if len(s.Files) > 0 {
|
|
cmd.Dir = filepath.Dir(s.Files[0])
|
|
}
|
|
return cmd
|
|
}
|