github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/daemon/restart.go (about)

     1  package daemon // import "github.com/docker/docker/daemon"
     2  
     3  import (
     4  	"fmt"
     5  
     6  	containertypes "github.com/docker/docker/api/types/container"
     7  	"github.com/docker/docker/container"
     8  	"github.com/sirupsen/logrus"
     9  )
    10  
    11  // ContainerRestart stops and starts a container. It attempts to
    12  // gracefully stop the container within the given timeout, forcefully
    13  // stopping it if the timeout is exceeded. If given a negative
    14  // timeout, ContainerRestart will wait forever until a graceful
    15  // stop. Returns an error if the container cannot be found, or if
    16  // there is an underlying error at any stage of the restart.
    17  func (daemon *Daemon) ContainerRestart(name string, seconds *int) error {
    18  	ctr, err := daemon.GetContainer(name)
    19  	if err != nil {
    20  		return err
    21  	}
    22  	if seconds == nil {
    23  		stopTimeout := ctr.StopTimeout()
    24  		seconds = &stopTimeout
    25  	}
    26  	if err := daemon.containerRestart(ctr, *seconds); err != nil {
    27  		return fmt.Errorf("Cannot restart container %s: %v", name, err)
    28  	}
    29  	return nil
    30  
    31  }
    32  
    33  // containerRestart attempts to gracefully stop and then start the
    34  // container. When stopping, wait for the given duration in seconds to
    35  // gracefully stop, before forcefully terminating the container. If
    36  // given a negative duration, wait forever for a graceful stop.
    37  func (daemon *Daemon) containerRestart(container *container.Container, seconds int) error {
    38  
    39  	// Determine isolation. If not specified in the hostconfig, use daemon default.
    40  	actualIsolation := container.HostConfig.Isolation
    41  	if containertypes.Isolation.IsDefault(actualIsolation) {
    42  		actualIsolation = daemon.defaultIsolation
    43  	}
    44  
    45  	// Avoid unnecessarily unmounting and then directly mounting
    46  	// the container when the container stops and then starts
    47  	// again. We do not do this for Hyper-V isolated containers
    48  	// (implying also on Windows) as the HCS must have exclusive
    49  	// access to mount the containers filesystem inside the utility
    50  	// VM.
    51  	if !containertypes.Isolation.IsHyperV(actualIsolation) {
    52  		if err := daemon.Mount(container); err == nil {
    53  			defer daemon.Unmount(container)
    54  		}
    55  	}
    56  
    57  	if container.IsRunning() {
    58  		// set AutoRemove flag to false before stop so the container won't be
    59  		// removed during restart process
    60  		autoRemove := container.HostConfig.AutoRemove
    61  
    62  		container.HostConfig.AutoRemove = false
    63  		err := daemon.containerStop(container, seconds)
    64  		// restore AutoRemove irrespective of whether the stop worked or not
    65  		container.HostConfig.AutoRemove = autoRemove
    66  		// containerStop will write HostConfig to disk, we shall restore AutoRemove
    67  		// in disk too
    68  		if toDiskErr := daemon.checkpointAndSave(container); toDiskErr != nil {
    69  			logrus.Errorf("Write container to disk error: %v", toDiskErr)
    70  		}
    71  
    72  		if err != nil {
    73  			return err
    74  		}
    75  	}
    76  
    77  	if err := daemon.containerStart(container, "", "", true); err != nil {
    78  		return err
    79  	}
    80  
    81  	daemon.LogContainerEvent(container, "restart")
    82  	return nil
    83  }