github.com/toplink-cn/moby@v0.0.0-20240305205811-460b4aebdf81/daemon/restart.go (about)

     1  package daemon // import "github.com/docker/docker/daemon"
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	containertypes "github.com/docker/docker/api/types/container"
     8  	"github.com/docker/docker/api/types/events"
     9  	"github.com/docker/docker/container"
    10  	"github.com/docker/docker/internal/compatcontext"
    11  )
    12  
    13  // ContainerRestart stops and starts a container. It attempts to
    14  // gracefully stop the container within the given timeout, forcefully
    15  // stopping it if the timeout is exceeded. If given a negative
    16  // timeout, ContainerRestart will wait forever until a graceful
    17  // stop. Returns an error if the container cannot be found, or if
    18  // there is an underlying error at any stage of the restart.
    19  func (daemon *Daemon) ContainerRestart(ctx context.Context, name string, options containertypes.StopOptions) error {
    20  	ctr, err := daemon.GetContainer(name)
    21  	if err != nil {
    22  		return err
    23  	}
    24  	err = daemon.containerRestart(ctx, daemon.config(), ctr, options)
    25  	if err != nil {
    26  		return fmt.Errorf("Cannot restart container %s: %v", name, err)
    27  	}
    28  	return nil
    29  }
    30  
    31  // containerRestart attempts to gracefully stop and then start the
    32  // container. When stopping, wait for the given duration in seconds to
    33  // gracefully stop, before forcefully terminating the container. If
    34  // given a negative duration, wait forever for a graceful stop.
    35  func (daemon *Daemon) containerRestart(ctx context.Context, daemonCfg *configStore, container *container.Container, options containertypes.StopOptions) error {
    36  	// Restarting is expected to be an atomic operation, and cancelling
    37  	// the request should not cancel the stop -> start sequence.
    38  	ctx = compatcontext.WithoutCancel(ctx)
    39  
    40  	// Determine isolation. If not specified in the hostconfig, use daemon default.
    41  	actualIsolation := container.HostConfig.Isolation
    42  	if containertypes.Isolation.IsDefault(actualIsolation) {
    43  		actualIsolation = daemon.defaultIsolation
    44  	}
    45  
    46  	// Avoid unnecessarily unmounting and then directly mounting
    47  	// the container when the container stops and then starts
    48  	// again. We do not do this for Hyper-V isolated containers
    49  	// (implying also on Windows) as the HCS must have exclusive
    50  	// access to mount the containers filesystem inside the utility
    51  	// VM.
    52  	if !containertypes.Isolation.IsHyperV(actualIsolation) {
    53  		if err := daemon.Mount(container); err == nil {
    54  			defer daemon.Unmount(container)
    55  		}
    56  	}
    57  
    58  	if container.IsRunning() {
    59  		container.Lock()
    60  		container.HasBeenManuallyRestarted = true
    61  		container.Unlock()
    62  
    63  		err := daemon.containerStop(ctx, container, options)
    64  		if err != nil {
    65  			return err
    66  		}
    67  	}
    68  
    69  	if err := daemon.containerStart(ctx, daemonCfg, container, "", "", true); err != nil {
    70  		return err
    71  	}
    72  
    73  	daemon.LogContainerEvent(container, events.ActionRestart)
    74  	return nil
    75  }