diff --git a/daemon/container.go b/daemon/container.go index 4113227115..24092151df 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -1,11 +1,16 @@ +// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: +//go:build go1.23 + package daemon import ( "context" "fmt" + "maps" "os" "path/filepath" "runtime" + "slices" "strings" "time" @@ -196,6 +201,31 @@ func (daemon *Daemon) GetByName(name string) (*container.Container, error) { return e, nil } +// GetDependentContainers returns a list of containers that depend on the given container. +// Dependencies are determined by: +// - Network mode dependencies (--network=container:xxx) +// - Legacy container links (--link) +// +// This is primarily used during daemon startup to determine container startup order, +// ensuring that dependent containers are started after their dependencies are running. +// Upon error, it returns the last known dependent containers, which may be empty. +func (daemon *Daemon) GetDependentContainers(c *container.Container) []*container.Container { + var dependentContainers []*container.Container + + if c.HostConfig.NetworkMode.IsContainer() { + // If the container is using a network mode that depends on another container, + // we need to find that container and add it to the dependency map. + dependencyContainer, err := daemon.GetContainer(c.HostConfig.NetworkMode.ConnectedContainer()) + if err != nil { + log.G(context.TODO()).WithError(err).Errorf("Could not find dependent container for %s", c.ID) + return dependentContainers + } + dependentContainers = append(dependentContainers, dependencyContainer) + } + + return append(dependentContainers, slices.Collect(maps.Values(daemon.linkIndex.children(c)))...) +} + func (daemon *Daemon) setSecurityOptions(cfg *config.Config, container *container.Container, hostConfig *containertypes.HostConfig) error { container.Lock() defer container.Unlock() diff --git a/daemon/daemon.go b/daemon/daemon.go index bbe2aea48c..4e91648aab 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -575,8 +575,8 @@ func (daemon *Daemon) restore(cfg *configStore) error { logger.Debug("starting container") // ignore errors here as this is a best effort to wait for children - // (legacy links) to be running before we try to start the container - if children := daemon.linkIndex.children(c); len(children) > 0 { + // (legacy links or container network) to be running before we try to start the container + if children := daemon.GetDependentContainers(c); len(children) > 0 { timeout := time.NewTimer(5 * time.Second) defer timeout.Stop()