c8d: Handle nil container.ImageManifest
Don't panic when processing containers created under fork containerd integration (this field was added in the upstream and didn't exist in fork). Co-authored-by: Djordje Lukic <djordje.lukic@docker.com> Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
parent
a343ed13e5
commit
9fe5ac6614
3 changed files with 52 additions and 9 deletions
|
@ -17,7 +17,12 @@ import (
|
|||
func (i *ImageService) Changes(ctx context.Context, container *container.Container) ([]archive.Change, error) {
|
||||
cs := i.client.ContentStore()
|
||||
|
||||
imageManifestBytes, err := content.ReadBlob(ctx, cs, *container.ImageManifest)
|
||||
imageManifest, err := getContainerImageManifest(container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
imageManifestBytes, err := content.ReadBlob(ctx, cs, imageManifest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -40,7 +40,12 @@ func (i *ImageService) CommitImage(ctx context.Context, cc backend.CommitConfig)
|
|||
container := i.containers.Get(cc.ContainerID)
|
||||
cs := i.client.ContentStore()
|
||||
|
||||
imageManifestBytes, err := content.ReadBlob(ctx, cs, *container.ImageManifest)
|
||||
imageManifest, err := getContainerImageManifest(container)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
imageManifestBytes, err := content.ReadBlob(ctx, cs, imageManifest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/containerd/containerd/plugin"
|
||||
"github.com/containerd/containerd/remotes/docker"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
imagetypes "github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/container"
|
||||
daemonevents "github.com/docker/docker/daemon/events"
|
||||
"github.com/docker/docker/daemon/images"
|
||||
|
@ -20,6 +21,7 @@ import (
|
|||
"github.com/opencontainers/image-spec/identity"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ImageService implements daemon.ImageService
|
||||
|
@ -154,9 +156,35 @@ func (i *ImageService) GetContainerLayerSize(ctx context.Context, containerID st
|
|||
if ctr == nil {
|
||||
return 0, 0, nil
|
||||
}
|
||||
|
||||
snapshotter := i.client.SnapshotService(ctr.Driver)
|
||||
|
||||
usage, err := snapshotter.Usage(ctx, containerID)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
imageManifest, err := getContainerImageManifest(ctr)
|
||||
if err != nil {
|
||||
// Best efforts attempt to pick an image.
|
||||
// We don't have platform information at this point, so we can only
|
||||
// assume that the platform matches host.
|
||||
// Otherwise this will give a wrong base image size (different
|
||||
// platform), but should be close enough.
|
||||
mfst, err := i.GetImageManifest(ctx, ctr.Config.Image, imagetypes.GetImageOpts{})
|
||||
if err != nil {
|
||||
// Log error, don't error out whole operation.
|
||||
logrus.WithFields(logrus.Fields{
|
||||
logrus.ErrorKey: err,
|
||||
"container": containerID,
|
||||
}).Warn("empty ImageManifest, can't calculate base image size")
|
||||
return usage.Size, 0, nil
|
||||
}
|
||||
imageManifest = *mfst
|
||||
}
|
||||
cs := i.client.ContentStore()
|
||||
|
||||
imageManifestBytes, err := content.ReadBlob(ctx, cs, *ctr.ImageManifest)
|
||||
imageManifestBytes, err := content.ReadBlob(ctx, cs, imageManifest)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
@ -175,12 +203,6 @@ func (i *ImageService) GetContainerLayerSize(ctx context.Context, containerID st
|
|||
return 0, 0, err
|
||||
}
|
||||
|
||||
snapshotter := i.client.SnapshotService(ctr.Driver)
|
||||
usage, err := snapshotter.Usage(ctx, containerID)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
sizeCache := make(map[digest.Digest]int64)
|
||||
snapshotSizeFn := func(d digest.Digest) (int64, error) {
|
||||
if s, ok := sizeCache[d]; ok {
|
||||
|
@ -203,3 +225,14 @@ func (i *ImageService) GetContainerLayerSize(ctx context.Context, containerID st
|
|||
// TODO(thaJeztah): include content-store size for the image (similar to "GET /images/json")
|
||||
return usage.Size, usage.Size + snapShotSize, nil
|
||||
}
|
||||
|
||||
// getContainerImageManifest safely dereferences ImageManifest.
|
||||
// ImageManifest can be nil for containers created with Docker Desktop with old
|
||||
// containerd image store integration enabled which didn't set this field.
|
||||
func getContainerImageManifest(ctr *container.Container) (ocispec.Descriptor, error) {
|
||||
if ctr.ImageManifest == nil {
|
||||
return ocispec.Descriptor{}, errdefs.InvalidParameter(errors.New("container is missing ImageManifest (probably created on old version), please recreate it"))
|
||||
}
|
||||
|
||||
return *ctr.ImageManifest, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue