Skip to content

Commit b33a58f

Browse files
authored
Merge pull request #2404 from gemini-platform/fix-tracker
fix: registry missing layer when concurrently push image
2 parents 2b560f0 + 5793cca commit b33a58f

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

pkg/cmd/image/push.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import (
3030
"github.com/containerd/containerd/reference"
3131
refdocker "github.com/containerd/containerd/reference/docker"
3232
"github.com/containerd/containerd/remotes"
33+
"github.com/containerd/containerd/remotes/docker"
34+
dockerconfig "github.com/containerd/containerd/remotes/docker/config"
3335
"github.com/containerd/nerdctl/pkg/api/types"
3436
"github.com/containerd/nerdctl/pkg/errutil"
3537
"github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver"
@@ -117,8 +119,15 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options
117119
logrus.Infof("pushing as an eStargz image (%s, %s)", esgzImg.Target.MediaType, esgzImg.Target.Digest)
118120
}
119121

122+
// In order to push images where most layers are the same but the
123+
// repository name is different, it is necessary to refresh the
124+
// PushTracker. Otherwise, the MANIFEST_BLOB_UNKNOWN error will occur due
125+
// to the registry not creating the corresponding layer link file,
126+
// resulting in the failure of the entire image push.
127+
pushTracker := docker.NewInMemoryTracker()
128+
120129
pushFunc := func(r remotes.Resolver) error {
121-
return push.Push(ctx, client, r, options.Stdout, pushRef, ref, platMC, options.AllowNondistributableArtifacts, options.Quiet)
130+
return push.Push(ctx, client, r, pushTracker, options.Stdout, pushRef, ref, platMC, options.AllowNondistributableArtifacts, options.Quiet)
122131
}
123132

124133
var dOpts []dockerconfigresolver.Opt
@@ -127,10 +136,18 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options
127136
dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true))
128137
}
129138
dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(options.GOptions.HostsDir))
130-
resolver, err := dockerconfigresolver.New(ctx, refDomain, dOpts...)
139+
140+
ho, err := dockerconfigresolver.NewHostOptions(ctx, refDomain, dOpts...)
131141
if err != nil {
132142
return err
133143
}
144+
145+
resolverOpts := docker.ResolverOptions{
146+
Tracker: pushTracker,
147+
Hosts: dockerconfig.ConfigureHosts(ctx, *ho),
148+
}
149+
150+
resolver := docker.NewResolver(resolverOpts)
134151
if err = pushFunc(resolver); err != nil {
135152
// In some circumstance (e.g. people just use 80 port to support pure http), the error will contain message like "dial tcp <port>: connection refused"
136153
if !errutil.IsErrHTTPResponseToHTTPSClient(err) && !errutil.IsErrConnectionRefused(err) {

pkg/imgutil/push/push.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,22 @@ import (
3232
"github.com/containerd/containerd/platforms"
3333
"github.com/containerd/containerd/remotes"
3434
"github.com/containerd/containerd/remotes/docker"
35-
"github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver"
3635
"github.com/containerd/nerdctl/pkg/imgutil/jobs"
3736
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
3837

3938
"golang.org/x/sync/errgroup"
4039
)
4140

4241
// Push pushes an image to a remote registry.
43-
func Push(ctx context.Context, client *containerd.Client, resolver remotes.Resolver, stdout io.Writer,
42+
func Push(ctx context.Context, client *containerd.Client, resolver remotes.Resolver, pushTracker docker.StatusTracker, stdout io.Writer,
4443
localRef, remoteRef string, platform platforms.MatchComparer, allowNonDist, quiet bool) error {
4544
img, err := client.ImageService().Get(ctx, localRef)
4645
if err != nil {
4746
return fmt.Errorf("unable to resolve image to manifest: %w", err)
4847
}
4948
desc := img.Target
5049

51-
ongoing := newPushJobs(dockerconfigresolver.PushTracker)
50+
ongoing := newPushJobs(pushTracker)
5251

5352
eg, ctx := errgroup.WithContext(ctx)
5453

0 commit comments

Comments
 (0)