Update RestartPolicy of container
Add `--restart` flag for `update` command, so we can change restart policy for a container no matter it's running or stopped. Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
This commit is contained in:
parent
6668326aa8
commit
ff3ea4c90f
17 changed files with 154 additions and 33 deletions
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
Cli "github.com/docker/docker/cli"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/runconfig/opts"
|
||||
"github.com/docker/engine-api/types/container"
|
||||
"github.com/docker/go-units"
|
||||
)
|
||||
|
@ -25,6 +26,7 @@ func (cli *DockerCli) CmdUpdate(args ...string) error {
|
|||
flMemoryReservation := cmd.String([]string{"-memory-reservation"}, "", "Memory soft limit")
|
||||
flMemorySwap := cmd.String([]string{"-memory-swap"}, "", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap")
|
||||
flKernelMemory := cmd.String([]string{"-kernel-memory"}, "", "Kernel memory limit")
|
||||
flRestartPolicy := cmd.String([]string{"-restart"}, "", "Restart policy to apply when a container exits")
|
||||
|
||||
cmd.Require(flag.Min, 1)
|
||||
cmd.ParseFlags(args, true)
|
||||
|
@ -69,6 +71,14 @@ func (cli *DockerCli) CmdUpdate(args ...string) error {
|
|||
}
|
||||
}
|
||||
|
||||
var restartPolicy container.RestartPolicy
|
||||
if *flRestartPolicy != "" {
|
||||
restartPolicy, err = opts.ParseRestartPolicy(*flRestartPolicy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
resources := container.Resources{
|
||||
BlkioWeight: *flBlkioWeight,
|
||||
CpusetCpus: *flCpusetCpus,
|
||||
|
@ -83,7 +93,8 @@ func (cli *DockerCli) CmdUpdate(args ...string) error {
|
|||
}
|
||||
|
||||
updateConfig := container.UpdateConfig{
|
||||
Resources: resources,
|
||||
Resources: resources,
|
||||
RestartPolicy: restartPolicy,
|
||||
}
|
||||
|
||||
names := cmd.Args()
|
||||
|
|
|
@ -322,7 +322,8 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon
|
|||
}
|
||||
|
||||
hostConfig := &container.HostConfig{
|
||||
Resources: updateConfig.Resources,
|
||||
Resources: updateConfig.Resources,
|
||||
RestartPolicy: updateConfig.RestartPolicy,
|
||||
}
|
||||
|
||||
name := vars["name"]
|
||||
|
|
|
@ -64,7 +64,7 @@ var dockerCommands = []Command{
|
|||
{"tag", "Tag an image into a repository"},
|
||||
{"top", "Display the running processes of a container"},
|
||||
{"unpause", "Unpause all processes within a container"},
|
||||
{"update", "Update resources of one or more containers"},
|
||||
{"update", "Update configuration of one or more containers"},
|
||||
{"version", "Show the Docker version information"},
|
||||
{"volume", "Manage Docker volumes"},
|
||||
{"wait", "Block until a container stops, then print its exit code"},
|
||||
|
|
|
@ -594,3 +594,20 @@ func (container *Container) InitDNSHostConfig() {
|
|||
container.HostConfig.DNSOptions = make([]string, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateMonitor updates monitor configure for running container
|
||||
func (container *Container) UpdateMonitor(restartPolicy containertypes.RestartPolicy) {
|
||||
monitor := container.monitor
|
||||
// No need to update monitor if container hasn't got one
|
||||
// monitor will be generated correctly according to container
|
||||
if monitor == nil {
|
||||
return
|
||||
}
|
||||
|
||||
monitor.mux.Lock()
|
||||
// to check whether restart policy has changed.
|
||||
if restartPolicy.Name != "" && !monitor.restartPolicy.IsSame(&restartPolicy) {
|
||||
monitor.restartPolicy = restartPolicy
|
||||
}
|
||||
monitor.mux.Unlock()
|
||||
}
|
||||
|
|
|
@ -564,10 +564,11 @@ func updateCommand(c *execdriver.Command, resources containertypes.Resources) {
|
|||
c.Resources.KernelMemory = resources.KernelMemory
|
||||
}
|
||||
|
||||
// UpdateContainer updates resources of a container.
|
||||
// UpdateContainer updates configuration of a container.
|
||||
func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfig) error {
|
||||
container.Lock()
|
||||
|
||||
// update resources of container
|
||||
resources := hostConfig.Resources
|
||||
cResources := &container.HostConfig.Resources
|
||||
if resources.BlkioWeight != 0 {
|
||||
|
@ -600,6 +601,11 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi
|
|||
if resources.KernelMemory != 0 {
|
||||
cResources.KernelMemory = resources.KernelMemory
|
||||
}
|
||||
|
||||
// update HostConfig of container
|
||||
if hostConfig.RestartPolicy.Name != "" {
|
||||
container.HostConfig.RestartPolicy = hostConfig.RestartPolicy
|
||||
}
|
||||
container.Unlock()
|
||||
|
||||
// If container is not running, update hostConfig struct is enough,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
|
@ -45,8 +46,22 @@ func (container *Container) TmpfsMounts() []execdriver.Mount {
|
|||
return nil
|
||||
}
|
||||
|
||||
// UpdateContainer updates resources of a container
|
||||
// UpdateContainer updates configuration of a container
|
||||
func (container *Container) UpdateContainer(hostConfig *container.HostConfig) error {
|
||||
container.Lock()
|
||||
defer container.Unlock()
|
||||
resources := hostConfig.Resources
|
||||
if resources.BlkioWeight != 0 || resources.CPUShares != 0 ||
|
||||
resources.CPUPeriod != 0 || resources.CPUQuota != 0 ||
|
||||
resources.CpusetCpus != "" || resources.CpusetMems != "" ||
|
||||
resources.Memory != 0 || resources.MemorySwap != 0 ||
|
||||
resources.MemoryReservation != 0 || resources.KernelMemory != 0 {
|
||||
return fmt.Errorf("Resource updating isn't supported on Windows")
|
||||
}
|
||||
// update HostConfig of container
|
||||
if hostConfig.RestartPolicy.Name != "" {
|
||||
container.HostConfig.RestartPolicy = hostConfig.RestartPolicy
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -79,11 +79,11 @@ type containerMonitor struct {
|
|||
|
||||
// StartMonitor initializes a containerMonitor for this container with the provided supervisor and restart policy
|
||||
// and starts the container's process.
|
||||
func (container *Container) StartMonitor(s supervisor, policy container.RestartPolicy) error {
|
||||
func (container *Container) StartMonitor(s supervisor) error {
|
||||
container.monitor = &containerMonitor{
|
||||
supervisor: s,
|
||||
container: container,
|
||||
restartPolicy: policy,
|
||||
restartPolicy: container.HostConfig.RestartPolicy,
|
||||
timeIncrement: defaultTimeIncrement,
|
||||
stopChan: make(chan struct{}),
|
||||
startSignal: make(chan struct{}),
|
||||
|
|
|
@ -119,11 +119,11 @@ func wait(waitChan <-chan struct{}, timeout time.Duration) error {
|
|||
}
|
||||
}
|
||||
|
||||
// waitRunning waits until state is running. If state is already
|
||||
// WaitRunning waits until state is running. If state is already
|
||||
// running it returns immediately. If you want wait forever you must
|
||||
// supply negative timeout. Returns pid, that was passed to
|
||||
// SetRunning.
|
||||
func (s *State) waitRunning(timeout time.Duration) (int, error) {
|
||||
func (s *State) WaitRunning(timeout time.Duration) (int, error) {
|
||||
s.Lock()
|
||||
if s.Running {
|
||||
pid := s.Pid
|
||||
|
|
|
@ -14,7 +14,7 @@ func TestStateRunStop(t *testing.T) {
|
|||
started := make(chan struct{})
|
||||
var pid int64
|
||||
go func() {
|
||||
runPid, _ := s.waitRunning(-1 * time.Second)
|
||||
runPid, _ := s.WaitRunning(-1 * time.Second)
|
||||
atomic.StoreInt64(&pid, int64(runPid))
|
||||
close(started)
|
||||
}()
|
||||
|
@ -41,8 +41,8 @@ func TestStateRunStop(t *testing.T) {
|
|||
if runPid != i+100 {
|
||||
t.Fatalf("Pid %v, expected %v", runPid, i+100)
|
||||
}
|
||||
if pid, err := s.waitRunning(-1 * time.Second); err != nil || pid != i+100 {
|
||||
t.Fatalf("waitRunning returned pid: %v, err: %v, expected pid: %v, err: %v", pid, err, i+100, nil)
|
||||
if pid, err := s.WaitRunning(-1 * time.Second); err != nil || pid != i+100 {
|
||||
t.Fatalf("WaitRunning returned pid: %v, err: %v, expected pid: %v, err: %v", pid, err, i+100, nil)
|
||||
}
|
||||
|
||||
stopped := make(chan struct{})
|
||||
|
@ -82,7 +82,7 @@ func TestStateTimeoutWait(t *testing.T) {
|
|||
s := NewState()
|
||||
started := make(chan struct{})
|
||||
go func() {
|
||||
s.waitRunning(100 * time.Millisecond)
|
||||
s.WaitRunning(100 * time.Millisecond)
|
||||
close(started)
|
||||
}()
|
||||
select {
|
||||
|
@ -98,7 +98,7 @@ func TestStateTimeoutWait(t *testing.T) {
|
|||
|
||||
stopped := make(chan struct{})
|
||||
go func() {
|
||||
s.waitRunning(100 * time.Millisecond)
|
||||
s.WaitRunning(100 * time.Millisecond)
|
||||
close(stopped)
|
||||
}()
|
||||
select {
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
package windows
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
)
|
||||
|
||||
// Update updates resource configs for a container.
|
||||
func (d *Driver) Update(c *execdriver.Command) error {
|
||||
return fmt.Errorf("Windows: Update not implemented")
|
||||
// Updating resource isn't supported on Windows
|
||||
// but we should return nil for enabling updating container
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ func (daemon *Daemon) containerStart(container *container.Container) (err error)
|
|||
}
|
||||
|
||||
func (daemon *Daemon) waitForStart(container *container.Container) error {
|
||||
return container.StartMonitor(daemon, container.HostConfig.RestartPolicy)
|
||||
return container.StartMonitor(daemon)
|
||||
}
|
||||
|
||||
// Cleanup releases any network resources allocated to the container along with any rules
|
||||
|
|
|
@ -2,12 +2,13 @@ package daemon
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/engine-api/types/container"
|
||||
)
|
||||
|
||||
// ContainerUpdate updates resources of the container
|
||||
// ContainerUpdate updates configuration of the container
|
||||
func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error) {
|
||||
var warnings []string
|
||||
|
||||
|
@ -58,11 +59,19 @@ func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) erro
|
|||
return derr.ErrorCodeCantUpdate.WithArgs(container.ID, err.Error())
|
||||
}
|
||||
|
||||
// if Restart Policy changed, we need to update container monitor
|
||||
container.UpdateMonitor(hostConfig.RestartPolicy)
|
||||
|
||||
// if container is restarting, wait 5 seconds until it's running
|
||||
if container.IsRestarting() {
|
||||
container.WaitRunning(5 * time.Second)
|
||||
}
|
||||
|
||||
// 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.
|
||||
if container.IsRunning() {
|
||||
if container.IsRunning() && !container.IsRestarting() {
|
||||
if err := daemon.execDriver.Update(container.Command); err != nil {
|
||||
return derr.ErrorCodeCantUpdate.WithArgs(container.ID, err.Error())
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ This section lists each version from latest to oldest. Each listing includes a
|
|||
|
||||
* `GET /containers/json` returns the state of the container, one of `created`, `restarting`, `running`, `paused`, `exited` or `dead`.
|
||||
* `GET /networks/(name)` now returns an `Internal` field showing whether the network is internal or not.
|
||||
|
||||
* `POST /containers/(name)/update` now supports updating container's restart policy.
|
||||
|
||||
### v1.22 API changes
|
||||
|
||||
|
|
|
@ -1031,7 +1031,7 @@ Status Codes:
|
|||
|
||||
`POST /containers/(id)/update`
|
||||
|
||||
Update resource configs of one or more containers.
|
||||
Update configuration of one or more containers.
|
||||
|
||||
**Example request**:
|
||||
|
||||
|
@ -1049,6 +1049,10 @@ Update resource configs of one or more containers.
|
|||
"MemorySwap": 514288000,
|
||||
"MemoryReservation": 209715200,
|
||||
"KernelMemory": 52428800,
|
||||
"RestartPolicy": {
|
||||
"MaximumRetryCount": 4,
|
||||
"Name": "on-failure"
|
||||
},
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
|
|
@ -12,7 +12,7 @@ parent = "smn_cli"
|
|||
|
||||
Usage: docker update [OPTIONS] CONTAINER [CONTAINER...]
|
||||
|
||||
Updates container resource limits
|
||||
Update configuration of one or more containers
|
||||
|
||||
--help=false Print usage
|
||||
--blkio-weight=0 Block IO (relative weight), between 10 and 1000
|
||||
|
@ -25,11 +25,12 @@ parent = "smn_cli"
|
|||
--memory-reservation="" Memory soft limit
|
||||
--memory-swap="" A positive integer equal to memory plus swap. Specify -1 to enable unlimited swap
|
||||
--kernel-memory="" Kernel memory limit: container must be stopped
|
||||
--restart Restart policy to apply when a container exits
|
||||
|
||||
The `docker update` command dynamically updates container resources. Use this
|
||||
command to prevent containers from consuming too many resources from their
|
||||
Docker host. With a single command, you can place limits on a single
|
||||
container or on many. To specify more than one container, provide
|
||||
The `docker update` command dynamically updates container configuration.
|
||||
You can use this command to prevent containers from consuming too many resources
|
||||
from their Docker host. With a single command, you can place limits on
|
||||
a single container or on many. To specify more than one container, provide
|
||||
space-separated list of container names or IDs.
|
||||
|
||||
With the exception of the `--kernel-memory` value, you can specify these
|
||||
|
@ -38,6 +39,10 @@ options on a running or a stopped container. You can only update
|
|||
stopped container, the next time you restart it, the container uses those
|
||||
values.
|
||||
|
||||
Another configuration you can change with this command is restart policy,
|
||||
new restart policy will take effect instantly after you run `docker update`
|
||||
on a container.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
The following sections illustrate ways to use this command.
|
||||
|
@ -59,3 +64,10 @@ To update multiple resource configurations for multiple containers:
|
|||
```bash
|
||||
$ docker update --cpu-shares 512 -m 300M abebf7571666 hopeful_morse
|
||||
```
|
||||
|
||||
### Update a container's restart policy
|
||||
|
||||
To update restart policy for one or more containers:
|
||||
```bash
|
||||
$ docker update --restart=on-failure:3 abebf7571666 hopeful_morse
|
||||
```
|
||||
|
|
31
integration-cli/docker_cli_update_test.go
Normal file
31
integration-cli/docker_cli_update_test.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
func (s *DockerSuite) TestUpdateRestartPolicy(c *check.C) {
|
||||
out, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "sh", "-c", "sleep 1 && false")
|
||||
timeout := 60 * time.Second
|
||||
if daemonPlatform == "windows" {
|
||||
timeout = 100 * time.Second
|
||||
}
|
||||
|
||||
id := strings.TrimSpace(string(out))
|
||||
|
||||
// update restart policy to on-failure:5
|
||||
dockerCmd(c, "update", "--restart=on-failure:5", id)
|
||||
|
||||
err := waitExited(id, timeout)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
count := inspectField(c, id, "RestartCount")
|
||||
c.Assert(count, checker.Equals, "5")
|
||||
|
||||
maximumRetryCount := inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount")
|
||||
c.Assert(maximumRetryCount, checker.Equals, "5")
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
% Docker Community
|
||||
% JUNE 2014
|
||||
# NAME
|
||||
docker-update - Update resource configs of one or more containers
|
||||
docker-update - Update configuration of one or more containers
|
||||
|
||||
# SYNOPSIS
|
||||
**docker update**
|
||||
|
@ -17,15 +17,16 @@ docker-update - Update resource configs of one or more containers
|
|||
[**-m**|**--memory**[=*MEMORY*]]
|
||||
[**--memory-reservation**[=*MEMORY-RESERVATION*]]
|
||||
[**--memory-swap**[=*MEMORY-SWAP*]]
|
||||
[**--restart**[=*""*]]
|
||||
CONTAINER [CONTAINER...]
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
The `docker update` command dynamically updates container resources. Use this
|
||||
command to prevent containers from consuming too many resources from their
|
||||
Docker host. With a single command, you can place limits on a single
|
||||
container or on many. To specify more than one container, provide
|
||||
space-separated list of container names or IDs.
|
||||
The `docker update` command dynamically updates container configuration.
|
||||
you can Use this command to prevent containers from consuming too many
|
||||
resources from their Docker host. With a single command, you can place
|
||||
limits on a single container or on many. To specify more than one container,
|
||||
provide space-separated list of container names or IDs.
|
||||
|
||||
With the exception of the `--kernel-memory` value, you can specify these
|
||||
options on a running or a stopped container. You can only update
|
||||
|
@ -33,6 +34,10 @@ options on a running or a stopped container. You can only update
|
|||
stopped container, the next time you restart it, the container uses those
|
||||
values.
|
||||
|
||||
Another configuration you can change with this command is restart policy,
|
||||
new restart policy will take effect instantly after you run `docker update`
|
||||
on a container.
|
||||
|
||||
# OPTIONS
|
||||
**--blkio-weight**=0
|
||||
Block IO weight (relative weight) accepts a weight value between 10 and 1000.
|
||||
|
@ -70,6 +75,9 @@ be updated to a stopped container, and affect after it's started.
|
|||
**--memory-swap**=""
|
||||
Total memory limit (memory + swap)
|
||||
|
||||
**--restart**=""
|
||||
Restart policy to apply when a container exits (no, on-failure[:max-retry], always, unless-stopped).
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
The following sections illustrate ways to use this command.
|
||||
|
@ -91,3 +99,10 @@ To update multiple resource configurations for multiple containers:
|
|||
```bash
|
||||
$ docker update --cpu-shares 512 -m 300M abebf7571666 hopeful_morse
|
||||
```
|
||||
|
||||
### Update a container's restart policy
|
||||
|
||||
To update restart policy for one or more containers:
|
||||
```bash
|
||||
$ docker update --restart=on-failure:3 abebf7571666 hopeful_morse
|
||||
```
|
||||
|
|
Loading…
Reference in a new issue