From 08f233c5b1f11259ddd327f0ac9bbd9ff4b9e810 Mon Sep 17 00:00:00 2001 From: Pasha Sviderski Date: Tue, 23 Sep 2025 15:10:34 +1000 Subject: [PATCH] fix: auto-detect containerd.sock path and conditionally start unregistry --- internal/machine/cluster.go | 36 ++++++++++++++------------ internal/machine/machine.go | 50 ++++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/internal/machine/cluster.go b/internal/machine/cluster.go index 258e3225..9dab4f5d 100644 --- a/internal/machine/cluster.go +++ b/internal/machine/cluster.go @@ -215,13 +215,15 @@ func (cc *clusterController) Run(ctx context.Context) error { return nil }) - errGroup.Go(func() error { - slog.Info("Starting unregistry server.") - if err := cc.unregistry.ListenAndServe(); err != nil { - return fmt.Errorf("unregistry server failed: %w", err) - } - return nil - }) + if cc.unregistry != nil { + errGroup.Go(func() error { + slog.Info("Starting unregistry server.") + if err := cc.unregistry.ListenAndServe(); err != nil { + return fmt.Errorf("unregistry server failed: %w", err) + } + return nil + }) + } // Wait for the context to be done and stop the network API server. <-ctx.Done() @@ -230,23 +232,25 @@ func (cc *clusterController) Run(ctx context.Context) error { cc.server.GracefulStop() slog.Info("Network API server stopped.") - // Stop the unregistry server with a timeout. - unregTimeout := 30 * time.Second - slog.Info("Stopping unregistry server.", "timeout", unregTimeout) - unregCtx, cancel := context.WithTimeout(context.Background(), unregTimeout) - defer cancel() + // Stop the unregistry server with a timeout if it was started. + if cc.unregistry != nil { + unregTimeout := 30 * time.Second + slog.Info("Stopping unregistry server.", "timeout", unregTimeout) + unregCtx, cancel := context.WithTimeout(context.Background(), unregTimeout) + defer cancel() - if err = cc.unregistry.Shutdown(unregCtx); err != nil { - return fmt.Errorf("unregistry server forced to shutdown: %w", err) + if err = cc.unregistry.Shutdown(unregCtx); err != nil { + return fmt.Errorf("unregistry server forced to shutdown: %w", err) + } + slog.Info("Unregistry server stopped.") } - slog.Info("Unregistry server stopped.") // Wait for all controllers to finish. err = errGroup.Wait() // It's safe to stop the Corrosion service after the controllers depending on it and API server are stopped. // Use a new context with a timeout as the current context is already canceled. - ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if corroErr := cc.corroService.Stop(ctx); corroErr != nil { err = errors.Join(err, fmt.Errorf("stop corrosion service: %w", corroErr)) diff --git a/internal/machine/machine.go b/internal/machine/machine.go index 6cd4992a..28c30728 100644 --- a/internal/machine/machine.go +++ b/internal/machine/machine.go @@ -64,6 +64,8 @@ type Config struct { // DockerClient manages system and user containers using the local Docker daemon. DockerClient *client.Client + // ContainerdSockPath is the path to the containerd.sock used by Docker. + ContainerdSockPath string // CaddyConfigDir specifies the directory where the machine generates the Caddy reverse proxy configuration file // for routing external traffic to service containers across the internal network. Default is DataDir/caddy. @@ -94,6 +96,26 @@ func (c *Config) SetDefaults() (*Config, error) { } cfg.DockerClient = cli } + if cfg.ContainerdSockPath == "" { + // Auto-detect the containerd.sock path used by Docker. + paths := []string{ + "/run/containerd/containerd.sock", // Default path on most Linux distributions. + "/run/docker/containerd/containerd.sock", + "/var/run/containerd/containerd.sock", + "/var/run/docker/containerd/containerd.sock", + } + for _, path := range paths { + if _, err := os.Stat(path); err == nil { + cfg.ContainerdSockPath = path + slog.Debug("Detected containerd socket used by Docker.", "path", path) + break + } + } + + if cfg.ContainerdSockPath == "" { + slog.Warn("Failed to auto-detect containerd socket used by Docker.") + } + } if cfg.CorrosionDir == "" { cfg.CorrosionDir = filepath.Join(cfg.DataDir, "corrosion") @@ -409,18 +431,22 @@ func (m *Machine) Run(ctx context.Context) error { return fmt.Errorf("create embedded DNS server: %w", err) } - // Create an embedded container registry listening on the machine IP address and - // using the local Docker (containerd) image store as its backend. - unreg, err := unregistry.NewRegistry(unregistry.Config{ - Addr: net.JoinHostPort(m.IP().String(), strconv.Itoa(constants.UnregistryPort)), - ContainerdNamespace: "moby", - // TODO: auto-detect the containerd.sock path used by Docker and/or allow configuring it. - ContainerdSock: "/run/containerd/containerd.sock", - LogFormatter: "text", - LogLevel: "info", - }) - if err != nil { - return fmt.Errorf("create embedded registry: %w", err) + var unreg *unregistry.Registry + if m.config.ContainerdSockPath != "" { + // Create an embedded container registry listening on the machine IP address and + // using the local Docker (containerd) image store as its backend. + unreg, err = unregistry.NewRegistry(unregistry.Config{ + Addr: net.JoinHostPort(m.IP().String(), strconv.Itoa(constants.UnregistryPort)), + ContainerdNamespace: "moby", + ContainerdSock: m.config.ContainerdSockPath, + LogFormatter: "text", + LogLevel: "info", + }) + if err != nil { + return fmt.Errorf("create embedded registry: %w", err) + } + } else { + slog.Warn("Skipping embedded unregistry setup as the containerd socket path is not configured.") } m.mu.Lock()