docker/compose · error

%q attribute is mandatory to push an image for service %q

Error message

%q attribute is mandatory to push an image for service %q

What it means

Raised by push when the caller set ImageMandatory and a service has no build section and no image attribute (and no provider). Without an image name there is nothing to tag or push, so compose refuses instead of silently skipping; services with build or image are unaffected.

Source

Thrown at pkg/compose/push.go:55

)

func (s *composeService) Push(ctx context.Context, project *types.Project, options api.PushOptions) error {
	if options.Quiet {
		return s.push(ctx, project, options)
	}
	return Run(ctx, func(ctx context.Context) error {
		return s.push(ctx, project, options)
	}, "push", s.events)
}

func (s *composeService) push(ctx context.Context, project *types.Project, options api.PushOptions) error {
	eg, ctx := errgroup.WithContext(ctx)
	eg.SetLimit(s.maxConcurrency)

	for _, service := range project.Services {
		if service.Build == nil || service.Image == "" {
			if options.ImageMandatory && service.Image == "" && service.Provider == nil {
				return fmt.Errorf("%q attribute is mandatory to push an image for service %q", "service.image", service.Name)
			}
			s.events.On(api.Resource{
				ID:     service.Name,
				Status: api.Done,
				Text:   "Skipped",
			})
			continue
		}
		tags := []string{service.Image}
		if service.Build != nil {
			tags = append(tags, service.Build.Tags...)
		}

		for _, tag := range tags {
			eg.Go(func() error {
				s.events.On(newEvent(tag, api.Working, "Pushing"))
				err := s.pushServiceImage(ctx, tag, options.Quiet)
				if err != nil {

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Add an explicit image: <registry>/<repo>:<tag> to the service named in the error.
  2. If the service should not be pushed, exclude it from the push selection (push specific services only).
  3. If skipping is acceptable, clear the ImageMandatory option so the service is skipped with a 'Skipped' event instead of failing.
  4. Add a build: section if the image is meant to be built and pushed under service.image.

Example fix

# before
services:
  migrate:
    build: .            # no image: → push fails when mandatory

# after
services:
  migrate:
    build: .
    image: registry.example.com/team/migrate:1.2.0
Defensive patterns

Strategy: validation

Validate before calling

func allServicesPushable(project *types.Project) error {
	for name, svc := range project.Services {
		if svc.Image == "" && svc.Build == nil && svc.Provider == nil {
			return fmt.Errorf("service %q lacks image and build; not pushable", name)
		}
	}
	return nil
}

Try / catch

if err := composeService.Push(ctx, project, api.PushOptions{ImageMandatory: true}); err != nil {
    if strings.Contains(err.Error(), "attribute is mandatory to push an image") {
        // add image: to the named service or drop ImageMandatory
    }
    return err
}

Prevention

When it happens

Trigger: Running push with the image-mandatory option (mirrors docker compose push --ignore-buildable-failure=false semantics) on a project where a service omits image: and is not built from a Dockerfile.

Common situations: Copy-pasted service blocks missing the image key; services intended only as run-once utilities without an image; CI enforcing that every pushable service is explicitly tagged.

Related errors


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/509af9fbf4012251. Report an issue: GitHub.