mirror of https://github.com/docker/docs.git
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:
parent
1c94f5f53a
commit
3a49765046
|
@ -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.
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue