c8d: delete dangling image on pull
<!--
Please make sure you've read and understood our contributing guidelines;
https://github.com/moby/moby/blob/master/CONTRIBUTING.md

** Make sure all your commits include a signature generated with `git commit -s` **

For additional information on our contributing process, read our contributing
guide https://docs.docker.com/opensource/code/

If this is a bug fix, make sure your description includes "fixes #xxxx", or
"closes #xxxx"

Please provide the following information:
-->

**- What I did**

fix https://github.com/moby/moby/issues/45430

**- How to verify it**

Pull an image with a target that matches the target of a local dangling image, and verify that the dangling image has been removed.

**- Description for the changelog**
<!--
Write a short (one line) summary that describes the changes in this
pull request for inclusion in the changelog:
-->


**- A picture of a cute animal (not mandatory but encouraged)**

![image](https://user-images.githubusercontent.com/70572044/235155009-e4fbea69-a598-488b-a90e-10cf84aad8a5.png)



daemon/containerd/image_pull.go
package containerd

import (
	"context"
	"io"

	"github.com/containerd/containerd"
	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/pkg/snapshotters"
	"github.com/containerd/containerd/platforms"
	"github.com/docker/distribution/reference"
	"github.com/docker/docker/api/types/registry"
	"github.com/docker/docker/errdefs"
	"github.com/docker/docker/pkg/streamformatter"
	"github.com/opencontainers/go-digest"
	specs "github.com/opencontainers/image-spec/specs-go/v1"
)

// PullImage initiates a pull operation. image is the repository name to pull, and
// tagOrDigest may be either empty, or indicate a specific tag or digest to pull.
func (i *ImageService) PullImage(ctx context.Context, image, tagOrDigest string, platform *specs.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error {
	var opts []containerd.RemoteOpt
	if platform != nil {
		opts = append(opts, containerd.WithPlatform(platforms.Format(*platform)))
	}
	ref, err := reference.ParseNormalizedNamed(image)
	if err != nil {
		return errdefs.InvalidParameter(err)
	}

	// TODO(thaJeztah) this could use a WithTagOrDigest() utility
	if tagOrDigest != "" {
		// The "tag" could actually be a digest.
		var dgst digest.Digest
		dgst, err = digest.Parse(tagOrDigest)
		if err == nil {
			ref, err = reference.WithDigest(reference.TrimNamed(ref), dgst)
		} else {
			ref, err = reference.WithTag(ref, tagOrDigest)
		}
		if err != nil {
			return errdefs.InvalidParameter(err)
		}
	}

	resolver, _ := i.newResolverFromAuthConfig(authConfig)
	opts = append(opts, containerd.WithResolver(resolver))

	jobs := newJobs()
	h := images.HandlerFunc(func(ctx context.Context, desc specs.Descriptor) ([]specs.Descriptor, error) {
		if desc.MediaType != images.MediaTypeDockerSchema1Manifest {
			jobs.Add(desc)
		}
		return nil, nil
	})
	opts = append(opts, containerd.WithImageHandler(h))

	out := streamformatter.NewJSONProgressOutput(outStream, false)
	finishProgress := jobs.showProgress(ctx, out, pullProgress{Store: i.client.ContentStore(), ShowExists: true})
	defer finishProgress()

	opts = append(opts, containerd.WithPullUnpack)
	// TODO(thaJeztah): we may have to pass the snapshotter to use if the pull is part of a "docker run" (container create -> pull image if missing). See https://github.com/moby/moby/issues/45273
	opts = append(opts, containerd.WithPullSnapshotter(i.snapshotter))

	// AppendInfoHandlerWrapper will annotate the image with basic information like manifest and layer digests as labels;
	// this information is used to enable remote snapshotters like nydus and stargz to query a registry.
	infoHandler := snapshotters.AppendInfoHandlerWrapper(ref.String())
	opts = append(opts, containerd.WithImageHandlerWrapper(infoHandler))

	_, err = i.client.Pull(ctx, ref.String(), opts...)
	return err
}

package containerd

import (
	"context"
	"io"

	"github.com/containerd/containerd"
	cerrdefs "github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/pkg/snapshotters"
	"github.com/containerd/containerd/platforms"
	"github.com/docker/distribution/reference"
	"github.com/docker/docker/api/types/registry"
	"github.com/docker/docker/errdefs"
	"github.com/docker/docker/pkg/streamformatter"
	"github.com/opencontainers/go-digest"
	specs "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/sirupsen/logrus"
)

// PullImage initiates a pull operation. image is the repository name to pull, and
// tagOrDigest may be either empty, or indicate a specific tag or digest to pull.
func (i *ImageService) PullImage(ctx context.Context, image, tagOrDigest string, platform *specs.Platform, metaHeaders map[string][]string, authConfig *registry.AuthConfig, outStream io.Writer) error {
	var opts []containerd.RemoteOpt
	if platform != nil {
		opts = append(opts, containerd.WithPlatform(platforms.Format(*platform)))
	}
	ref, err := reference.ParseNormalizedNamed(image)
	if err != nil {
		return errdefs.InvalidParameter(err)
	}

	// TODO(thaJeztah) this could use a WithTagOrDigest() utility
	if tagOrDigest != "" {
		// The "tag" could actually be a digest.
		var dgst digest.Digest
		dgst, err = digest.Parse(tagOrDigest)
		if err == nil {
			ref, err = reference.WithDigest(reference.TrimNamed(ref), dgst)
		} else {
			ref, err = reference.WithTag(ref, tagOrDigest)
		}
		if err != nil {
			return errdefs.InvalidParameter(err)
		}
	}

	resolver, _ := i.newResolverFromAuthConfig(authConfig)
	opts = append(opts, containerd.WithResolver(resolver))

	jobs := newJobs()
	h := images.HandlerFunc(func(ctx context.Context, desc specs.Descriptor) ([]specs.Descriptor, error) {
		if desc.MediaType != images.MediaTypeDockerSchema1Manifest {
			jobs.Add(desc)
		}
		return nil, nil
	})
	opts = append(opts, containerd.WithImageHandler(h))

	out := streamformatter.NewJSONProgressOutput(outStream, false)
	finishProgress := jobs.showProgress(ctx, out, pullProgress{Store: i.client.ContentStore(), ShowExists: true})
	defer finishProgress()

	opts = append(opts, containerd.WithPullUnpack)
	// TODO(thaJeztah): we may have to pass the snapshotter to use if the pull is part of a "docker run" (container create -> pull image if missing). See https://github.com/moby/moby/issues/45273
	opts = append(opts, containerd.WithPullSnapshotter(i.snapshotter))

	// AppendInfoHandlerWrapper will annotate the image with basic information like manifest and layer digests as labels;
	// this information is used to enable remote snapshotters like nydus and stargz to query a registry.
	infoHandler := snapshotters.AppendInfoHandlerWrapper(ref.String())
	opts = append(opts, containerd.WithImageHandlerWrapper(infoHandler))

	img, err := i.client.Pull(ctx, ref.String(), opts...)
	if err != nil {
		return err
	}

	logger := logrus.WithFields(logrus.Fields{
		"digest": img.Target().Digest,
		"remote": ref.String(),
	})
	logger.Info("image pulled")

	// The pull succeeded, so try to remove any dangling image we have for this target
	err = i.client.ImageService().Delete(context.Background(), danglingImageName(img.Target().Digest))
	if err != nil && !cerrdefs.IsNotFound(err) {
		// Image pull succeeded, but cleaning up the dangling image failed. Ignore the
		// error to not mark the pull as failed.
		logger.WithError(err).Warn("unexpected error while removing outdated dangling image reference")
	}
	return nil
}

Wondering if we should just use `digest` and `remote` for this (instead of `imageID` and `tag`).


Also comparing logs between containerd-integration (and not). Containerd integration is quite noisy, but on the other hand is missing some logs that may be slightly more readable.
```suggestion
	logger := logrus.WithFields(logrus.Fields{
		"digest": img.Target().Digest,
		"remote":     ref.String(),
	})
	logger.Info("image pulled")
```

With containerd integration:

```
DEBU[2023-04-28T15:15:45.258436545Z] Calling GET /_ping
DEBU[2023-04-28T15:15:45.260657378Z] Calling GET /v1.30/info
DEBU[2023-04-28T15:15:45.282431253Z] Calling POST /v1.30/images/create?fromImage=busybox&tag=latest
DEBU[2023-04-28T15:15:45.335191503Z] resolving                                     host=registry-1.docker.io
DEBU[2023-04-28T15:15:45.335239628Z] do request                                    host=registry-1.docker.io request.header.accept="application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, */*" request.header.user-agent=containerd/1.6.20+unknown request.method=HEAD url="https://registry-1.docker.io/v2/library/busybox/manifests/latest"
DEBU[2023-04-28T15:15:45.731191336Z] fetch response received                       host=registry-1.docker.io response.header.content-length=158 response.header.content-type=application/json response.header.date="Fri, 28 Apr 2023 15:15:45 GMT" response.header.docker-distribution-api-version=registry/2.0 response.header.docker-ratelimit-source=213.127.30.9 response.header.strict-transport-security="max-age=31536000" response.header.www-authenticate="Bearer realm=\"https://auth.docker.io/token\",service=\"registry.docker.io\",scope=\"repository:library/busybox:pull\"" response.status="401 Unauthorized" url="https://registry-1.docker.io/v2/library/busybox/manifests/latest"
DEBU[2023-04-28T15:15:45.731504545Z] Unauthorized                                  header="Bearer realm=\"https://auth.docker.io/token\",service=\"registry.docker.io\",scope=\"repository:library/busybox:pull\"" host=registry-1.docker.io
WARN[2023-04-28T15:15:45.731624461Z] Host doesn't match                            cfgHost= host=registry-1.docker.io
DEBU[2023-04-28T15:15:45.731710545Z] do request                                    host=registry-1.docker.io request.header.accept="application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, */*" request.header.user-agent=containerd/1.6.20+unknown request.method=HEAD url="https://registry-1.docker.io/v2/library/busybox/manifests/latest"
DEBU[2023-04-28T15:15:46.312977920Z] fetch response received                       host=registry-1.docker.io response.header.content-length=2295 response.header.content-type=application/vnd.docker.distribution.manifest.list.v2+json response.header.date="Fri, 28 Apr 2023 15:15:46 GMT" response.header.docker-content-digest="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" response.header.docker-distribution-api-version=registry/2.0 response.header.docker-ratelimit-source=213.127.30.9 response.header.etag="\"sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16\"" response.header.ratelimit-limit="100;w=21600" response.header.ratelimit-remaining="95;w=21600" response.header.strict-transport-security="max-age=31536000" response.status="200 OK" url="https://registry-1.docker.io/v2/library/busybox/manifests/latest"
DEBU[2023-04-28T15:15:46.313148212Z] resolved                                      desc.digest="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" host=registry-1.docker.io
DEBU[2023-04-28T15:15:46.329550212Z] fetch                                         digest="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" mediatype=application/vnd.docker.distribution.manifest.list.v2+json size=2295
DEBU[2023-04-28T15:15:46.331094337Z] (*service).Write started                      expected="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" ref="index-sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" total=2295
DEBU[2023-04-28T15:15:46.340422712Z] do request                                    digest="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" mediatype=application/vnd.docker.distribution.manifest.list.v2+json request.header.accept="application/vnd.docker.distribution.manifest.list.v2+json, */*" request.header.user-agent=containerd/1.6.20+unknown request.method=GET size=2295 url="https://registry-1.docker.io/v2/library/busybox/manifests/sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16"
DEBU[2023-04-28T15:15:46.691260754Z] fetch response received                       digest="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" mediatype=application/vnd.docker.distribution.manifest.list.v2+json response.header.content-length=158 response.header.content-type=application/json response.header.date="Fri, 28 Apr 2023 15:15:46 GMT" response.header.docker-distribution-api-version=registry/2.0 response.header.docker-ratelimit-source=213.127.30.9 response.header.strict-transport-security="max-age=31536000" response.header.www-authenticate="Bearer realm=\"https://auth.docker.io/token\",service=\"registry.docker.io\",scope=\"repository:library/busybox:pull\"" response.status="401 Unauthorized" size=2295 url="https://registry-1.docker.io/v2/library/busybox/manifests/sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16"
DEBU[2023-04-28T15:15:46.691419879Z] Unauthorized                                  digest="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" header="Bearer realm=\"https://auth.docker.io/token\",service=\"registry.docker.io\",scope=\"repository:library/busybox:pull\"" mediatype=application/vnd.docker.distribution.manifest.list.v2+json size=2295
WARN[2023-04-28T15:15:46.691483629Z] Host doesn't match                            cfgHost= host=registry-1.docker.io
DEBU[2023-04-28T15:15:46.691845587Z] do request                                    digest="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" mediatype=application/vnd.docker.distribution.manifest.list.v2+json request.header.accept="application/vnd.docker.distribution.manifest.list.v2+json, */*" request.header.user-agent=containerd/1.6.20+unknown request.method=GET size=2295 url="https://registry-1.docker.io/v2/library/busybox/manifests/sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16"
DEBU[2023-04-28T15:15:47.219064421Z] fetch response received                       digest="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" mediatype=application/vnd.docker.distribution.manifest.list.v2+json response.header.content-length=2295 response.header.content-type=application/vnd.docker.distribution.manifest.list.v2+json response.header.date="Fri, 28 Apr 2023 15:15:47 GMT" response.header.docker-content-digest="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" response.header.docker-distribution-api-version=registry/2.0 response.header.docker-ratelimit-source=213.127.30.9 response.header.etag="\"sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16\"" response.header.ratelimit-limit="100;w=21600" response.header.ratelimit-remaining="95;w=21600" response.header.strict-transport-security="max-age=31536000" response.status="200 OK" size=2295 url="https://registry-1.docker.io/v2/library/busybox/manifests/sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16"
DEBU[2023-04-28T15:15:47.245709087Z] fetch                                         digest="sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d" mediatype=application/vnd.docker.distribution.manifest.v2+json size=528
DEBU[2023-04-28T15:15:47.246255129Z] (*service).Write started                      expected="sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d" ref="manifest-sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d" total=528
DEBU[2023-04-28T15:15:47.251461129Z] do request                                    digest="sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d" mediatype=application/vnd.docker.distribution.manifest.v2+json request.header.accept="application/vnd.docker.distribution.manifest.v2+json, */*" request.header.user-agent=containerd/1.6.20+unknown request.method=GET size=528 url="https://registry-1.docker.io/v2/library/busybox/manifests/sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d"
DEBU[2023-04-28T15:15:47.380419296Z] fetch response received                       digest="sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d" mediatype=application/vnd.docker.distribution.manifest.v2+json response.header.content-length=528 response.header.content-type=application/vnd.docker.distribution.manifest.v2+json response.header.date="Fri, 28 Apr 2023 15:15:47 GMT" response.header.docker-content-digest="sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d" response.header.docker-distribution-api-version=registry/2.0 response.header.docker-ratelimit-source=213.127.30.9 response.header.etag="\"sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d\"" response.header.ratelimit-limit="100;w=21600" response.header.ratelimit-remaining="94;w=21600" response.header.strict-transport-security="max-age=31536000" response.status="200 OK" size=528 url="https://registry-1.docker.io/v2/library/busybox/manifests/sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d"
DEBU[2023-04-28T15:15:47.396763879Z] fetch                                         digest="sha256:3fbaf71a998bae6e375be74b999bd418091bf6511e356a129fdc969c4a94a5bc" mediatype=application/vnd.docker.container.image.v1+json size=1472
DEBU[2023-04-28T15:15:47.397454254Z] (*service).Write started                      expected="sha256:3fbaf71a998bae6e375be74b999bd418091bf6511e356a129fdc969c4a94a5bc" ref="config-sha256:3fbaf71a998bae6e375be74b999bd418091bf6511e356a129fdc969c4a94a5bc" total=1472
DEBU[2023-04-28T15:15:47.404576546Z] do request                                    digest="sha256:3fbaf71a998bae6e375be74b999bd418091bf6511e356a129fdc969c4a94a5bc" mediatype=application/vnd.docker.container.image.v1+json request.header.accept="application/vnd.docker.container.image.v1+json, */*" request.header.user-agent=containerd/1.6.20+unknown request.method=GET size=1472 url="https://registry-1.docker.io/v2/library/busybox/blobs/sha256:3fbaf71a998bae6e375be74b999bd418091bf6511e356a129fdc969c4a94a5bc"
DEBU[2023-04-28T15:15:47.651694962Z] fetch response received                       digest="sha256:3fbaf71a998bae6e375be74b999bd418091bf6511e356a129fdc969c4a94a5bc" mediatype=application/vnd.docker.container.image.v1+json response.header.accept-ranges=bytes response.header.age=934529 response.header.cache-control="public, max-age=14400" response.header.cf-cache-status=HIT response.header.cf-ray=7bf0433f08750e4c-AMS response.header.connection=keep-alive response.header.content-length=1472 response.header.content-type=application/octet-stream response.header.date="Fri, 28 Apr 2023 15:15:47 GMT" response.header.etag="\"29e2e68046cc2035e201781b3952f168\"" response.header.expires="Fri, 28 Apr 2023 19:15:47 GMT" response.header.last-modified="Fri, 17 Mar 2023 01:47:43 GMT" response.header.server=cloudflare response.header.vary=Accept-Encoding response.header.x-amz-id-2="CLErUYhX6Ni8mn5cKP/KWpMvoSg3qEcrSqY/Rm5f/VO35Xoko4olvnqbJpSRdV0Xsh/rSt0Fepg=" response.header.x-amz-request-id=B9RE9BSFT53ZDQN9 response.header.x-amz-server-side-encryption=AES256 response.header.x-amz-version-id=ZGizPNRpICs7_reRloXVM5Vaw69BXB89 response.status="200 OK" size=1472 url="https://registry-1.docker.io/v2/library/busybox/blobs/sha256:3fbaf71a998bae6e375be74b999bd418091bf6511e356a129fdc969c4a94a5bc"
DEBU[2023-04-28T15:15:47.673126004Z] stat snapshot                                 key="sha256:416052d13ad7f11c2b56249c179249f1ce37b0e1caf453bb037d863fd2588072"
DEBU[2023-04-28T15:15:47.674731546Z] prepare snapshot                              key="extract-673752587-M6zw sha256:416052d13ad7f11c2b56249c179249f1ce37b0e1caf453bb037d863fd2588072" parent=
DEBU[2023-04-28T15:15:47.681191296Z] event published                               ns=moby topic=/snapshot/prepare type=containerd.events.SnapshotPrepare
DEBU[2023-04-28T15:15:47.682019837Z] fetch                                         digest="sha256:b50100f25006c29bd3a3dd4abacfeb7e9cb61c1a758d07c68fa699a2494fd2df" mediatype=application/vnd.docker.image.rootfs.diff.tar.gzip size=2001144
DEBU[2023-04-28T15:15:47.682411754Z] (*service).Write started                      expected="sha256:b50100f25006c29bd3a3dd4abacfeb7e9cb61c1a758d07c68fa699a2494fd2df" ref="layer-sha256:b50100f25006c29bd3a3dd4abacfeb7e9cb61c1a758d07c68fa699a2494fd2df" total=2001144
DEBU[2023-04-28T15:15:47.688579421Z] do request                                    digest="sha256:b50100f25006c29bd3a3dd4abacfeb7e9cb61c1a758d07c68fa699a2494fd2df" mediatype=application/vnd.docker.image.rootfs.diff.tar.gzip request.header.accept="application/vnd.docker.image.rootfs.diff.tar.gzip, */*" request.header.user-agent=containerd/1.6.20+unknown request.method=GET size=2001144 url="https://registry-1.docker.io/v2/library/busybox/blobs/sha256:b50100f25006c29bd3a3dd4abacfeb7e9cb61c1a758d07c68fa699a2494fd2df"
DEBU[2023-04-28T15:15:47.841918046Z] fetch response received                       digest="sha256:b50100f25006c29bd3a3dd4abacfeb7e9cb61c1a758d07c68fa699a2494fd2df" mediatype=application/vnd.docker.image.rootfs.diff.tar.gzip response.header.accept-ranges=bytes response.header.age=894058 response.header.cache-control="public, max-age=14400" response.header.cf-cache-status=HIT response.header.cf-ray=7bf043403a1b0e4c-AMS response.header.connection=keep-alive response.header.content-length=2001144 response.header.content-type=application/octet-stream response.header.date="Fri, 28 Apr 2023 15:15:47 GMT" response.header.etag="\"7bb83f84eceb4fd001604e93f8e46dbd\"" response.header.expires="Fri, 28 Apr 2023 19:15:47 GMT" response.header.last-modified="Fri, 17 Mar 2023 01:47:40 GMT" response.header.server=cloudflare response.header.vary=Accept-Encoding response.header.x-amz-id-2="T0bT4Z2SHpXKVjZQJxlTRy8SDwk7QvEj1smTdUxS+xXjIWy2vulTCfIKX+E3615HmvwHU+vemb4=" response.header.x-amz-request-id=C0C61AV6254RQ9SK response.header.x-amz-server-side-encryption=AES256 response.header.x-amz-version-id=uY5.qowBrH_UFvtPQEkOmfKvLE5kyCdT response.status="200 OK" size=2001144 url="https://registry-1.docker.io/v2/library/busybox/blobs/sha256:b50100f25006c29bd3a3dd4abacfeb7e9cb61c1a758d07c68fa699a2494fd2df"
DEBU[2023-04-28T15:15:47.952059921Z] using pigz for decompression
DEBU[2023-04-28T15:15:48.001937963Z] diff applied                                  d=50.860292ms digest="sha256:b50100f25006c29bd3a3dd4abacfeb7e9cb61c1a758d07c68fa699a2494fd2df" media=application/vnd.docker.image.rootfs.diff.tar.gzip size=2001144
DEBU[2023-04-28T15:15:48.002485421Z] commit snapshot                               key="extract-673752587-M6zw sha256:416052d13ad7f11c2b56249c179249f1ce37b0e1caf453bb037d863fd2588072" name="sha256:416052d13ad7f11c2b56249c179249f1ce37b0e1caf453bb037d863fd2588072"
DEBU[2023-04-28T15:15:48.006047879Z] event published                               ns=moby topic=/snapshot/commit type=containerd.events.SnapshotCommit
DEBU[2023-04-28T15:15:48.007349213Z] image unpacked                                chainID="sha256:416052d13ad7f11c2b56249c179249f1ce37b0e1caf453bb037d863fd2588072" config="sha256:3fbaf71a998bae6e375be74b999bd418091bf6511e356a129fdc969c4a94a5bc"
DEBU[2023-04-28T15:15:48.007682504Z] create image                                  name="docker.io/library/busybox:latest" target="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16"
DEBU[2023-04-28T15:15:48.008268421Z] event published                               ns=moby topic=/images/create type=containerd.services.images.v1.ImageCreate
INFO[2023-04-28T15:15:48.009013463Z] image pulled                                  imageID="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" tag="docker.io/library/busybox:latest"
DEBU[2023-04-28T15:15:48.023274004Z] garbage collected                             d="424.375µs"
```

Without containerd integration:

```
DEBU[2023-04-28T15:19:49.958819380Z] Calling GET /_ping
DEBU[2023-04-28T15:19:49.959660880Z] Calling GET /v1.30/info
DEBU[2023-04-28T15:19:49.974199005Z] Calling POST /v1.30/images/create?fromImage=busybox&tag=latest
DEBU[2023-04-28T15:19:50.027799838Z] Trying to pull busybox from https://registry-1.docker.io
DEBU[2023-04-28T15:19:51.246131047Z] (*service).Write started                      expected="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" ref="index-sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" total=2295
DEBU[2023-04-28T15:19:51.272461797Z] Pulling ref from V2 registry: busybox:latest
DEBU[2023-04-28T15:19:51.272648589Z] docker.io/library/busybox:latest resolved to a manifestList object with 10 entries; looking for a unknown match
DEBU[2023-04-28T15:19:51.272729131Z] found match for linux/arm64 with media type application/vnd.docker.distribution.manifest.v2+json, digest sha256:41acaa55f2b4f4a07973f400bbc2bc66bdc2cff9a8fb509eff8445ae5dd24f08
DEBU[2023-04-28T15:19:51.272754631Z] found match for linux/arm64 with media type application/vnd.docker.distribution.manifest.v2+json, digest sha256:4b6c3421712a1022fcd399294ec7b46d94c370e8f94afc73da3e22752fe3d23c
DEBU[2023-04-28T15:19:51.272796464Z] found match for linux/arm64 with media type application/vnd.docker.distribution.manifest.v2+json, digest sha256:ba3b2a4af4711892b4814123d47250b6283cba6e61ed9b3a8b73a3186e31c860
DEBU[2023-04-28T15:19:51.272803339Z] found match for linux/arm64 with media type application/vnd.docker.distribution.manifest.v2+json, digest sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d
DEBU[2023-04-28T15:19:51.273275797Z] (*service).Write started                      expected="sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d" ref="manifest-sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d" total=528
DEBU[2023-04-28T15:19:51.282183089Z] pulling blob "sha256:b50100f25006c29bd3a3dd4abacfeb7e9cb61c1a758d07c68fa699a2494fd2df"
DEBU[2023-04-28T15:19:51.868487714Z] Downloaded b50100f25006 to tempfile /var/lib/docker/tmp/GetImageBlob3557625968
DEBU[2023-04-28T15:19:51.869201964Z] Using /usr/bin/unpigz to decompress
DEBU[2023-04-28T15:19:51.880352589Z] Applying tar in /var/lib/docker/overlay2/a55472148a81b2fc43fbb4e9d710115e1d4ebc7d38a4a8b4838f9dc0c9f8972d/diff  storage-driver=overlay2
DEBU[2023-04-28T15:19:51.973500423Z] Applied tar sha256:416052d13ad7f11c2b56249c179249f1ce37b0e1caf453bb037d863fd2588072 to a55472148a81b2fc43fbb4e9d710115e1d4ebc7d38a4a8b4838f9dc0c9f8972d, size: 3726546
DEBU[2023-04-28T15:19:51.980793798Z] Adding content digest to lease                digest="sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16" lease="moby-image-sha256:3fbaf71a998bae6e375be74b999bd418091bf6511e356a129fdc969c4a94a5bc" remote="docker.io/library/busybox:latest"
DEBU[2023-04-28T15:19:51.981589798Z] Adding content digest to lease                digest="sha256:ba7000206594c2d72c3ab550453004c0dc50961157e5ebd2fb8ea1890099d02d" lease="moby-image-sha256:3fbaf71a998bae6e375be74b999bd418091bf6511e356a129fdc969c4a94a5bc" remote="docker.io/library/busybox:latest"
DEBU[2023-04-28T15:19:51.999020756Z] garbage collected                             d="473.125µs"
```