package backup import ( "context" "fmt" "os/exec" ) // ComposeExecutor runs docker compose commands. type ComposeExecutor struct { ProjectPath string ComposeFile string } // NewComposeExecutor creates an executor for a project. func NewComposeExecutor(projectPath, composeFile string) *ComposeExecutor { return &ComposeExecutor{ ProjectPath: projectPath, ComposeFile: composeFile, } } // Stop runs `docker compose -f stop`. func (e *ComposeExecutor) Stop(ctx context.Context) error { args := []string{"compose", "-f", e.ComposeFile, "stop"} cmd := exec.CommandContext(ctx, "docker", args...) cmd.Dir = e.ProjectPath out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("docker compose stop: %w\n%s", err, string(out)) } return nil } // Start runs `docker compose -f up -d`. func (e *ComposeExecutor) Start(ctx context.Context) error { args := []string{"compose", "-f", e.ComposeFile, "up", "-d"} cmd := exec.CommandContext(ctx, "docker", args...) cmd.Dir = e.ProjectPath out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("docker compose up -d: %w\n%s", err, string(out)) } return nil } // IsDockerAvailable checks whether docker is on PATH. func IsDockerAvailable() bool { _, err := exec.LookPath("docker") return err == nil }