From bcb36e26cbf921bd7bc788c2f6d4a0e82fe22b39 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 22 Apr 2025 16:23:41 +0200 Subject: [PATCH] stack deploy: fail early on invalid image reference format Before this patch, `docker stack deploy` would not validate the image reference on the client side, depending on the daemon to return an error, which was not always easy to interpret; docker stack deploy -c docker-compose.yaml mystack Creating service mystack_myservice failed to create service mystack_myservice: Error response from daemon: rpc error: code = InvalidArgument desc = ContainerSpec: image reference must be provided IMAGE_NAME=FOOBAR docker stack deploy -c docker-compose.yaml mystack Creating service mystack_myservice failed to create service mystack_myservice: Error response from daemon: rpc error: code = InvalidArgument desc = ContainerSpec: "FOOBAR" is not a valid repository/tag With this patch, the CLI validates the image-reference for each service, producing an error if the reference is empty or invalid. docker stack config -c docker-compose.yaml invalid service myservice: no image specified IMAGE_NAME=FOOBAR ~/Projects/cli/build/docker stack deploy -c docker-compose.yaml mystack invalid image reference for service myservice: invalid reference format: repository name (library/FOOBAR) must be lowercase Signed-off-by: Sebastiaan van Stijn --- cli/command/stack/loader/loader.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cli/command/stack/loader/loader.go b/cli/command/stack/loader/loader.go index 43f227a42c..75d485b014 100644 --- a/cli/command/stack/loader/loader.go +++ b/cli/command/stack/loader/loader.go @@ -12,6 +12,7 @@ import ( "sort" "strings" + "github.com/distribution/reference" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/stack/options" "github.com/docker/cli/cli/compose/loader" @@ -49,6 +50,17 @@ func LoadComposefile(dockerCli command.Cli, opts options.Deploy) (*composetypes. _, _ = fmt.Fprintf(dockerCli.Err(), "Ignoring deprecated options:\n\n%s\n\n", propertyWarnings(deprecatedProperties)) } + + // Validate if each service has a valid image-reference. + for _, svc := range config.Services { + if svc.Image == "" { + return nil, errors.Errorf("invalid image reference for service %s: no image specified", svc.Name) + } + if _, err := reference.ParseAnyReference(svc.Image); err != nil { + return nil, errors.Wrapf(err, "invalid image reference for service %s", svc.Name) + } + } + return config, nil }