restart.go 2.8 KB

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