diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index df64de6edf..afec744300 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -24,6 +24,7 @@ import ( "github.com/docker/docker/container" "github.com/docker/docker/daemon/config" "github.com/docker/docker/daemon/initlayer" + "github.com/docker/docker/errdefs" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" @@ -1290,12 +1291,26 @@ func (daemon *Daemon) registerLinks(container *container.Container, hostConfig * } child, err := daemon.GetContainer(name) if err != nil { + if errdefs.IsNotFound(err) { + // Trying to link to a non-existing container is not valid, and + // should return an "invalid parameter" error. Returning a "not + // found" error here would make the client report the container's + // image could not be found (see moby/moby#39823) + err = errdefs.InvalidParameter(err) + } return errors.Wrapf(err, "could not get container for %s", name) } for child.HostConfig.NetworkMode.IsContainer() { parts := strings.SplitN(string(child.HostConfig.NetworkMode), ":", 2) child, err = daemon.GetContainer(parts[1]) if err != nil { + if errdefs.IsNotFound(err) { + // Trying to link to a non-existing container is not valid, and + // should return an "invalid parameter" error. Returning a "not + // found" error here would make the client report the container's + // image could not be found (see moby/moby#39823) + err = errdefs.InvalidParameter(err) + } return errors.Wrapf(err, "Could not get container for %s", parts[1]) } } diff --git a/integration/container/create_test.go b/integration/container/create_test.go index b52f831715..b4bd23bce8 100644 --- a/integration/container/create_test.go +++ b/integration/container/create_test.go @@ -65,6 +65,28 @@ func TestCreateFailsWhenIdentifierDoesNotExist(t *testing.T) { } } +// TestCreateLinkToNonExistingContainer verifies that linking to a non-existing +// container returns an "invalid parameter" (400) status, and not the underlying +// "non exists" (404). +func TestCreateLinkToNonExistingContainer(t *testing.T) { + skip.If(t, testEnv.DaemonInfo.OSType == "windows", "legacy links are not supported on windows") + defer setupTest(t)() + c := testEnv.APIClient() + + _, err := c.ContainerCreate(context.Background(), + &container.Config{ + Image: "busybox", + }, + &container.HostConfig{ + Links: []string{"no-such-container"}, + }, + &network.NetworkingConfig{}, + "", + ) + assert.Check(t, is.ErrorContains(err, "could not get container for no-such-container")) + assert.Check(t, errdefs.IsInvalidParameter(err)) +} + func TestCreateWithInvalidEnv(t *testing.T) { defer setupTest(t)() client := testEnv.APIClient()