Image commit
Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
parent
0ac4ad0580
commit
bad33bbd02
2 changed files with 124 additions and 118 deletions
118
daemon/commit.go
118
daemon/commit.go
|
@ -1,9 +1,7 @@
|
|||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -12,10 +10,6 @@ import (
|
|||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/builder/dockerfile"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/layer"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -190,115 +184,3 @@ func (daemon *Daemon) CreateImageFromContainer(name string, c *backend.CreateIma
|
|||
containerActions.WithValues("commit").UpdateSince(start)
|
||||
return id.String(), nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) commitImage(c backend.CommitConfig) (image.ID, error) {
|
||||
layerStore, ok := daemon.layerStores[c.ContainerOS]
|
||||
if !ok {
|
||||
return "", system.ErrNotSupportedOperatingSystem
|
||||
}
|
||||
rwTar, err := exportContainerRw(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 = daemon.imageStore.Get(image.ID(c.ParentImageID))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
l, err := layerStore.Register(rwTar, parent.RootFS.ChainID())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer layer.ReleaseAndLog(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 := daemon.imageStore.Create(config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if c.ParentImageID != "" {
|
||||
if err := daemon.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, err error) {
|
||||
rwlayer, err := layerStore.GetRWLayer(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err != 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.
|
||||
_, err = rwlayer.Mount(mountLabel)
|
||||
if 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 (daemon *Daemon) CommitBuildStep(c backend.CommitConfig) (image.ID, error) {
|
||||
container, err := daemon.GetContainer(c.ContainerID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
c.ContainerMountLabel = container.MountLabel
|
||||
c.ContainerOS = container.OS
|
||||
c.ParentImageID = string(container.ImageID)
|
||||
return daemon.commitImage(c)
|
||||
}
|
||||
|
|
124
daemon/image_commit.go
Normal file
124
daemon/image_commit.go
Normal file
|
@ -0,0 +1,124 @@
|
|||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/layer"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) commitImage(c backend.CommitConfig) (image.ID, error) {
|
||||
layerStore, ok := daemon.layerStores[c.ContainerOS]
|
||||
if !ok {
|
||||
return "", system.ErrNotSupportedOperatingSystem
|
||||
}
|
||||
rwTar, err := exportContainerRw(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 = daemon.imageStore.Get(image.ID(c.ParentImageID))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
l, err := layerStore.Register(rwTar, parent.RootFS.ChainID())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer layer.ReleaseAndLog(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 := daemon.imageStore.Create(config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if c.ParentImageID != "" {
|
||||
if err := daemon.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, err error) {
|
||||
rwlayer, err := layerStore.GetRWLayer(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err != 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.
|
||||
_, err = rwlayer.Mount(mountLabel)
|
||||
if 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 (daemon *Daemon) CommitBuildStep(c backend.CommitConfig) (image.ID, error) {
|
||||
container, err := daemon.GetContainer(c.ContainerID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
c.ContainerMountLabel = container.MountLabel
|
||||
c.ContainerOS = container.OS
|
||||
c.ParentImageID = string(container.ImageID)
|
||||
return daemon.commitImage(c)
|
||||
}
|
Loading…
Add table
Reference in a new issue