Files
moby/daemon/images/image_commit.go
Sebastiaan van Stijn 7d4caf4ba8 daemon/images: remove // import comments
These comments were added to enforce using the correct import path for
our packages ("github.com/docker/docker", not "github.com/moby/moby").
However, when working in go module mode (not GOPATH / vendor), they have
no effect, so their impact is limited.

Remove these imports in preparation of migrating our code to become an
actual go module.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-05-30 15:59:12 +02:00

133 lines
3.4 KiB
Go

package images
import (
"context"
"encoding/json"
"io"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/ioutils"
"github.com/pkg/errors"
)
// CommitImage creates a new image from a commit config
func (i *ImageService) CommitImage(ctx context.Context, c backend.CommitConfig) (image.ID, error) {
if err := ctx.Err(); err != nil {
return "", err
}
rwTar, err := exportContainerRw(i.layerStore, c.ContainerID, c.ContainerMountLabel)
if err != nil {
return "", err
}
defer func() {
if rwTar != nil {
rwTar.Close()
}
}()
var parent *image.Image
if c.ParentImageID == "" {
parent = new(image.Image)
parent.RootFS = image.NewRootFS()
} else {
parent, err = i.imageStore.Get(image.ID(c.ParentImageID))
if err != nil {
return "", err
}
}
l, err := i.layerStore.Register(rwTar, parent.RootFS.ChainID())
if err != nil {
return "", err
}
defer layer.ReleaseAndLog(i.layerStore, l)
cc := image.ChildConfig{
ContainerID: c.ContainerID,
Author: c.Author,
Comment: c.Comment,
ContainerConfig: c.ContainerConfig,
Config: c.Config,
DiffID: l.DiffID(),
}
config, err := json.Marshal(image.NewChildImage(parent, cc, c.ContainerOS))
if err != nil {
return "", err
}
id, err := i.imageStore.Create(config)
if err != nil {
return "", err
}
i.LogImageEvent(ctx, id.String(), id.String(), events.ActionCreate)
if err := i.imageStore.SetBuiltLocally(id); err != nil {
return "", err
}
if c.ParentImageID != "" {
if err := i.imageStore.SetParent(id, image.ID(c.ParentImageID)); err != nil {
return "", err
}
}
return id, nil
}
func exportContainerRw(layerStore layer.Store, id, mountLabel string) (arch io.ReadCloser, retErr error) {
rwlayer, err := layerStore.GetRWLayer(id)
if err != nil {
return nil, err
}
defer func() {
if retErr != nil {
_, _ = layerStore.ReleaseRWLayer(rwlayer)
}
}()
// TODO: this mount call is not necessary as we assume that TarStream() should
// mount the layer if needed. But the Diff() function for windows requests that
// the layer should be mounted when calling it. So we reserve this mount call
// until windows driver can implement Diff() interface correctly.
if _, err := rwlayer.Mount(mountLabel); err != nil {
return nil, err
}
archive, err := rwlayer.TarStream()
if err != nil {
_ = rwlayer.Unmount()
return nil, err
}
return ioutils.NewReadCloserWrapper(archive, func() error {
_ = archive.Close()
err := rwlayer.Unmount()
_, _ = layerStore.ReleaseRWLayer(rwlayer)
return err
}), nil
}
// CommitBuildStep is used by the builder to create an image for each step in
// the build.
//
// This method is different from CreateImageFromContainer:
// - it doesn't attempt to validate container state
// - it doesn't send a commit action to metrics
// - it doesn't log a container commit event
//
// This is a temporary shim. Should be removed when builder stops using commit.
func (i *ImageService) CommitBuildStep(ctx context.Context, c backend.CommitConfig) (image.ID, error) {
ctr := i.containers.Get(c.ContainerID)
if ctr == nil {
// TODO: use typed error
return "", errors.Errorf("container not found: %s", c.ContainerID)
}
c.ContainerMountLabel = ctr.MountLabel
c.ContainerOS = ctr.ImagePlatform.OS
c.ParentImageID = string(ctr.ImageID)
return i.CommitImage(ctx, c)
}