diff --git a/network-go/docker/docker.go b/network-go/docker/docker.go index 896314b..acb1ab9 100644 --- a/network-go/docker/docker.go +++ b/network-go/docker/docker.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "os/exec" + "regexp" "strings" "time" @@ -203,25 +204,37 @@ func (c *Client) AddRouteInContainer(ctx context.Context, containerName, network } // FindContainerName attempts to find a running container by name or selector. -// First tries the exact name, then tries listing running containers whose name -// starts with the selector prefix (or the name prefix), matching the old shell -// script's grep $D"-" behavior. +// First tries exact name match, then exact selector, then prefix matching +// (matching the old shell script's grep $D"-" behavior). func (c *Client) FindContainerName(ctx context.Context, name, selector string) (string, error) { - // First try the exact name - cont, err := c.cli.ContainerInspect(ctx, name) - if err == nil && cont.State != nil && cont.State.Running { - return name, nil + // Try exact name match using ContainerList with a name filter + // Docker API name filter does an exact match by default + containers, err := c.cli.ContainerList(ctx, container.ListOptions{ + Filters: filters.NewArgs( + filters.Arg("name", "^/?"+regexp.QuoteMeta(name)+"$"), + filters.Arg("status", "running"), + ), + }) + if err == nil && len(containers) > 0 { + cName := strings.TrimPrefix(containers[0].Names[0], "/") + return cName, nil } - // Try exact selector + // Try exact selector match if selector != "" && selector != name { - cont, err := c.cli.ContainerInspect(ctx, selector) - if err == nil && cont.State != nil && cont.State.Running { - return selector, nil + containers, err = c.cli.ContainerList(ctx, container.ListOptions{ + Filters: filters.NewArgs( + filters.Arg("name", "^/?"+regexp.QuoteMeta(selector)+"$"), + filters.Arg("status", "running"), + ), + }) + if err == nil && len(containers) > 0 { + cName := strings.TrimPrefix(containers[0].Names[0], "/") + return cName, nil } } - // Try prefix matching with selector (old shell script behavior: grep $D"-") + // Try prefix matching on both name and selector (shell script behavior: grep $D"-") candidates := []string{name, selector} for _, candidate := range candidates { if candidate == "" { @@ -233,21 +246,23 @@ func (c *Client) FindContainerName(ctx context.Context, name, selector string) ( prefix = candidate[:strings.Index(candidate, "-")] } - containers, err := c.cli.ContainerList(ctx, container.ListOptions{}) + containers, err = c.cli.ContainerList(ctx, container.ListOptions{ + Filters: filters.NewArgs( + filters.Arg("name", prefix+"-"), + filters.Arg("status", "running"), + ), + }) if err != nil { continue } - for _, container := range containers { - // Remove leading / from container names - for _, cName := range container.Names { + for _, c := range containers { + for _, cName := range c.Names { cName = strings.TrimPrefix(cName, "/") - if strings.HasPrefix(cName, prefix+"-") && container.State == "running" { - return cName, nil - } + return cName, nil } } } return "", fmt.Errorf("no running container found matching name=%q selector=%q", name, selector) -} \ No newline at end of file +}