From 510369170afd3c43d6a5fbb203372f701dfea29e Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Thu, 22 Jan 2026 14:54:12 -0800 Subject: [PATCH 1/2] imagetools: fix excessive copies on create command Currently needed manifests were filtered out and then copied in a loop, but for each copy still the full unfiltered descriptor was copied instead of single manifest, resulting multiple push attempts for same descriptor. Signed-off-by: Tonis Tiigi --- commands/imagetools/create.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/commands/imagetools/create.go b/commands/imagetools/create.go index 6f7903eea116..b8c9d97a042a 100644 --- a/commands/imagetools/create.go +++ b/commands/imagetools/create.go @@ -208,7 +208,10 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg for _, desc := range manifests { eg2.Go(func() error { sub.Log(1, fmt.Appendf(nil, "copying %s from %s to %s\n", desc.Digest.String(), desc.Source.Ref.String(), t.String())) - return r.Copy(ctx, desc.Source, t) + return r.Copy(ctx, &imagetools.Source{ + Ref: desc.Source.Ref, + Desc: desc.Descriptor, + }, t) }) } if err := eg2.Wait(); err != nil { From 87c77aca7bf244d0bcdb9d71c5cf0160bcfb1569 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Thu, 22 Jan 2026 15:46:15 -0800 Subject: [PATCH 2/2] imagetools: avoid trying to load attestations inline references When creating resulting image index it is wasteful to check for attestations for the descriptors in original index what were already attestation for subject manifest. Signed-off-by: Tonis Tiigi --- commands/imagetools/create.go | 22 +++++++++++++++++----- util/imagetools/create.go | 3 +++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/commands/imagetools/create.go b/commands/imagetools/create.go index b8c9d97a042a..df28603daad0 100644 --- a/commands/imagetools/create.go +++ b/commands/imagetools/create.go @@ -200,25 +200,37 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg eg, _ := errgroup.WithContext(ctx) pw := progress.WithPrefix(printer, "internal", true) + tagsByRepo := map[string][]reference.Named{} for _, t := range tags { + repo := t.Name() + tagsByRepo[repo] = append(tagsByRepo[repo], t) + } + + for repo, repoTags := range tagsByRepo { eg.Go(func() error { - return progress.Wrap(fmt.Sprintf("pushing %s", t.String()), pw.Write, func(sub progress.SubLogger) error { + seed := repoTags[0] + return progress.Wrap(fmt.Sprintf("pushing %s", repo), pw.Write, func(sub progress.SubLogger) error { ctx = withMediaTypeKeyPrefix(ctx) eg2, _ := errgroup.WithContext(ctx) for _, desc := range manifests { eg2.Go(func() error { - sub.Log(1, fmt.Appendf(nil, "copying %s from %s to %s\n", desc.Digest.String(), desc.Source.Ref.String(), t.String())) + sub.Log(1, fmt.Appendf(nil, "copying %s from %s to %s\n", desc.Digest.String(), desc.Source.Ref.String(), repo)) return r.Copy(ctx, &imagetools.Source{ Ref: desc.Source.Ref, Desc: desc.Descriptor, - }, t) + }, seed) }) } if err := eg2.Wait(); err != nil { return err } - sub.Log(1, fmt.Appendf(nil, "pushing %s to %s\n", desc.Digest.String(), t.String())) - return r.Push(ctx, t, desc, dt) + for _, t := range repoTags { + sub.Log(1, fmt.Appendf(nil, "pushing %s to %s\n", desc.Digest.String(), t.String())) + if err := r.Push(ctx, t, desc, dt); err != nil { + return err + } + } + return nil }) }) } diff --git a/util/imagetools/create.go b/util/imagetools/create.go index 60db747a47fd..979b3f7793b4 100644 --- a/util/imagetools/create.go +++ b/util/imagetools/create.go @@ -429,6 +429,9 @@ func (r *Resolver) filterPlatforms(ctx context.Context, dt []byte, desc ocispecs // try to pull in attestation manifest via referrer if one exists addedRef := false for d := range matchedManifests { + if _, ok := references[d]; ok { // manifest itself is already attestation + continue + } hasRef := false for _, subject := range references { if subject.Digest == d {