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 <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2025-04-22 16:23:41 +02:00
parent 61c6818f0b
commit bcb36e26cb
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C

View File

@ -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
}