Decouple daemon and container to mount and unmount filesystems.

Side effects:
- Decouple daemon and container to start containers.
- Decouple daemon and container to copy files.

Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
David Calavera 2015-11-02 20:06:09 -05:00
parent 1c94f5f53a
commit 3a49765046
17 changed files with 188 additions and 176 deletions

View File

@ -130,6 +130,12 @@ type Docker interface {
Release(sessionID string, activeImages []string) Release(sessionID string, activeImages []string)
// Kill stops the container execution abruptly. // Kill stops the container execution abruptly.
Kill(c *daemon.Container) error Kill(c *daemon.Container) error
// Mount mounts the root filesystem for the container.
Mount(c *daemon.Container) error
// Unmount unmounts the root filesystem for the container.
Unmount(c *daemon.Container) error
// Start starts a new container
Start(c *daemon.Container) error
} }
// ImageCache abstracts an image cache store. // ImageCache abstracts an image cache store.

View File

@ -399,8 +399,8 @@ func run(b *Builder, args []string, attributes map[string]bool, original string)
// Ensure that we keep the container mounted until the commit // Ensure that we keep the container mounted until the commit
// to avoid unmounting and then mounting directly again // to avoid unmounting and then mounting directly again
c.Mount() b.docker.Mount(c)
defer c.Unmount() defer b.docker.Unmount(c)
err = b.run(c) err = b.run(c)
if err != nil { if err != nil {

View File

@ -67,10 +67,10 @@ func (b *Builder) commit(id string, autoCmd *stringutils.StrSlice, comment strin
} }
id = container.ID id = container.ID
if err := container.Mount(); err != nil { if err := b.docker.Mount(container); err != nil {
return err return err
} }
defer container.Unmount() defer b.docker.Unmount(container)
} }
container, err := b.docker.Container(id) container, err := b.docker.Container(id)
@ -201,7 +201,7 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD
if err != nil { if err != nil {
return err return err
} }
defer container.Unmount() defer b.docker.Unmount(container)
b.tmpContainers[container.ID] = struct{}{} b.tmpContainers[container.ID] = struct{}{}
comment := fmt.Sprintf("%s %s in %s", cmdName, origPaths, dest) comment := fmt.Sprintf("%s %s in %s", cmdName, origPaths, dest)
@ -524,7 +524,7 @@ func (b *Builder) create() (*daemon.Container, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer c.Unmount() defer b.docker.Unmount(c)
for _, warning := range warnings { for _, warning := range warnings {
fmt.Fprintf(b.Stdout, " ---> [Warning] %s\n", warning) fmt.Fprintf(b.Stdout, " ---> [Warning] %s\n", warning)
} }
@ -549,7 +549,7 @@ func (b *Builder) run(c *daemon.Container) error {
} }
//start the container //start the container
if err := c.Start(); err != nil { if err := b.docker.Start(c); err != nil {
return err return err
} }

View File

@ -30,7 +30,7 @@ func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, err
res = res[1:] res = res[1:]
} }
return container.copy(res) return daemon.containerCopy(container, res)
} }
// ContainerStatPath stats the filesystem resource at the specified path in the // ContainerStatPath stats the filesystem resource at the specified path in the
@ -41,7 +41,7 @@ func (daemon *Daemon) ContainerStatPath(name string, path string) (stat *types.C
return nil, err return nil, err
} }
return container.StatPath(path) return daemon.containerStatPath(container, path)
} }
// ContainerArchivePath creates an archive of the filesystem resource at the // ContainerArchivePath creates an archive of the filesystem resource at the
@ -53,7 +53,7 @@ func (daemon *Daemon) ContainerArchivePath(name string, path string) (content io
return nil, nil, err return nil, nil, err
} }
return container.ArchivePath(path) return daemon.containerArchivePath(container, path)
} }
// ContainerExtractToDir extracts the given archive to the specified location // ContainerExtractToDir extracts the given archive to the specified location
@ -68,7 +68,7 @@ func (daemon *Daemon) ContainerExtractToDir(name, path string, noOverwriteDirNon
return err return err
} }
return container.ExtractToDir(path, noOverwriteDirNonDir, content) return daemon.containerExtractToDir(container, path, noOverwriteDirNonDir, content)
} }
// resolvePath resolves the given path in the container to a resource on the // resolvePath resolves the given path in the container to a resource on the
@ -131,16 +131,16 @@ func (container *Container) statPath(resolvedPath, absPath string) (stat *types.
}, nil }, nil
} }
// StatPath stats the filesystem resource at the specified path in this // containerStatPath stats the filesystem resource at the specified path in this
// container. Returns stat info about the resource. // container. Returns stat info about the resource.
func (container *Container) StatPath(path string) (stat *types.ContainerPathStat, err error) { func (daemon *Daemon) containerStatPath(container *Container, path string) (stat *types.ContainerPathStat, err error) {
container.Lock() container.Lock()
defer container.Unlock() defer container.Unlock()
if err = container.Mount(); err != nil { if err = daemon.Mount(container); err != nil {
return nil, err return nil, err
} }
defer container.Unmount() defer daemon.Unmount(container)
err = container.mountVolumes() err = container.mountVolumes()
defer container.unmountVolumes(true) defer container.unmountVolumes(true)
@ -156,10 +156,10 @@ func (container *Container) StatPath(path string) (stat *types.ContainerPathStat
return container.statPath(resolvedPath, absPath) return container.statPath(resolvedPath, absPath)
} }
// ArchivePath creates an archive of the filesystem resource at the specified // containerArchivePath creates an archive of the filesystem resource at the specified
// path in this container. Returns a tar archive of the resource and stat info // path in this container. Returns a tar archive of the resource and stat info
// about the resource. // about the resource.
func (container *Container) ArchivePath(path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error) { func (daemon *Daemon) containerArchivePath(container *Container, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error) {
container.Lock() container.Lock()
defer func() { defer func() {
@ -171,7 +171,7 @@ func (container *Container) ArchivePath(path string) (content io.ReadCloser, sta
} }
}() }()
if err = container.Mount(); err != nil { if err = daemon.Mount(container); err != nil {
return nil, nil, err return nil, nil, err
} }
@ -180,7 +180,7 @@ func (container *Container) ArchivePath(path string) (content io.ReadCloser, sta
// unmount any volumes // unmount any volumes
container.unmountVolumes(true) container.unmountVolumes(true)
// unmount the container's rootfs // unmount the container's rootfs
container.Unmount() daemon.Unmount(container)
} }
}() }()
@ -214,7 +214,7 @@ func (container *Container) ArchivePath(path string) (content io.ReadCloser, sta
content = ioutils.NewReadCloserWrapper(data, func() error { content = ioutils.NewReadCloserWrapper(data, func() error {
err := data.Close() err := data.Close()
container.unmountVolumes(true) container.unmountVolumes(true)
container.Unmount() daemon.Unmount(container)
container.Unlock() container.Unlock()
return err return err
}) })
@ -224,20 +224,20 @@ func (container *Container) ArchivePath(path string) (content io.ReadCloser, sta
return content, stat, nil return content, stat, nil
} }
// ExtractToDir extracts the given tar archive to the specified location in the // containerExtractToDir extracts the given tar archive to the specified location in the
// filesystem of this container. The given path must be of a directory in the // filesystem of this container. The given path must be of a directory in the
// container. If it is not, the error will be ErrExtractPointNotDirectory. If // container. If it is not, the error will be ErrExtractPointNotDirectory. If
// noOverwriteDirNonDir is true then it will be an error if unpacking the // noOverwriteDirNonDir is true then it will be an error if unpacking the
// given content would cause an existing directory to be replaced with a non- // given content would cause an existing directory to be replaced with a non-
// directory and vice versa. // directory and vice versa.
func (container *Container) ExtractToDir(path string, noOverwriteDirNonDir bool, content io.Reader) (err error) { func (daemon *Daemon) containerExtractToDir(container *Container, path string, noOverwriteDirNonDir bool, content io.Reader) (err error) {
container.Lock() container.Lock()
defer container.Unlock() defer container.Unlock()
if err = container.Mount(); err != nil { if err = daemon.Mount(container); err != nil {
return err return err
} }
defer container.Unmount() defer daemon.Unmount(container)
err = container.mountVolumes() err = container.mountVolumes()
defer container.unmountVolumes(true) defer container.unmountVolumes(true)

View File

@ -225,76 +225,6 @@ func (container *Container) getRootResourcePath(path string) (string, error) {
return symlink.FollowSymlinkInScope(filepath.Join(container.root, cleanPath), container.root) return symlink.FollowSymlinkInScope(filepath.Join(container.root, cleanPath), container.root)
} }
// Start prepares the container to run by setting up everything the
// container needs, such as storage and networking, as well as links
// between containers. The container is left waiting for a signal to
// begin running.
func (container *Container) Start() (err error) {
container.Lock()
defer container.Unlock()
if container.Running {
return nil
}
if container.removalInProgress || container.Dead {
return derr.ErrorCodeContainerBeingRemoved
}
// if we encounter an error during start we need to ensure that any other
// setup has been cleaned up properly
defer func() {
if err != nil {
container.setError(err)
// if no one else has set it, make sure we don't leave it at zero
if container.ExitCode == 0 {
container.ExitCode = 128
}
container.toDisk()
container.cleanup()
container.logEvent("die")
}
}()
if err := container.conditionalMountOnStart(); err != nil {
return err
}
// Make sure NetworkMode has an acceptable value. We do this to ensure
// backwards API compatibility.
container.hostConfig = runconfig.SetDefaultNetModeIfBlank(container.hostConfig)
if err := container.initializeNetworking(); err != nil {
return err
}
linkedEnv, err := container.setupLinkedContainers()
if err != nil {
return err
}
if err := container.setupWorkingDirectory(); err != nil {
return err
}
env := container.createDaemonEnvironment(linkedEnv)
if err := populateCommand(container, env); err != nil {
return err
}
if !container.hostConfig.IpcMode.IsContainer() && !container.hostConfig.IpcMode.IsHost() {
if err := container.setupIpcDirs(); err != nil {
return err
}
}
mounts, err := container.setupMounts()
if err != nil {
return err
}
mounts = append(mounts, container.ipcMounts()...)
container.command.Mounts = mounts
return container.waitForStart()
}
// streamConfig.StdinPipe returns a WriteCloser which can be used to feed data // streamConfig.StdinPipe returns a WriteCloser which can be used to feed data
// to the standard input of the container's active process. // to the standard input of the container's active process.
// Container.StdoutPipe and Container.StderrPipe each return a ReadCloser // Container.StdoutPipe and Container.StderrPipe each return a ReadCloser
@ -326,7 +256,7 @@ func (container *Container) cleanup() {
container.unmountIpcMounts(detachMounted) container.unmountIpcMounts(detachMounted)
container.conditionalUnmountOnCleanup() container.daemon.conditionalUnmountOnCleanup(container)
for _, eConfig := range container.execCommands.s { for _, eConfig := range container.execCommands.s {
container.daemon.unregisterExecCommand(eConfig) container.daemon.unregisterExecCommand(eConfig)
@ -356,11 +286,6 @@ func (container *Container) Resize(h, w int) error {
return nil return nil
} }
// Mount sets container.basefs
func (container *Container) Mount() error {
return container.daemon.Mount(container)
}
func (container *Container) changes() ([]archive.Change, error) { func (container *Container) changes() ([]archive.Change, error) {
container.Lock() container.Lock()
defer container.Unlock() defer container.Unlock()
@ -374,12 +299,6 @@ func (container *Container) getImage() (*image.Image, error) {
return container.daemon.graph.Get(container.ImageID) return container.daemon.graph.Get(container.ImageID)
} }
// Unmount asks the daemon to release the layered filesystems that are
// mounted by the container.
func (container *Container) Unmount() error {
return container.daemon.unmount(container)
}
func (container *Container) hostConfigPath() (string, error) { func (container *Container) hostConfigPath() (string, error) {
return container.getRootResourcePath("hostconfig.json") return container.getRootResourcePath("hostconfig.json")
} }
@ -401,7 +320,7 @@ func validateID(id string) error {
return nil return nil
} }
func (container *Container) copy(resource string) (rc io.ReadCloser, err error) { func (daemon *Daemon) containerCopy(container *Container, resource string) (rc io.ReadCloser, err error) {
container.Lock() container.Lock()
defer func() { defer func() {
@ -413,7 +332,7 @@ func (container *Container) copy(resource string) (rc io.ReadCloser, err error)
} }
}() }()
if err := container.Mount(); err != nil { if err := daemon.Mount(container); err != nil {
return nil, err return nil, err
} }
@ -422,7 +341,7 @@ func (container *Container) copy(resource string) (rc io.ReadCloser, err error)
// unmount any volumes // unmount any volumes
container.unmountVolumes(true) container.unmountVolumes(true)
// unmount the container's rootfs // unmount the container's rootfs
container.Unmount() daemon.Unmount(container)
} }
}() }()
@ -458,11 +377,11 @@ func (container *Container) copy(resource string) (rc io.ReadCloser, err error)
reader := ioutils.NewReadCloserWrapper(archive, func() error { reader := ioutils.NewReadCloserWrapper(archive, func() error {
err := archive.Close() err := archive.Close()
container.unmountVolumes(true) container.unmountVolumes(true)
container.Unmount() daemon.Unmount(container)
container.Unlock() container.Unlock()
return err return err
}) })
container.logEvent("copy") daemon.logContainerEvent(container, "copy")
return reader, nil return reader, nil
} }

View File

@ -379,24 +379,23 @@ func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Devi
return append(devs, userDevices...) return append(devs, userDevices...)
} }
// GetSize returns the real size & virtual size of the container. // getSize returns the real size & virtual size of the container.
func (container *Container) getSize() (int64, int64) { func (daemon *Daemon) getSize(container *Container) (int64, int64) {
var ( var (
sizeRw, sizeRootfs int64 sizeRw, sizeRootfs int64
err error err error
driver = container.daemon.driver
) )
if err := container.Mount(); err != nil { if err := daemon.Mount(container); err != nil {
logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err) logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err)
return sizeRw, sizeRootfs return sizeRw, sizeRootfs
} }
defer container.Unmount() defer daemon.Unmount(container)
initID := fmt.Sprintf("%s-init", container.ID) initID := fmt.Sprintf("%s-init", container.ID)
sizeRw, err = driver.DiffSize(container.ID, initID) sizeRw, err = daemon.driver.DiffSize(container.ID, initID)
if err != nil { if err != nil {
logrus.Errorf("Driver %s couldn't return diff size of container %s: %s", driver, container.ID, err) logrus.Errorf("Driver %s couldn't return diff size of container %s: %s", daemon.driver, container.ID, err)
// FIXME: GetSize should return an error. Not changing it now in case // FIXME: GetSize should return an error. Not changing it now in case
// there is a side-effect. // there is a side-effect.
sizeRw = -1 sizeRw = -1
@ -1444,20 +1443,3 @@ func (container *Container) ipcMounts() []execdriver.Mount {
func detachMounted(path string) error { func detachMounted(path string) error {
return syscall.Unmount(path, syscall.MNT_DETACH) return syscall.Unmount(path, syscall.MNT_DETACH)
} }
// conditionalMountOnStart is a platform specific helper function during the
// container start to call mount.
func (container *Container) conditionalMountOnStart() error {
if err := container.Mount(); err != nil {
return err
}
return nil
}
// conditionalUnmountOnCleanup is a platform specific helper function called
// during the cleanup of a container to unmount.
func (container *Container) conditionalUnmountOnCleanup() {
if err := container.Unmount(); err != nil {
logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err)
}
}

View File

@ -5,7 +5,6 @@ package daemon
import ( import (
"strings" "strings"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/daemon/execdriver"
derr "github.com/docker/docker/errors" derr "github.com/docker/docker/errors"
"github.com/docker/docker/volume" "github.com/docker/docker/volume"
@ -143,8 +142,8 @@ func populateCommand(c *Container, env []string) error {
return nil return nil
} }
// GetSize returns real size & virtual size // getSize returns real size & virtual size
func (container *Container) getSize() (int64, int64) { func (daemon *Daemon) getSize(container *Container) (int64, int64) {
// TODO Windows // TODO Windows
return 0, 0 return 0, 0
} }
@ -191,26 +190,3 @@ func (container *Container) ipcMounts() []execdriver.Mount {
func getDefaultRouteMtu() (int, error) { func getDefaultRouteMtu() (int, error) {
return -1, errSystemNotSupported return -1, errSystemNotSupported
} }
// conditionalMountOnStart is a platform specific helper function during the
// container start to call mount.
func (container *Container) conditionalMountOnStart() error {
// We do not mount if a Hyper-V container
if !container.hostConfig.Isolation.IsHyperV() {
if err := container.Mount(); err != nil {
return err
}
}
return nil
}
// conditionalUnmountOnCleanup is a platform specific helper function called
// during the cleanup of a container to unmount.
func (container *Container) conditionalUnmountOnCleanup() {
// We do not unmount if a Hyper-V container
if !container.hostConfig.Isolation.IsHyperV() {
if err := container.Unmount(); err != nil {
logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err)
}
}
}

View File

@ -114,10 +114,10 @@ func (daemon *Daemon) create(params *ContainerCreateConfig) (retC *Container, re
} }
} }
}() }()
if err := container.Mount(); err != nil { if err := daemon.Mount(container); err != nil {
return nil, err return nil, err
} }
defer container.Unmount() defer daemon.Unmount(container)
if err := createContainerPlatformSpecificSettings(container, params.Config, params.HostConfig, img); err != nil { if err := createContainerPlatformSpecificSettings(container, params.Config, params.HostConfig, img); err != nil {
return nil, err return nil, err
@ -127,7 +127,7 @@ func (daemon *Daemon) create(params *ContainerCreateConfig) (retC *Container, re
logrus.Errorf("Error saving new container to disk: %v", err) logrus.Errorf("Error saving new container to disk: %v", err)
return nil, err return nil, err
} }
container.logEvent("create") daemon.logContainerEvent(container, "create")
return container, nil return container, nil
} }

View File

@ -234,7 +234,7 @@ func (daemon *Daemon) Register(container *Container) error {
container.unmountIpcMounts(mount.Unmount) container.unmountIpcMounts(mount.Unmount)
if err := container.Unmount(); err != nil { if err := daemon.Unmount(container); err != nil {
logrus.Debugf("unmount error %s", err) logrus.Debugf("unmount error %s", err)
} }
if err := container.toDiskLocking(); err != nil { if err := container.toDiskLocking(); err != nil {
@ -349,7 +349,7 @@ func (daemon *Daemon) restore() error {
if daemon.configStore.AutoRestart && container.shouldRestart() { if daemon.configStore.AutoRestart && container.shouldRestart() {
logrus.Debugf("Starting container %s", container.ID) logrus.Debugf("Starting container %s", container.ID)
if err := container.Start(); err != nil { if err := daemon.containerStart(container); err != nil {
logrus.Errorf("Failed to start container %s: %s", container.ID, err) logrus.Errorf("Failed to start container %s: %s", container.ID, err)
} }
} }
@ -947,7 +947,8 @@ func (daemon *Daemon) Mount(container *Container) error {
return nil return nil
} }
func (daemon *Daemon) unmount(container *Container) error { // Unmount unsets the container base filesystem
func (daemon *Daemon) Unmount(container *Container) error {
return daemon.driver.Put(container.ID) return daemon.driver.Put(container.ID)
} }

View File

@ -610,6 +610,20 @@ func (daemon *Daemon) newBaseContainer(id string) *Container {
} }
} }
// conditionalMountOnStart is a platform specific helper function during the
// container start to call mount.
func (daemon *Daemon) conditionalMountOnStart(container *Container) error {
return daemon.Mount(container)
}
// conditionalUnmountOnCleanup is a platform specific helper function called
// during the cleanup of a container to unmount.
func (daemon *Daemon) conditionalUnmountOnCleanup(container *Container) {
if err := daemon.Unmount(container); err != nil {
logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err)
}
}
// getDefaultRouteMtu returns the MTU for the default route's interface. // getDefaultRouteMtu returns the MTU for the default route's interface.
func getDefaultRouteMtu() (int, error) { func getDefaultRouteMtu() (int, error) {
routes, err := netlink.RouteList(nil, 0) routes, err := netlink.RouteList(nil, 0)

View File

@ -154,3 +154,26 @@ func (daemon *Daemon) newBaseContainer(id string) *Container {
func (daemon *Daemon) cleanupMounts() error { func (daemon *Daemon) cleanupMounts() error {
return nil return nil
} }
// conditionalMountOnStart is a platform specific helper function during the
// container start to call mount.
func (daemon *Daemon) conditionalMountOnStart(container *Container) error {
// We do not mount if a Hyper-V container
if !container.hostConfig.Isolation.IsHyperV() {
if err := daemon.Mount(container); err != nil {
return err
}
}
return nil
}
// conditionalUnmountOnCleanup is a platform specific helper function called
// during the cleanup of a container to unmount.
func (daemon *Daemon) conditionalUnmountOnCleanup(container *Container) {
// We do not unmount if a Hyper-V container
if !container.hostConfig.Isolation.IsHyperV() {
if err := daemon.Unmount(container); err != nil {
logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err)
}
}
}

View File

@ -96,7 +96,8 @@ func (d Docker) Create(cfg *runconfig.Config, hostCfg *runconfig.HostConfig) (*d
if err != nil { if err != nil {
return nil, ccr.Warnings, err return nil, ccr.Warnings, err
} }
return container, ccr.Warnings, container.Mount()
return container, ccr.Warnings, d.Mount(container)
} }
// Remove removes a container specified by `id`. // Remove removes a container specified by `id`.
@ -210,6 +211,21 @@ func (d Docker) Kill(container *daemon.Container) error {
return d.Daemon.Kill(container) return d.Daemon.Kill(container)
} }
// Mount mounts the root filesystem for the container.
func (d Docker) Mount(c *daemon.Container) error {
return d.Daemon.Mount(c)
}
// Unmount unmounts the root filesystem for the container.
func (d Docker) Unmount(c *daemon.Container) error {
return d.Daemon.Unmount(c)
}
// Start starts a container
func (d Docker) Start(c *daemon.Container) error {
return d.Daemon.Start(c)
}
// Following is specific to builder contexts // Following is specific to builder contexts
// DetectContextFromRemoteURL returns a context and in certain cases the name of the dockerfile to be used // DetectContextFromRemoteURL returns a context and in certain cases the name of the dockerfile to be used

View File

@ -41,12 +41,12 @@ func (daemon *Daemon) containerExport(container *Container) (archive.Archive, er
GIDMaps: gidMaps, GIDMaps: gidMaps,
}) })
if err != nil { if err != nil {
daemon.unmount(container) daemon.Unmount(container)
return nil, err return nil, err
} }
arch := ioutils.NewReadCloserWrapper(archive, func() error { arch := ioutils.NewReadCloserWrapper(archive, func() error {
err := archive.Close() err := archive.Close()
container.Unmount() daemon.Unmount(container)
return err return err
}) })
daemon.logContainerEvent(container, "export") daemon.logContainerEvent(container, "export")

View File

@ -140,7 +140,7 @@ func (daemon *Daemon) getInspectData(container *Container, size bool) (*types.Co
sizeRootFs int64 sizeRootFs int64
) )
if size { if size {
sizeRw, sizeRootFs = container.getSize() sizeRw, sizeRootFs = daemon.getSize(container)
contJSONBase.SizeRw = &sizeRw contJSONBase.SizeRw = &sizeRw
contJSONBase.SizeRootFs = &sizeRootFs contJSONBase.SizeRootFs = &sizeRootFs
} }

View File

@ -369,7 +369,7 @@ func (daemon *Daemon) transformContainer(container *Container, ctx *listContext)
} }
if ctx.Size { if ctx.Size {
sizeRw, sizeRootFs := container.getSize() sizeRw, sizeRootFs := daemon.getSize(container)
newC.SizeRw = sizeRw newC.SizeRw = sizeRw
newC.SizeRootFs = sizeRootFs newC.SizeRootFs = sizeRootFs
} }

View File

@ -29,15 +29,15 @@ func (daemon *Daemon) containerRestart(container *Container, seconds int) error
// Avoid unnecessarily unmounting and then directly mounting // Avoid unnecessarily unmounting and then directly mounting
// the container when the container stops and then starts // the container when the container stops and then starts
// again // again
if err := container.Mount(); err == nil { if err := daemon.Mount(container); err == nil {
defer container.Unmount() defer daemon.Unmount(container)
} }
if err := daemon.containerStop(container, seconds); err != nil { if err := daemon.containerStop(container, seconds); err != nil {
return err return err
} }
if err := container.Start(); err != nil { if err := daemon.containerStart(container); err != nil {
return err return err
} }

View File

@ -44,9 +44,84 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *runconfig.HostConf
return err return err
} }
if err := container.Start(); err != nil { if err := daemon.containerStart(container); err != nil {
return derr.ErrorCodeCantStart.WithArgs(name, utils.GetErrorMessage(err)) return derr.ErrorCodeCantStart.WithArgs(name, utils.GetErrorMessage(err))
} }
return nil return nil
} }
// Start starts a container
func (daemon *Daemon) Start(container *Container) error {
return daemon.containerStart(container)
}
// containerStart prepares the container to run by setting up everything the
// container needs, such as storage and networking, as well as links
// between containers. The container is left waiting for a signal to
// begin running.
func (daemon *Daemon) containerStart(container *Container) (err error) {
container.Lock()
defer container.Unlock()
if container.Running {
return nil
}
if container.removalInProgress || container.Dead {
return derr.ErrorCodeContainerBeingRemoved
}
// if we encounter an error during start we need to ensure that any other
// setup has been cleaned up properly
defer func() {
if err != nil {
container.setError(err)
// if no one else has set it, make sure we don't leave it at zero
if container.ExitCode == 0 {
container.ExitCode = 128
}
container.toDisk()
container.cleanup()
daemon.logContainerEvent(container, "die")
}
}()
if err := daemon.conditionalMountOnStart(container); err != nil {
return err
}
// Make sure NetworkMode has an acceptable value. We do this to ensure
// backwards API compatibility.
container.hostConfig = runconfig.SetDefaultNetModeIfBlank(container.hostConfig)
if err := container.initializeNetworking(); err != nil {
return err
}
linkedEnv, err := container.setupLinkedContainers()
if err != nil {
return err
}
if err := container.setupWorkingDirectory(); err != nil {
return err
}
env := container.createDaemonEnvironment(linkedEnv)
if err := populateCommand(container, env); err != nil {
return err
}
if !container.hostConfig.IpcMode.IsContainer() && !container.hostConfig.IpcMode.IsHost() {
if err := container.setupIpcDirs(); err != nil {
return err
}
}
mounts, err := container.setupMounts()
if err != nil {
return err
}
mounts = append(mounts, container.ipcMounts()...)
container.command.Mounts = mounts
return container.waitForStart()
}