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