Files
moby/client/container_restart.go
Paweł Gronowski 99c1a9c778 daemon: Add configurable default container stop timeout
A container that defines no stop timeout of its own always got 10
seconds on Linux, or 30 on Windows, to shut down before being killed.
The value was a constant in the container package, so operators who
wanted a different grace period had to pass `--stop-timeout` on every
container.

Add a `default-stop-timeout` daemon flag and configuration file option
that supplies that fallback. Stopping a container, killing it, and
computing the daemon shutdown timeout take the value from the daemon
configuration when the container has no timeout of its own, so an
explicit per-container timeout still wins and the container
configuration itself stays untouched. The option can be reloaded, and
negative values are rejected.

mergo cannot tell an unset option from a zero value, so a configured
timeout of `0`, meaning "kill immediately", would be replaced by the
non-zero flag default while merging. Remember whether the
configuration file set the option, and restore its value after the
merge.

`ContainerConfig.StopTimeout` in the API documentation no longer
claims a fixed default of 10 seconds, because the fallback is now
whatever `default-stop-timeout` holds.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-07-27 14:15:55 +02:00

56 lines
1.9 KiB
Go

package client
import (
"context"
"net/url"
"strconv"
)
// ContainerRestartOptions holds options for [Client.ContainerRestart].
type ContainerRestartOptions struct {
// Signal (optional) is the signal to send to the container to (gracefully)
// stop it before forcibly terminating the container with SIGKILL after the
// timeout expires. If no value is set, the default (SIGTERM) is used.
Signal string `json:",omitempty"`
// Timeout (optional) is the timeout (in seconds) to wait for the container
// to stop gracefully before forcibly terminating it with SIGKILL.
//
// - Use nil to use the container's configured timeout, or the engine default
// if the container has no configured timeout.
// - Use '-1' to wait indefinitely.
// - Use '0' to not wait for the container to exit gracefully, and
// immediately proceeds to forcibly terminating the container.
// - Other positive values are used as timeout (in seconds).
Timeout *int `json:",omitempty"`
}
// ContainerRestartResult holds the result of [Client.ContainerRestart],
type ContainerRestartResult struct {
// Add future fields here.
}
// ContainerRestart stops, and starts a container again.
// It makes the daemon wait for the container to be up again for
// a specific amount of time, given the timeout.
func (cli *Client) ContainerRestart(ctx context.Context, containerID string, options ContainerRestartOptions) (ContainerRestartResult, error) {
containerID, err := trimID("container", containerID)
if err != nil {
return ContainerRestartResult{}, err
}
query := url.Values{}
if options.Timeout != nil {
query.Set("t", strconv.Itoa(*options.Timeout))
}
if options.Signal != "" {
query.Set("signal", options.Signal)
}
resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil)
defer ensureReaderClosed(resp)
if err != nil {
return ContainerRestartResult{}, err
}
return ContainerRestartResult{}, nil
}