daemon/update.go
8799c4fc
 package daemon
 
 import (
 	"fmt"
 
91e197d6
 	"github.com/docker/docker/api/types/container"
ebcb7d6b
 	"github.com/pkg/errors"
8799c4fc
 )
 
ff3ea4c9
 // ContainerUpdate updates configuration of the container
ef39256d
 func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error) {
8799c4fc
 	var warnings []string
 
9fa44906
 	c, err := daemon.GetContainer(name)
 	if err != nil {
 		return container.ContainerUpdateOKBody{Warnings: warnings}, err
 	}
 
0380fbff
 	warnings, err = daemon.verifyContainerSettings(c.OS, hostConfig, nil, true)
8799c4fc
 	if err != nil {
ebcb7d6b
 		return container.ContainerUpdateOKBody{Warnings: warnings}, validationError{err}
8799c4fc
 	}
 
 	if err := daemon.update(name, hostConfig); err != nil {
f196cf6a
 		return container.ContainerUpdateOKBody{Warnings: warnings}, err
8799c4fc
 	}
 
f196cf6a
 	return container.ContainerUpdateOKBody{Warnings: warnings}, nil
8799c4fc
 }
 
 func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) error {
 	if hostConfig == nil {
 		return nil
 	}
 
 	container, err := daemon.GetContainer(name)
 	if err != nil {
 		return err
 	}
 
fa3b1971
 	restoreConfig := false
 	backupHostConfig := *container.HostConfig
 	defer func() {
 		if restoreConfig {
 			container.Lock()
 			container.HostConfig = &backupHostConfig
edad5270
 			container.CheckpointTo(daemon.containersReplica)
fa3b1971
 			container.Unlock()
 		}
 	}()
 
8799c4fc
 	if container.RemovalInProgress || container.Dead {
9b47b7b1
 		return errCannotUpdate(container.ID, fmt.Errorf("container is marked for removal and cannot be \"update\""))
8799c4fc
 	}
 
eed4c7b7
 	container.Lock()
8799c4fc
 	if err := container.UpdateContainer(hostConfig); err != nil {
fa3b1971
 		restoreConfig = true
eed4c7b7
 		container.Unlock()
a793564b
 		return errCannotUpdate(container.ID, err)
8799c4fc
 	}
aacddda8
 	if err := container.CheckpointTo(daemon.containersReplica); err != nil {
eed4c7b7
 		restoreConfig = true
 		container.Unlock()
 		return errCannotUpdate(container.ID, err)
 	}
 	container.Unlock()
8799c4fc
 
ff3ea4c9
 	// if Restart Policy changed, we need to update container monitor
737b5b17
 	if hostConfig.RestartPolicy.Name != "" {
 		container.UpdateMonitor(hostConfig.RestartPolicy)
 	}
ff3ea4c9
 
8799c4fc
 	// If container is not running, update hostConfig struct is enough,
 	// resources will be updated when the container is started again.
 	// If container is running (including paused), we need to update configs
 	// to the real world.
ff3ea4c9
 	if container.IsRunning() && !container.IsRestarting() {
9c4570a9
 		if err := daemon.containerd.UpdateResources(container.ID, toContainerdResources(hostConfig.Resources)); err != nil {
fa3b1971
 			restoreConfig = true
ebcb7d6b
 			// TODO: it would be nice if containerd responded with better errors here so we can classify this better.
 			return errCannotUpdate(container.ID, systemError{err})
8799c4fc
 		}
 	}
 
72f1881d
 	daemon.LogContainerEvent(container, "update")
 
8799c4fc
 	return nil
 }
a793564b
 
 func errCannotUpdate(containerID string, err error) error {
ebcb7d6b
 	return errors.Wrap(err, "Cannot update container "+containerID)
a793564b
 }