fix: auto-detect containerd.sock path and conditionally start unregistry

This commit is contained in:
Pasha Sviderski
2025-09-23 15:10:34 +10:00
parent 9438654d99
commit 08f233c5b1
2 changed files with 58 additions and 28 deletions
+6 -2
View File
@@ -215,6 +215,7 @@ func (cc *clusterController) Run(ctx context.Context) error {
return nil return nil
}) })
if cc.unregistry != nil {
errGroup.Go(func() error { errGroup.Go(func() error {
slog.Info("Starting unregistry server.") slog.Info("Starting unregistry server.")
if err := cc.unregistry.ListenAndServe(); err != nil { if err := cc.unregistry.ListenAndServe(); err != nil {
@@ -222,6 +223,7 @@ func (cc *clusterController) Run(ctx context.Context) error {
} }
return nil return nil
}) })
}
// Wait for the context to be done and stop the network API server. // Wait for the context to be done and stop the network API server.
<-ctx.Done() <-ctx.Done()
@@ -230,7 +232,8 @@ func (cc *clusterController) Run(ctx context.Context) error {
cc.server.GracefulStop() cc.server.GracefulStop()
slog.Info("Network API server stopped.") slog.Info("Network API server stopped.")
// Stop the unregistry server with a timeout. // Stop the unregistry server with a timeout if it was started.
if cc.unregistry != nil {
unregTimeout := 30 * time.Second unregTimeout := 30 * time.Second
slog.Info("Stopping unregistry server.", "timeout", unregTimeout) slog.Info("Stopping unregistry server.", "timeout", unregTimeout)
unregCtx, cancel := context.WithTimeout(context.Background(), unregTimeout) unregCtx, cancel := context.WithTimeout(context.Background(), unregTimeout)
@@ -240,13 +243,14 @@ func (cc *clusterController) Run(ctx context.Context) error {
return fmt.Errorf("unregistry server forced to shutdown: %w", err) 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. // Wait for all controllers to finish.
err = errGroup.Wait() err = errGroup.Wait()
// It's safe to stop the Corrosion service after the controllers depending on it and API server are stopped. // 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. // 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() defer cancel()
if corroErr := cc.corroService.Stop(ctx); corroErr != nil { if corroErr := cc.corroService.Stop(ctx); corroErr != nil {
err = errors.Join(err, fmt.Errorf("stop corrosion service: %w", corroErr)) err = errors.Join(err, fmt.Errorf("stop corrosion service: %w", corroErr))
+29 -3
View File
@@ -64,6 +64,8 @@ type Config struct {
// DockerClient manages system and user containers using the local Docker daemon. // DockerClient manages system and user containers using the local Docker daemon.
DockerClient *client.Client 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 // 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. // 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 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 == "" { if cfg.CorrosionDir == "" {
cfg.CorrosionDir = filepath.Join(cfg.DataDir, "corrosion") cfg.CorrosionDir = filepath.Join(cfg.DataDir, "corrosion")
@@ -409,19 +431,23 @@ func (m *Machine) Run(ctx context.Context) error {
return fmt.Errorf("create embedded DNS server: %w", err) return fmt.Errorf("create embedded DNS server: %w", err)
} }
var unreg *unregistry.Registry
if m.config.ContainerdSockPath != "" {
// Create an embedded container registry listening on the machine IP address and // Create an embedded container registry listening on the machine IP address and
// using the local Docker (containerd) image store as its backend. // using the local Docker (containerd) image store as its backend.
unreg, err := unregistry.NewRegistry(unregistry.Config{ unreg, err = unregistry.NewRegistry(unregistry.Config{
Addr: net.JoinHostPort(m.IP().String(), strconv.Itoa(constants.UnregistryPort)), Addr: net.JoinHostPort(m.IP().String(), strconv.Itoa(constants.UnregistryPort)),
ContainerdNamespace: "moby", ContainerdNamespace: "moby",
// TODO: auto-detect the containerd.sock path used by Docker and/or allow configuring it. ContainerdSock: m.config.ContainerdSockPath,
ContainerdSock: "/run/containerd/containerd.sock",
LogFormatter: "text", LogFormatter: "text",
LogLevel: "info", LogLevel: "info",
}) })
if err != nil { if err != nil {
return fmt.Errorf("create embedded registry: %w", err) 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() m.mu.Lock()
m.clusterCtrl, err = newClusterController( m.clusterCtrl, err = newClusterController(