c8d: add support for docker diff

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
This commit is contained in:
Laura Brehm 2023-03-23 11:32:59 +00:00
parent e85c69e1b7
commit 4c459ddabd
No known key found for this signature in database
GPG key ID: 526E3FC49260D47A
6 changed files with 96 additions and 13 deletions

View file

@ -48,7 +48,7 @@ type stateBackend interface {
// monitorBackend includes functions to implement to provide containers monitoring functionality.
type monitorBackend interface {
ContainerChanges(name string) ([]archive.Change, error)
ContainerChanges(ctx context.Context, name string) ([]archive.Change, error)
ContainerInspect(ctx context.Context, name string, size bool, version string) (interface{}, error)
ContainerLogs(ctx context.Context, name string, config *types.ContainerLogsOptions) (msgs <-chan *backend.LogMessage, tty bool, err error)
ContainerStats(ctx context.Context, name string, config *backend.ContainerStatsConfig) error

View file

@ -401,7 +401,7 @@ func (s *containerRouter) postContainersWait(ctx context.Context, w http.Respons
}
func (s *containerRouter) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
changes, err := s.backend.ContainerChanges(vars["name"])
changes, err := s.backend.ContainerChanges(ctx, vars["name"])
if err != nil {
return err
}

View file

@ -1,16 +1,17 @@
package daemon // import "github.com/docker/docker/daemon"
import (
"context"
"errors"
"time"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/archive"
)
// ContainerChanges returns a list of container fs changes
func (daemon *Daemon) ContainerChanges(name string) ([]archive.Change, error) {
func (daemon *Daemon) ContainerChanges(ctx context.Context, name string) ([]archive.Change, error) {
start := time.Now()
container, err := daemon.GetContainer(name)
if err != nil {
return nil, err
@ -20,15 +21,7 @@ func (daemon *Daemon) ContainerChanges(name string) ([]archive.Change, error) {
return nil, errors.New("Windows does not support diff of a running container")
}
if daemon.UsesSnapshotter() {
return nil, errdefs.NotImplemented(errors.New("not implemented"))
}
container.Lock()
defer container.Unlock()
if container.RWLayer == nil {
return nil, errors.New("RWLayer of container " + name + " is unexpectedly nil")
}
c, err := container.RWLayer.Changes()
c, err := daemon.imageService.Changes(ctx, container)
if err != nil {
return nil, err
}

View file

@ -0,0 +1,69 @@
package containerd
import (
"context"
"encoding/json"
"github.com/containerd/containerd/content"
"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"
"github.com/sirupsen/logrus"
)
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)
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(i.snapshotter)
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 {
logrus.WithError(err).WithField("key", rnd.String()).Warn("remove temporary snapshot")
}
}()
mounts, err := snapshotter.Mounts(ctx, container.ID)
if err != nil {
return nil, err
}
var changes []archive.Change
err = mount.WithReadonlyTempMount(ctx, mounts, func(fs string) error {
return mount.WithTempMount(ctx, parent, func(root string) error {
changes, err = archive.ChangesDirs(fs, root)
return err
})
})
return changes, err
}

View file

@ -16,6 +16,7 @@ import (
"github.com/docker/docker/daemon/images"
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/archive"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
@ -60,6 +61,7 @@ type ImageService interface {
GetContainerLayerSize(ctx context.Context, containerID string) (int64, int64, error)
Mount(ctx context.Context, container *container.Container) error
Unmount(ctx context.Context, container *container.Container) error
Changes(ctx context.Context, container *container.Container) ([]archive.Change, error)
// Windows specific

View file

@ -0,0 +1,19 @@
package images
import (
"context"
"errors"
"github.com/docker/docker/container"
"github.com/docker/docker/pkg/archive"
)
func (i *ImageService) Changes(ctx context.Context, container *container.Container) ([]archive.Change, error) {
container.Lock()
defer container.Unlock()
if container.RWLayer == nil {
return nil, errors.New("RWLayer of container " + container.Name + " is unexpectedly nil")
}
return container.RWLayer.Changes()
}