daemon/c8d: Implement image history
**- What I did**

Implemented `docker image history`.

Note there is some duplication of code with the usual resolveDescriptor -> images.Config -> content.ReadBlob, I think we can refactor at a later time.

I'm unsure how `Tags` work, there is a difference between an image history when it's built by the classic builder or buildkit:

Currently, with this Dockerfile:
```dockerfile
FROM alpine

CMD ["echo", "hello"]
```

If we build it with the classic builder (``) we get this history:

```json
[
  {
    "Comment": "",
    "Created": 1673531696,
    "CreatedBy": "/bin/sh -c #(nop)  CMD [\"echo\" \"hello\"]",
    "Id": "sha256:42f9b7e41f28aa91037a8c8355de66d650c6fd192426e7d30c33591a5e72e6ea",
    "Size": 0,
    "Tags": [
      "henelo:latest"
    ]
  },
  {
    "Comment": "",
    "Created": 1673283889,
    "CreatedBy": "/bin/sh -c #(nop)  CMD [\"/bin/sh\"]",
    "Id": "sha256:04eeaa5f8c35b8206a15c12425498c37ecd2181e0ef202bea24a2382e4dd240f",
    "Size": 0,
    "Tags": [
      "alpine:latest"
    ]
  },
  {
    "Comment": "",
    "Created": 1673283888,
    "CreatedBy": "/bin/sh -c #(nop) ADD file:3080f19f39259a4b77cc53975de0184c78d4335ceb9ffb77a2838d0539ad6f85 in / ",
    "Id": "<missing>",
    "Size": 7458929,
    "Tags": null
  }
]
```

But if we build it with buidkit we get this:

```json
[
  {
    "Comment": "buildkit.dockerfile.v0",
    "Created": 1673283889,
    "CreatedBy": "CMD [\"echo\" \"hello\"]",
    "Id": "sha256:6f6cafc4e6423f0997d34c88b4e018028c5225c6ccb67f55c2f0efd5f8a808aa",
    "Size": 0,
    "Tags": [
      "henelo:latest"
    ]
  },
  {
    "Comment": "",
    "Created": 1673283889,
    "CreatedBy": "/bin/sh -c #(nop)  CMD [\"/bin/sh\"]",
    "Id": "<missing>",
    "Size": 0,
    "Tags": null
  },
  {
    "Comment": "",
    "Created": 1673283888,
    "CreatedBy": "/bin/sh -c #(nop) ADD file:3080f19f39259a4b77cc53975de0184c78d4335ceb9ffb77a2838d0539ad6f85 in / ",
    "Id": "<missing>",
    "Size": 7458929,
    "Tags": null
  }
]
```

Note how the image that's built with buildkit looses the `alpine:latest` tags in the second history item.

Also, the only way to see these `Tags` is to call the API directly, `docker image history <name> --format '{{ json . }}'` doesn't even show the `Tags` property.

~~Another difference with the exising history API is that the `Tags` will not be `null` since the docs say that `Tags` is required.~~

Upstreams:
* https://github.com/rumpl/moby/pull/69

**- How I did it**

By looping over the `History` of the image.

**- How to verify it**

Pull or build an image and then call `docker image history`.

**- Description for the changelog**

**- A picture of a cute animal (not mandatory but encouraged)**
<img width="750" alt="Screenshot 2023-01-12 at 14 40 37" src="https://user-images.githubusercontent.com/99933/212081796-e8a5908a-02ee-4f19-a7c8-d9396648a689.png">

daemon/containerd/image_history.go
package containerd

import (
	"context"
	"errors"

	imagetype "github.com/docker/docker/api/types/image"
	"github.com/docker/docker/errdefs"
)

// ImageHistory returns a slice of ImageHistory structures for the specified
// image name by walking the image lineage.
func (i *ImageService) ImageHistory(ctx context.Context, name string) ([]*imagetype.HistoryResponseItem, error) {
	return nil, errdefs.NotImplemented(errors.New("not implemented"))
}

package containerd

import (
	"context"
	"encoding/json"

	"github.com/containerd/containerd/content"
	containerdimages "github.com/containerd/containerd/images"
	cplatforms "github.com/containerd/containerd/platforms"
	"github.com/docker/distribution/reference"
	imagetype "github.com/docker/docker/api/types/image"
	"github.com/docker/docker/pkg/platforms"
	"github.com/opencontainers/image-spec/identity"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
)

// ImageHistory returns a slice of HistoryResponseItem structures for the
// specified image name by walking the image lineage.
func (i *ImageService) ImageHistory(ctx context.Context, name string) ([]*imagetype.HistoryResponseItem, error) {
	desc, err := i.resolveDescriptor(ctx, name)
	if err != nil {
		return nil, err
	}

	cs := i.client.ContentStore()
	// TODO: pass the platform from the cli
	conf, err := containerdimages.Config(ctx, cs, desc, platforms.AllPlatformsWithPreference(cplatforms.Default()))
	if err != nil {
		return nil, err
	}

	diffIDs, err := containerdimages.RootFS(ctx, cs, conf)
	if err != nil {
		return nil, err
	}

	blob, err := content.ReadBlob(ctx, cs, conf)
	if err != nil {
		return nil, err
	}

	var image ocispec.Image
	if err := json.Unmarshal(blob, &image); err != nil {
		return nil, err
	}

	var (
		history []*imagetype.HistoryResponseItem
		sizes   []int64
	)
	s := i.client.SnapshotService(i.snapshotter)

	for i := range diffIDs {
		chainID := identity.ChainID(diffIDs[0 : i+1]).String()

		use, err := s.Usage(ctx, chainID)
		if err != nil {
			return nil, err
		}

		sizes = append(sizes, use.Size)
	}

	for _, h := range image.History {
		size := int64(0)
		if !h.EmptyLayer {
			if len(sizes) == 0 {
				return nil, errors.New("unable to find the size of the layer")
			}
			size = sizes[0]
			sizes = sizes[1:]
		}

		history = append([]*imagetype.HistoryResponseItem{{
			ID:        "<missing>",
			Comment:   h.Comment,
			CreatedBy: h.CreatedBy,
			Created:   h.Created.Unix(),
			Size:      size,
			Tags:      nil,
		}}, history...)
	}

	if len(history) != 0 {
		history[0].ID = desc.Digest.String()

		tagged, err := i.client.ImageService().List(ctx, "target.digest=="+desc.Digest.String())
		if err != nil {
			return nil, err
		}

		tags := make([]string, len(tagged))
		for i, t := range tagged {
			name, err := reference.ParseNamed(t.Name)
			if err != nil {
				return nil, err
			}
			tags[i] = reference.FamiliarString(name)
		}
		history[0].Tags = tags
	}

	return history, nil
}

The `id` it's taking here is first the id of the image, but then it the id of the parent (https://github.com/moby/moby/blob/65c371ed6e48d0014a4826a6933f9231f688327a/daemon/images/image_history.go#L69) we don't have this relation in containerd unfortunately, or at least I didn't find any way to do it. 

That parent relation doesn't exist if you build the image with buildkit (see the PR description).

We could followup when we have the classic builder working?