mirror of
https://github.com/moby/moby.git
synced 2026-07-26 03:07:42 +00:00
The container rw layer may already be mounted, so it's not safe to use it in another overlay mount. Use the ref counted mounter (which will reuse the existing mount if it exists) to avoid that. Also, mount the parent mounts (layers of the base image) in a read-only mode. Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
70 lines
1.8 KiB
Go
70 lines
1.8 KiB
Go
package containerd
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"github.com/containerd/containerd/content"
|
|
"github.com/containerd/containerd/log"
|
|
"github.com/containerd/containerd/mount"
|
|
"github.com/docker/docker/container"
|
|
"github.com/docker/docker/pkg/archive"
|
|
"github.com/google/uuid"
|
|
"github.com/opencontainers/image-spec/identity"
|
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
)
|
|
|
|
func (i *ImageService) Changes(ctx context.Context, container *container.Container) ([]archive.Change, error) {
|
|
cs := i.client.ContentStore()
|
|
|
|
imageManifest, err := getContainerImageManifest(container)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
imageManifestBytes, err := content.ReadBlob(ctx, cs, imageManifest)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var manifest ocispec.Manifest
|
|
if err := json.Unmarshal(imageManifestBytes, &manifest); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
imageConfigBytes, err := content.ReadBlob(ctx, cs, manifest.Config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var image ocispec.Image
|
|
if err := json.Unmarshal(imageConfigBytes, &image); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rnd, err := uuid.NewRandom()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
snapshotter := i.client.SnapshotService(container.Driver)
|
|
|
|
diffIDs := image.RootFS.DiffIDs
|
|
parent, err := snapshotter.View(ctx, rnd.String(), identity.ChainID(diffIDs).String())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func() {
|
|
if err := snapshotter.Remove(ctx, rnd.String()); err != nil {
|
|
log.G(ctx).WithError(err).WithField("key", rnd.String()).Warn("remove temporary snapshot")
|
|
}
|
|
}()
|
|
|
|
var changes []archive.Change
|
|
err = i.PerformWithBaseFS(ctx, container, func(containerRootfs string) error {
|
|
return mount.WithReadonlyTempMount(ctx, parent, func(parentRootfs string) error {
|
|
changes, err = archive.ChangesDirs(containerRootfs, parentRootfs)
|
|
return err
|
|
})
|
|
})
|
|
return changes, err
|
|
}
|