github.com/lazyboychen7/engine@v17.12.1-ce-rc2+incompatible/daemon/update.go (about) 1 package daemon 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/docker/docker/api/types/container" 8 "github.com/pkg/errors" 9 ) 10 11 // ContainerUpdate updates configuration of the container 12 func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error) { 13 var warnings []string 14 15 c, err := daemon.GetContainer(name) 16 if err != nil { 17 return container.ContainerUpdateOKBody{Warnings: warnings}, err 18 } 19 20 warnings, err = daemon.verifyContainerSettings(c.OS, hostConfig, nil, true) 21 if err != nil { 22 return container.ContainerUpdateOKBody{Warnings: warnings}, validationError{err} 23 } 24 25 if err := daemon.update(name, hostConfig); err != nil { 26 return container.ContainerUpdateOKBody{Warnings: warnings}, err 27 } 28 29 return container.ContainerUpdateOKBody{Warnings: warnings}, nil 30 } 31 32 func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) error { 33 if hostConfig == nil { 34 return nil 35 } 36 37 container, err := daemon.GetContainer(name) 38 if err != nil { 39 return err 40 } 41 42 restoreConfig := false 43 backupHostConfig := *container.HostConfig 44 defer func() { 45 if restoreConfig { 46 container.Lock() 47 container.HostConfig = &backupHostConfig 48 container.CheckpointTo(daemon.containersReplica) 49 container.Unlock() 50 } 51 }() 52 53 if container.RemovalInProgress || container.Dead { 54 return errCannotUpdate(container.ID, fmt.Errorf("container is marked for removal and cannot be \"update\"")) 55 } 56 57 container.Lock() 58 if err := container.UpdateContainer(hostConfig); err != nil { 59 restoreConfig = true 60 container.Unlock() 61 return errCannotUpdate(container.ID, err) 62 } 63 if err := container.CheckpointTo(daemon.containersReplica); err != nil { 64 restoreConfig = true 65 container.Unlock() 66 return errCannotUpdate(container.ID, err) 67 } 68 container.Unlock() 69 70 // if Restart Policy changed, we need to update container monitor 71 if hostConfig.RestartPolicy.Name != "" { 72 container.UpdateMonitor(hostConfig.RestartPolicy) 73 } 74 75 // If container is not running, update hostConfig struct is enough, 76 // resources will be updated when the container is started again. 77 // If container is running (including paused), we need to update configs 78 // to the real world. 79 if container.IsRunning() && !container.IsRestarting() { 80 if err := daemon.containerd.UpdateResources(context.Background(), container.ID, toContainerdResources(hostConfig.Resources)); err != nil { 81 restoreConfig = true 82 // TODO: it would be nice if containerd responded with better errors here so we can classify this better. 83 return errCannotUpdate(container.ID, systemError{err}) 84 } 85 } 86 87 daemon.LogContainerEvent(container, "update") 88 89 return nil 90 } 91 92 func errCannotUpdate(containerID string, err error) error { 93 return errors.Wrap(err, "Cannot update container "+containerID) 94 }