daemon/start.go
4180b875
 package daemon
 
 import (
39ad38cc
 	"runtime"
c79b9bab
 
019c337b
 	"github.com/Sirupsen/logrus"
6bb0d181
 	"github.com/docker/docker/container"
a283a30f
 	derr "github.com/docker/docker/errors"
4180b875
 	"github.com/docker/docker/runconfig"
907407d0
 	containertypes "github.com/docker/engine-api/types/container"
4180b875
 )
 
abd72d40
 // ContainerStart starts a container.
7ac4232e
 func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig) error {
d7d512bb
 	container, err := daemon.GetContainer(name)
d25a6537
 	if err != nil {
c79b9bab
 		return err
4180b875
 	}
 
6bb0d181
 	if container.IsPaused() {
f7d4b4fe
 		return derr.ErrorCodeStartPaused
02246d2d
 	}
 
e0339d4b
 	if container.IsRunning() {
f7d4b4fe
 		return derr.ErrorCodeAlreadyStarted
4180b875
 	}
 
51462327
 	// Windows does not have the backwards compatibility issue here.
39ad38cc
 	if runtime.GOOS != "windows" {
 		// This is kept for backward compatibility - hostconfig should be passed when
 		// creating a container, not during start.
 		if hostConfig != nil {
d7117a1b
 			logrus.Warn("DEPRECATED: Setting host configuration options when the container starts is deprecated and will be removed in Docker 1.12")
3d2539d3
 			oldNetworkMode := container.HostConfig.NetworkMode
d8e09066
 			if err := daemon.setSecurityOptions(container, hostConfig); err != nil {
 				return err
 			}
b08f071e
 			if err := daemon.setHostConfig(container, hostConfig); err != nil {
39ad38cc
 				return err
 			}
3d2539d3
 			newNetworkMode := container.HostConfig.NetworkMode
 			if string(oldNetworkMode) != string(newNetworkMode) {
 				// if user has change the network mode on starting, clean up the
 				// old networks. It is a deprecated feature and will be removed in Docker 1.12
 				container.NetworkSettings.Networks = nil
 				if err := container.ToDisk(); err != nil {
 					return err
 				}
 			}
6bb0d181
 			container.InitDNSHostConfig()
39ad38cc
 		}
 	} else {
 		if hostConfig != nil {
f7d4b4fe
 			return derr.ErrorCodeHostConfigStart
4180b875
 		}
 	}
767df67e
 
4177b0ba
 	// check if hostConfig is in line with the current system settings.
 	// It may happen cgroups are umounted or the like.
6bb0d181
 	if _, err = daemon.verifyContainerSettings(container.HostConfig, nil); err != nil {
4177b0ba
 		return err
 	}
f408b4f4
 	// Adapt for old containers in case we have updates in this function and
 	// old containers never have chance to call the new function in create stage.
 	if err := daemon.adaptContainerSettings(container.HostConfig, false); err != nil {
 		return err
4177b0ba
 	}
 
c70f8b3c
 	return daemon.containerStart(container)
4180b875
 }
3a497650
 
 // Start starts a container
6bb0d181
 func (daemon *Daemon) Start(container *container.Container) error {
3a497650
 	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.
6bb0d181
 func (daemon *Daemon) containerStart(container *container.Container) (err error) {
3a497650
 	container.Lock()
 	defer container.Unlock()
 
 	if container.Running {
 		return nil
 	}
 
6bb0d181
 	if container.RemovalInProgress || container.Dead {
3a497650
 		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 {
6bb0d181
 			container.SetError(err)
3a497650
 			// if no one else has set it, make sure we don't leave it at zero
 			if container.ExitCode == 0 {
 				container.ExitCode = 128
 			}
6bb0d181
 			container.ToDisk()
019c337b
 			daemon.Cleanup(container)
ca5ede2d
 			daemon.LogContainerEvent(container, "die")
3a497650
 		}
 	}()
 
 	if err := daemon.conditionalMountOnStart(container); err != nil {
 		return err
 	}
 
 	// Make sure NetworkMode has an acceptable value. We do this to ensure
 	// backwards API compatibility.
6bb0d181
 	container.HostConfig = runconfig.SetDefaultNetModeIfBlank(container.HostConfig)
3a497650
 
669949d6
 	if err := daemon.initializeNetworking(container); err != nil {
3a497650
 		return err
 	}
669949d6
 	linkedEnv, err := daemon.setupLinkedContainers(container)
3a497650
 	if err != nil {
 		return err
 	}
6bb0d181
 	if err := container.SetupWorkingDirectory(); err != nil {
3a497650
 		return err
 	}
6bb0d181
 	env := container.CreateDaemonEnvironment(linkedEnv)
669949d6
 	if err := daemon.populateCommand(container, env); err != nil {
3a497650
 		return err
 	}
 
6bb0d181
 	if !container.HostConfig.IpcMode.IsContainer() && !container.HostConfig.IpcMode.IsHost() {
669949d6
 		if err := daemon.setupIpcDirs(container); err != nil {
3a497650
 			return err
 		}
 	}
 
63efc120
 	mounts, err := daemon.setupMounts(container)
3a497650
 	if err != nil {
 		return err
 	}
6bb0d181
 	mounts = append(mounts, container.IpcMounts()...)
 	mounts = append(mounts, container.TmpfsMounts()...)
3a497650
 
6bb0d181
 	container.Command.Mounts = mounts
8da44905
 	if err := daemon.waitForStart(container); err != nil {
 		return err
 	}
 	container.HasBeenStartedBefore = true
 	return nil
ca5ede2d
 }
 
6bb0d181
 func (daemon *Daemon) waitForStart(container *container.Container) error {
 	return container.StartMonitor(daemon, container.HostConfig.RestartPolicy)
3a497650
 }
019c337b
 
 // Cleanup releases any network resources allocated to the container along with any rules
 // around how containers are linked together.  It also unmounts the container's root filesystem.
6bb0d181
 func (daemon *Daemon) Cleanup(container *container.Container) {
019c337b
 	daemon.releaseNetwork(container)
 
6bb0d181
 	container.UnmountIpcMounts(detachMounted)
019c337b
 
 	daemon.conditionalUnmountOnCleanup(container)
 
6bb0d181
 	for _, eConfig := range container.ExecCommands.Commands() {
9ca2e4e8
 		daemon.unregisterExecCommand(container, eConfig)
019c337b
 	}
 
9d12d093
 	if err := container.UnmountVolumes(false, daemon.LogVolumeEvent); err != nil {
019c337b
 		logrus.Warnf("%s cleanup: Failed to umount volumes: %v", container.ID, err)
 	}
 }