Merge pull request #28408 from vieux/1.13.0-rc2-cherrypicks
1.13.0 rc2 cherrypicks
This commit is contained in:
commit
2dfa08bc50
47 changed files with 698 additions and 328 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -17,6 +17,7 @@ bundles/
|
|||
cmd/dockerd/dockerd
|
||||
cmd/docker/docker
|
||||
dockerversion/version_autogen.go
|
||||
dockerversion/version_autogen_unix.go
|
||||
docs/AWS_S3_BUCKET
|
||||
docs/GITCOMMIT
|
||||
docs/GIT_BRANCH
|
||||
|
|
|
@ -62,6 +62,12 @@ func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
|
|||
type preProcessor struct {
|
||||
types.Container
|
||||
opts *types.ContainerListOptions
|
||||
|
||||
// Fields that need to exist so the template doesn't error out
|
||||
// These are needed since they are available on the final object but are not
|
||||
// fields in types.Container
|
||||
// TODO(cpuguy83): this seems rather broken
|
||||
Networks, CreatedAt, RunningFor bool
|
||||
}
|
||||
|
||||
// Size sets the size option when called by a template execution.
|
||||
|
@ -70,13 +76,6 @@ func (p *preProcessor) Size() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// Networks does nothing but return true.
|
||||
// It is needed to avoid the template check to fail as this field
|
||||
// doesn't exist in `types.Container`
|
||||
func (p *preProcessor) Networks() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, error) {
|
||||
options := &types.ContainerListOptions{
|
||||
All: opts.all,
|
||||
|
|
|
@ -370,3 +370,29 @@ func TestContainerContextWriteJSONField(t *testing.T) {
|
|||
assert.Equal(t, s, containers[i].ID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerBackCompat(t *testing.T) {
|
||||
containers := []types.Container{types.Container{ID: "brewhaha"}}
|
||||
cases := []string{
|
||||
"ID",
|
||||
"Names",
|
||||
"Image",
|
||||
"Command",
|
||||
"CreatedAt",
|
||||
"RunningFor",
|
||||
"Ports",
|
||||
"Status",
|
||||
"Size",
|
||||
"Labels",
|
||||
"Mounts",
|
||||
}
|
||||
buf := bytes.NewBuffer(nil)
|
||||
for _, c := range cases {
|
||||
ctx := Context{Format: Format(fmt.Sprintf("{{ .%s }}", c)), Output: buf}
|
||||
if err := ContainerWrite(ctx, containers); err != nil {
|
||||
t.Log("could not render template for field '%s': %v", c, err)
|
||||
t.Fail()
|
||||
}
|
||||
buf.Reset()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ import (
|
|||
|
||||
func newPushCommand(dockerCli *command.DockerCli) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "push PLUGIN",
|
||||
Short: "Push a plugin",
|
||||
Use: "push NAME[:TAG]",
|
||||
Short: "Push a plugin to a registry",
|
||||
Args: cli.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runPush(dockerCli, args[0])
|
||||
|
|
|
@ -62,12 +62,16 @@ func runCreate(dockerCli *command.DockerCli, opts *serviceOptions) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// parse and validate secrets
|
||||
secrets, err := parseSecrets(apiClient, opts.secrets.Value())
|
||||
if err != nil {
|
||||
return err
|
||||
specifiedSecrets := opts.secrets.Value()
|
||||
if len(specifiedSecrets) > 0 {
|
||||
// parse and validate secrets
|
||||
secrets, err := parseSecrets(apiClient, specifiedSecrets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
service.TaskTemplate.ContainerSpec.Secrets = secrets
|
||||
|
||||
}
|
||||
service.TaskTemplate.ContainerSpec.Secrets = secrets
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
|
|
|
@ -126,8 +126,10 @@ func dockerPreRun(opts *cliflags.ClientOptions) {
|
|||
func hideUnsupportedFeatures(cmd *cobra.Command, clientVersion string, hasExperimental bool) {
|
||||
cmd.Flags().VisitAll(func(f *pflag.Flag) {
|
||||
// hide experimental flags
|
||||
if _, ok := f.Annotations["experimental"]; ok {
|
||||
f.Hidden = true
|
||||
if !hasExperimental {
|
||||
if _, ok := f.Annotations["experimental"]; ok {
|
||||
f.Hidden = true
|
||||
}
|
||||
}
|
||||
|
||||
// hide flags not supported by the server
|
||||
|
@ -139,8 +141,10 @@ func hideUnsupportedFeatures(cmd *cobra.Command, clientVersion string, hasExperi
|
|||
|
||||
for _, subcmd := range cmd.Commands() {
|
||||
// hide experimental subcommands
|
||||
if _, ok := subcmd.Tags["experimental"]; ok {
|
||||
subcmd.Hidden = true
|
||||
if !hasExperimental {
|
||||
if _, ok := subcmd.Tags["experimental"]; ok {
|
||||
subcmd.Hidden = true
|
||||
}
|
||||
}
|
||||
|
||||
// hide subcommands not supported by the server
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
containertypes "github.com/docker/docker/api/types/container"
|
||||
mounttypes "github.com/docker/docker/api/types/mount"
|
||||
networktypes "github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/container/stream"
|
||||
"github.com/docker/docker/daemon/exec"
|
||||
"github.com/docker/docker/daemon/logger"
|
||||
"github.com/docker/docker/daemon/logger/jsonfilelog"
|
||||
|
@ -65,7 +66,7 @@ func (DetachError) Error() string {
|
|||
// CommonContainer holds the fields for a container which are
|
||||
// applicable across all platforms supported by the daemon.
|
||||
type CommonContainer struct {
|
||||
*runconfig.StreamConfig
|
||||
StreamConfig *stream.Config
|
||||
// embed for Container to support states directly.
|
||||
*State `json:"State"` // Needed for remote api version <= 1.11
|
||||
Root string `json:"-"` // Path to the "home" of the container, including metadata.
|
||||
|
@ -109,7 +110,7 @@ func NewBaseContainer(id, root string) *Container {
|
|||
ExecCommands: exec.NewStore(),
|
||||
Root: root,
|
||||
MountPoints: make(map[string]*volume.MountPoint),
|
||||
StreamConfig: runconfig.NewStreamConfig(),
|
||||
StreamConfig: stream.NewConfig(),
|
||||
attachContext: &attachContext{},
|
||||
},
|
||||
}
|
||||
|
@ -377,7 +378,7 @@ func (container *Container) Attach(stdin io.ReadCloser, stdout io.Writer, stderr
|
|||
|
||||
// AttachStreams connects streams to a TTY.
|
||||
// Used by exec too. Should this move somewhere else?
|
||||
func AttachStreams(ctx context.Context, streamConfig *runconfig.StreamConfig, openStdin, stdinOnce, tty bool, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer, keys []byte) chan error {
|
||||
func AttachStreams(ctx context.Context, streamConfig *stream.Config, openStdin, stdinOnce, tty bool, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer, keys []byte) chan error {
|
||||
var (
|
||||
cStdout, cStderr io.ReadCloser
|
||||
cStdin io.WriteCloser
|
||||
|
@ -1064,6 +1065,26 @@ func (container *Container) startLogging() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// StdinPipe gets the stdin stream of the container
|
||||
func (container *Container) StdinPipe() io.WriteCloser {
|
||||
return container.StreamConfig.StdinPipe()
|
||||
}
|
||||
|
||||
// StdoutPipe gets the stdout stream of the container
|
||||
func (container *Container) StdoutPipe() io.ReadCloser {
|
||||
return container.StreamConfig.StdoutPipe()
|
||||
}
|
||||
|
||||
// StderrPipe gets the stderr stream of the container
|
||||
func (container *Container) StderrPipe() io.ReadCloser {
|
||||
return container.StreamConfig.StderrPipe()
|
||||
}
|
||||
|
||||
// CloseStreams closes the container's stdio streams
|
||||
func (container *Container) CloseStreams() error {
|
||||
return container.StreamConfig.CloseStreams()
|
||||
}
|
||||
|
||||
// InitializeStdio is called by libcontainerd to connect the stdio.
|
||||
func (container *Container) InitializeStdio(iop libcontainerd.IOPipe) error {
|
||||
if err := container.startLogging(); err != nil {
|
||||
|
@ -1073,7 +1094,7 @@ func (container *Container) InitializeStdio(iop libcontainerd.IOPipe) error {
|
|||
|
||||
container.StreamConfig.CopyToPipe(iop)
|
||||
|
||||
if container.Stdin() == nil && !container.Config.Tty {
|
||||
if container.StreamConfig.Stdin() == nil && !container.Config.Tty {
|
||||
if iop.Stdin != nil {
|
||||
if err := iop.Stdin.Close(); err != nil {
|
||||
logrus.Warnf("error closing stdin: %+v", err)
|
||||
|
|
|
@ -23,7 +23,7 @@ func (container *Container) Reset(lock bool) {
|
|||
|
||||
// Re-create a brand new stdin pipe once the container exited
|
||||
if container.Config.OpenStdin {
|
||||
container.NewInputPipes()
|
||||
container.StreamConfig.NewInputPipes()
|
||||
}
|
||||
|
||||
if container.LogDriver != nil {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package runconfig
|
||||
package stream
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -14,16 +14,16 @@ import (
|
|||
"github.com/docker/docker/pkg/pools"
|
||||
)
|
||||
|
||||
// StreamConfig holds information about I/O streams managed together.
|
||||
// Config holds information about I/O streams managed together.
|
||||
//
|
||||
// streamConfig.StdinPipe returns a WriteCloser which can be used to feed data
|
||||
// config.StdinPipe returns a WriteCloser which can be used to feed data
|
||||
// to the standard input of the streamConfig's active process.
|
||||
// streamConfig.StdoutPipe and streamConfig.StderrPipe each return a ReadCloser
|
||||
// config.StdoutPipe and streamConfig.StderrPipe each return a ReadCloser
|
||||
// which can be used to retrieve the standard output (and error) generated
|
||||
// by the container's active process. The output (and error) are actually
|
||||
// copied and delivered to all StdoutPipe and StderrPipe consumers, using
|
||||
// a kind of "broadcaster".
|
||||
type StreamConfig struct {
|
||||
type Config struct {
|
||||
sync.WaitGroup
|
||||
stdout *broadcaster.Unbuffered
|
||||
stderr *broadcaster.Unbuffered
|
||||
|
@ -31,76 +31,76 @@ type StreamConfig struct {
|
|||
stdinPipe io.WriteCloser
|
||||
}
|
||||
|
||||
// NewStreamConfig creates a stream config and initializes
|
||||
// NewConfig creates a stream config and initializes
|
||||
// the standard err and standard out to new unbuffered broadcasters.
|
||||
func NewStreamConfig() *StreamConfig {
|
||||
return &StreamConfig{
|
||||
func NewConfig() *Config {
|
||||
return &Config{
|
||||
stderr: new(broadcaster.Unbuffered),
|
||||
stdout: new(broadcaster.Unbuffered),
|
||||
}
|
||||
}
|
||||
|
||||
// Stdout returns the standard output in the configuration.
|
||||
func (streamConfig *StreamConfig) Stdout() *broadcaster.Unbuffered {
|
||||
return streamConfig.stdout
|
||||
func (c *Config) Stdout() *broadcaster.Unbuffered {
|
||||
return c.stdout
|
||||
}
|
||||
|
||||
// Stderr returns the standard error in the configuration.
|
||||
func (streamConfig *StreamConfig) Stderr() *broadcaster.Unbuffered {
|
||||
return streamConfig.stderr
|
||||
func (c *Config) Stderr() *broadcaster.Unbuffered {
|
||||
return c.stderr
|
||||
}
|
||||
|
||||
// Stdin returns the standard input in the configuration.
|
||||
func (streamConfig *StreamConfig) Stdin() io.ReadCloser {
|
||||
return streamConfig.stdin
|
||||
func (c *Config) Stdin() io.ReadCloser {
|
||||
return c.stdin
|
||||
}
|
||||
|
||||
// StdinPipe returns an input writer pipe as an io.WriteCloser.
|
||||
func (streamConfig *StreamConfig) StdinPipe() io.WriteCloser {
|
||||
return streamConfig.stdinPipe
|
||||
func (c *Config) StdinPipe() io.WriteCloser {
|
||||
return c.stdinPipe
|
||||
}
|
||||
|
||||
// StdoutPipe creates a new io.ReadCloser with an empty bytes pipe.
|
||||
// It adds this new out pipe to the Stdout broadcaster.
|
||||
func (streamConfig *StreamConfig) StdoutPipe() io.ReadCloser {
|
||||
func (c *Config) StdoutPipe() io.ReadCloser {
|
||||
bytesPipe := ioutils.NewBytesPipe()
|
||||
streamConfig.stdout.Add(bytesPipe)
|
||||
c.stdout.Add(bytesPipe)
|
||||
return bytesPipe
|
||||
}
|
||||
|
||||
// StderrPipe creates a new io.ReadCloser with an empty bytes pipe.
|
||||
// It adds this new err pipe to the Stderr broadcaster.
|
||||
func (streamConfig *StreamConfig) StderrPipe() io.ReadCloser {
|
||||
func (c *Config) StderrPipe() io.ReadCloser {
|
||||
bytesPipe := ioutils.NewBytesPipe()
|
||||
streamConfig.stderr.Add(bytesPipe)
|
||||
c.stderr.Add(bytesPipe)
|
||||
return bytesPipe
|
||||
}
|
||||
|
||||
// NewInputPipes creates new pipes for both standard inputs, Stdin and StdinPipe.
|
||||
func (streamConfig *StreamConfig) NewInputPipes() {
|
||||
streamConfig.stdin, streamConfig.stdinPipe = io.Pipe()
|
||||
func (c *Config) NewInputPipes() {
|
||||
c.stdin, c.stdinPipe = io.Pipe()
|
||||
}
|
||||
|
||||
// NewNopInputPipe creates a new input pipe that will silently drop all messages in the input.
|
||||
func (streamConfig *StreamConfig) NewNopInputPipe() {
|
||||
streamConfig.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard)
|
||||
func (c *Config) NewNopInputPipe() {
|
||||
c.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard)
|
||||
}
|
||||
|
||||
// CloseStreams ensures that the configured streams are properly closed.
|
||||
func (streamConfig *StreamConfig) CloseStreams() error {
|
||||
func (c *Config) CloseStreams() error {
|
||||
var errors []string
|
||||
|
||||
if streamConfig.stdin != nil {
|
||||
if err := streamConfig.stdin.Close(); err != nil {
|
||||
if c.stdin != nil {
|
||||
if err := c.stdin.Close(); err != nil {
|
||||
errors = append(errors, fmt.Sprintf("error close stdin: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
if err := streamConfig.stdout.Clean(); err != nil {
|
||||
if err := c.stdout.Clean(); err != nil {
|
||||
errors = append(errors, fmt.Sprintf("error close stdout: %s", err))
|
||||
}
|
||||
|
||||
if err := streamConfig.stderr.Clean(); err != nil {
|
||||
if err := c.stderr.Clean(); err != nil {
|
||||
errors = append(errors, fmt.Sprintf("error close stderr: %s", err))
|
||||
}
|
||||
|
||||
|
@ -112,25 +112,25 @@ func (streamConfig *StreamConfig) CloseStreams() error {
|
|||
}
|
||||
|
||||
// CopyToPipe connects streamconfig with a libcontainerd.IOPipe
|
||||
func (streamConfig *StreamConfig) CopyToPipe(iop libcontainerd.IOPipe) {
|
||||
func (c *Config) CopyToPipe(iop libcontainerd.IOPipe) {
|
||||
copyFunc := func(w io.Writer, r io.Reader) {
|
||||
streamConfig.Add(1)
|
||||
c.Add(1)
|
||||
go func() {
|
||||
if _, err := pools.Copy(w, r); err != nil {
|
||||
logrus.Errorf("stream copy error: %+v", err)
|
||||
}
|
||||
streamConfig.Done()
|
||||
c.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
if iop.Stdout != nil {
|
||||
copyFunc(streamConfig.Stdout(), iop.Stdout)
|
||||
copyFunc(c.Stdout(), iop.Stdout)
|
||||
}
|
||||
if iop.Stderr != nil {
|
||||
copyFunc(streamConfig.Stderr(), iop.Stderr)
|
||||
copyFunc(c.Stderr(), iop.Stderr)
|
||||
}
|
||||
|
||||
if stdin := streamConfig.Stdin(); stdin != nil {
|
||||
if stdin := c.Stdin(); stdin != nil {
|
||||
if iop.Stdin != nil {
|
||||
go func() {
|
||||
pools.Copy(iop.Stdin, stdin)
|
|
@ -1121,7 +1121,7 @@ _docker_container_ls() {
|
|||
|
||||
case "$prev" in
|
||||
--filter|-f)
|
||||
COMPREPLY=( $( compgen -S = -W "ancestor before exited health id label name network since status volume" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -S = -W "ancestor before exited health id is-task label name network since status volume" -- "$cur" ) )
|
||||
__docker_nospace
|
||||
return
|
||||
;;
|
||||
|
@ -1901,6 +1901,7 @@ _docker_image() {
|
|||
_docker_image_build() {
|
||||
local options_with_args="
|
||||
--build-arg
|
||||
--cache-from
|
||||
--cgroup-parent
|
||||
--cpuset-cpus
|
||||
--cpuset-mems
|
||||
|
@ -1936,6 +1937,10 @@ _docker_image_build() {
|
|||
__docker_nospace
|
||||
return
|
||||
;;
|
||||
--cache-from)
|
||||
__docker_complete_image_repos_and_tags
|
||||
return
|
||||
;;
|
||||
--file|-f)
|
||||
_filedir
|
||||
return
|
||||
|
@ -2582,7 +2587,7 @@ _docker_service_ps() {
|
|||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "--filter -f --help --no-resolve --no-trunc --quiet -q" -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W "--all -a --filter -f --help --no-resolve --no-trunc --quiet -q" -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
local counter=$(__docker_pos_first_nonflag '--filter|-f')
|
||||
|
@ -2643,11 +2648,15 @@ _docker_service_update() {
|
|||
if [ "$subcommand" = "create" ] ; then
|
||||
options_with_args="$options_with_args
|
||||
--container-label
|
||||
--dns
|
||||
--dns-option
|
||||
--dns-search
|
||||
--env-file
|
||||
--group
|
||||
--hostname
|
||||
--mode
|
||||
--name
|
||||
--port
|
||||
"
|
||||
|
||||
case "$prev" in
|
||||
|
@ -2670,9 +2679,17 @@ _docker_service_update() {
|
|||
--arg
|
||||
--container-label-add
|
||||
--container-label-rm
|
||||
--dns-add
|
||||
--dns-option-add
|
||||
--dns-option-rm
|
||||
--dns-rm
|
||||
--dns-search-add
|
||||
--dns-search-rm
|
||||
--group-add
|
||||
--group-rm
|
||||
--image
|
||||
--port-add
|
||||
--port-rm
|
||||
"
|
||||
|
||||
case "$prev" in
|
||||
|
|
|
@ -900,7 +900,8 @@ __docker_image_subcommand() {
|
|||
(build)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help)*--build-arg[Build-time variables]:<varname>=<value>: " \
|
||||
"($help)*--build-arg=[Build-time variables]:<varname>=<value>: " \
|
||||
"($help)*--cache-from=[Images to consider as cache sources]: :__docker_complete_repositories_with_tags" \
|
||||
"($help -c --cpu-shares)"{-c=,--cpu-shares=}"[CPU shares (relative weight)]:CPU shares:(0 10 100 200 500 800 1000)" \
|
||||
"($help)--cgroup-parent=[Parent cgroup for the container]:cgroup: " \
|
||||
"($help)--compress[Compress the build context using gzip]" \
|
||||
|
@ -917,6 +918,7 @@ __docker_image_subcommand() {
|
|||
"($help)*--label=[Set metadata for an image]:label=value: " \
|
||||
"($help -m --memory)"{-m=,--memory=}"[Memory limit]:Memory limit: " \
|
||||
"($help)--memory-swap=[Total memory limit with swap]:Memory limit: " \
|
||||
"($help)--network=[Connect a container to a network]:network mode:(bridge none container host)"
|
||||
"($help)--no-cache[Do not use cache when building the image]" \
|
||||
"($help)--pull[Attempt to pull a newer version of the image]" \
|
||||
"($help -q --quiet)"{-q,--quiet}"[Suppress verbose build output]" \
|
||||
|
@ -1514,6 +1516,107 @@ __docker_plugin_subcommand() {
|
|||
|
||||
# EO plugin
|
||||
|
||||
# BO secret
|
||||
|
||||
__docker_secrets() {
|
||||
[[ $PREFIX = -* ]] && return 1
|
||||
integer ret=1
|
||||
local line s
|
||||
declare -a lines secrets
|
||||
|
||||
type=$1; shift
|
||||
|
||||
lines=(${(f)${:-"$(_call_program commands docker $docker_options secret ls)"$'\n'}})
|
||||
|
||||
# Parse header line to find columns
|
||||
local i=1 j=1 k header=${lines[1]}
|
||||
declare -A begin end
|
||||
while (( j < ${#header} - 1 )); do
|
||||
i=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 1 ))
|
||||
j=$(( i + ${${header[$i,-1]}[(i) ]} - 1 ))
|
||||
k=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 2 ))
|
||||
begin[${header[$i,$((j-1))]}]=$i
|
||||
end[${header[$i,$((j-1))]}]=$k
|
||||
done
|
||||
end[${header[$i,$((j-1))]}]=-1
|
||||
lines=(${lines[2,-1]})
|
||||
|
||||
# ID
|
||||
if [[ $type = (ids|all) ]]; then
|
||||
for line in $lines; do
|
||||
s="${line[${begin[ID]},${end[ID]}]%% ##}"
|
||||
secrets=($secrets $s)
|
||||
done
|
||||
fi
|
||||
|
||||
# Names
|
||||
if [[ $type = (names|all) ]]; then
|
||||
for line in $lines; do
|
||||
s="${line[${begin[NAME]},${end[NAME]}]%% ##}"
|
||||
secrets=($secrets $s)
|
||||
done
|
||||
fi
|
||||
|
||||
_describe -t secrets-list "secrets" secrets "$@" && ret=0
|
||||
return ret
|
||||
}
|
||||
|
||||
__docker_complete_secrets() {
|
||||
[[ $PREFIX = -* ]] && return 1
|
||||
__docker_secrets all "$@"
|
||||
}
|
||||
|
||||
__docker_secret_commands() {
|
||||
local -a _docker_secret_subcommands
|
||||
_docker_secret_subcommands=(
|
||||
"create:Create a secret using stdin as content"
|
||||
"inspect:Display detailed information on one or more secrets"
|
||||
"ls:List secrets"
|
||||
"rm:Remove one or more secrets"
|
||||
)
|
||||
_describe -t docker-secret-commands "docker secret command" _docker_secret_subcommands
|
||||
}
|
||||
|
||||
__docker_secret_subcommand() {
|
||||
local -a _command_args opts_help
|
||||
local expl help="--help"
|
||||
integer ret=1
|
||||
|
||||
opts_help=("(: -)--help[Print usage]")
|
||||
|
||||
case "$words[1]" in
|
||||
(create)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help)*"{-l=,--label=}"[Secret labels]:label: " \
|
||||
"($help -):secret: " && ret=0
|
||||
;;
|
||||
(inspect)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help -f --format)"{-f=,--format=}"[Format the output using the given Go template]:template: " \
|
||||
"($help -)*:secret:__docker_complete_secrets" && ret=0
|
||||
;;
|
||||
(ls|list)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help -q --quiet)"{-q,--quiet}"[Only display IDs]" && ret=0
|
||||
;;
|
||||
(rm|remove)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help -)*:secret:__docker_complete_secrets" && ret=0
|
||||
;;
|
||||
(help)
|
||||
_arguments $(__docker_arguments) ":subcommand:__docker_secret_commands" && ret=0
|
||||
;;
|
||||
esac
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
# EO secret
|
||||
|
||||
# BO service
|
||||
|
||||
__docker_service_complete_ls_filters() {
|
||||
|
@ -1666,6 +1769,7 @@ __docker_service_subcommand() {
|
|||
"($help)--restart-delay=[Delay between restart attempts]:delay: "
|
||||
"($help)--restart-max-attempts=[Maximum number of restarts before giving up]:max-attempts: "
|
||||
"($help)--restart-window=[Window used to evaluate the restart policy]:window: "
|
||||
"($help)*--secret=[Specify secrets to expose to the service]:secret:__docker_complete_secrets"
|
||||
"($help)--stop-grace-period=[Time to wait before force killing a container]:grace period: "
|
||||
"($help -t --tty)"{-t,--tty}"[Allocate a pseudo-TTY]"
|
||||
"($help)--update-delay=[Delay between updates]:delay: "
|
||||
|
@ -1684,10 +1788,14 @@ __docker_service_subcommand() {
|
|||
$opts_help \
|
||||
$opts_create_update \
|
||||
"($help)*--container-label=[Container labels]:label: " \
|
||||
"($help)*--dns=[Set custom DNS servers]:DNS: " \
|
||||
"($help)*--dns-option=[Set DNS options]:DNS option: " \
|
||||
"($help)*--dns-search=[Set custom DNS search domains]:DNS search: " \
|
||||
"($help)*--env-file=[Read environment variables from a file]:environment file:_files" \
|
||||
"($help)--hostname=[Service containers hostname]:hostname: " \
|
||||
"($help)--mode=[Service Mode]:mode:(global replicated)" \
|
||||
"($help)--name=[Service name]:name: " \
|
||||
"($help)*--port=[Publish a port]:port: " \
|
||||
"($help -): :__docker_complete_images" \
|
||||
"($help -):command: _command_names -e" \
|
||||
"($help -)*::arguments: _normal" && ret=0
|
||||
|
@ -1750,10 +1858,18 @@ __docker_service_subcommand() {
|
|||
"($help)--arg=[Service command args]:arguments: _normal" \
|
||||
"($help)*--container-label-add=[Add or update container labels]:label: " \
|
||||
"($help)*--container-label-rm=[Remove a container label by its key]:label: " \
|
||||
"($help)*--dns-add=[Add or update custom DNS servers]:DNS: " \
|
||||
"($help)*--dns-rm=[Remove custom DNS servers]:DNS: " \
|
||||
"($help)*--dns-option-add=[Add or update DNS options]:DNS option: " \
|
||||
"($help)*--dns-option-rm=[Remove DNS options]:DNS option: " \
|
||||
"($help)*--dns-search-add=[Add or update custom DNS search domains]:DNS search: " \
|
||||
"($help)*--dns-search-rm=[Remove DNS search domains]:DNS search: " \
|
||||
"($help)--force[Force update]" \
|
||||
"($help)*--group-add=[Add additional supplementary user groups to the container]:group:_groups" \
|
||||
"($help)*--group-rm=[Remove previously added supplementary user groups from the container]:group:_groups" \
|
||||
"($help)--image=[Service image tag]:image:__docker_complete_repositories" \
|
||||
"($help)*--port-add=[Add or update a port]:port: " \
|
||||
"($help)*--port-rm=[Remove a port(target-port mandatory)]:port: " \
|
||||
"($help)--rollback[Rollback to previous specification]" \
|
||||
"($help -)1:service:__docker_complete_services" && ret=0
|
||||
;;
|
||||
|
@ -2298,6 +2414,23 @@ __docker_subcommand() {
|
|||
;;
|
||||
esac
|
||||
;;
|
||||
(secret)
|
||||
local curcontext="$curcontext" state
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help -): :->command" \
|
||||
"($help -)*:: :->option-or-argument" && ret=0
|
||||
|
||||
case $state in
|
||||
(command)
|
||||
__docker_secret_commands && ret=0
|
||||
;;
|
||||
(option-or-argument)
|
||||
curcontext=${curcontext%:*:*}:docker-${words[-1]}:
|
||||
__docker_secret_subcommand && ret=0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
(service)
|
||||
local curcontext="$curcontext" state
|
||||
_arguments $(__docker_arguments) \
|
||||
|
|
|
@ -9,6 +9,13 @@ import (
|
|||
|
||||
// GetSecret returns a secret from a managed swarm cluster
|
||||
func (c *Cluster) GetSecret(id string) (types.Secret, error) {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
if !c.isActiveManager() {
|
||||
return types.Secret{}, c.errNoManager()
|
||||
}
|
||||
|
||||
ctx, cancel := c.getRequestContext()
|
||||
defer cancel()
|
||||
|
||||
|
|
|
@ -91,9 +91,9 @@ func (daemon *Daemon) load(id string) (*container.Container, error) {
|
|||
func (daemon *Daemon) Register(c *container.Container) error {
|
||||
// Attach to stdout and stderr
|
||||
if c.Config.OpenStdin {
|
||||
c.NewInputPipes()
|
||||
c.StreamConfig.NewInputPipes()
|
||||
} else {
|
||||
c.NewNopInputPipe()
|
||||
c.StreamConfig.NewNopInputPipe()
|
||||
}
|
||||
|
||||
daemon.containers.Add(c.ID, c)
|
||||
|
|
|
@ -195,9 +195,9 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R
|
|||
}
|
||||
|
||||
if ec.OpenStdin {
|
||||
ec.NewInputPipes()
|
||||
ec.StreamConfig.NewInputPipes()
|
||||
} else {
|
||||
ec.NewNopInputPipe()
|
||||
ec.StreamConfig.NewNopInputPipe()
|
||||
}
|
||||
|
||||
p := libcontainerd.Process{
|
||||
|
|
|
@ -5,9 +5,9 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/container/stream"
|
||||
"github.com/docker/docker/libcontainerd"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/runconfig"
|
||||
)
|
||||
|
||||
// Config holds the configurations for execs. The Daemon keeps
|
||||
|
@ -15,30 +15,30 @@ import (
|
|||
// examined both during and after completion.
|
||||
type Config struct {
|
||||
sync.Mutex
|
||||
*runconfig.StreamConfig
|
||||
ID string
|
||||
Running bool
|
||||
ExitCode *int
|
||||
OpenStdin bool
|
||||
OpenStderr bool
|
||||
OpenStdout bool
|
||||
CanRemove bool
|
||||
ContainerID string
|
||||
DetachKeys []byte
|
||||
Entrypoint string
|
||||
Args []string
|
||||
Tty bool
|
||||
Privileged bool
|
||||
User string
|
||||
Env []string
|
||||
Pid int
|
||||
StreamConfig *stream.Config
|
||||
ID string
|
||||
Running bool
|
||||
ExitCode *int
|
||||
OpenStdin bool
|
||||
OpenStderr bool
|
||||
OpenStdout bool
|
||||
CanRemove bool
|
||||
ContainerID string
|
||||
DetachKeys []byte
|
||||
Entrypoint string
|
||||
Args []string
|
||||
Tty bool
|
||||
Privileged bool
|
||||
User string
|
||||
Env []string
|
||||
Pid int
|
||||
}
|
||||
|
||||
// NewConfig initializes the a new exec configuration
|
||||
func NewConfig() *Config {
|
||||
return &Config{
|
||||
ID: stringid.GenerateNonCryptoID(),
|
||||
StreamConfig: runconfig.NewStreamConfig(),
|
||||
StreamConfig: stream.NewConfig(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ func NewConfig() *Config {
|
|||
func (c *Config) InitializeStdio(iop libcontainerd.IOPipe) error {
|
||||
c.StreamConfig.CopyToPipe(iop)
|
||||
|
||||
if c.Stdin() == nil && !c.Tty && runtime.GOOS == "windows" {
|
||||
if c.StreamConfig.Stdin() == nil && !c.Tty && runtime.GOOS == "windows" {
|
||||
if iop.Stdin != nil {
|
||||
if err := iop.Stdin.Close(); err != nil {
|
||||
logrus.Errorf("error closing exec stdin: %+v", err)
|
||||
|
@ -57,6 +57,11 @@ func (c *Config) InitializeStdio(iop libcontainerd.IOPipe) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// CloseStreams closes the stdio streams for the exec
|
||||
func (c *Config) CloseStreams() error {
|
||||
return c.StreamConfig.CloseStreams()
|
||||
}
|
||||
|
||||
// Store keeps track of the exec configurations.
|
||||
type Store struct {
|
||||
commands map[string]*Config
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
|
@ -135,63 +132,8 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
|||
Isolation: daemon.defaultIsolation,
|
||||
}
|
||||
|
||||
// TODO Windows. Refactor this more once sysinfo is refactored into
|
||||
// platform specific code. On Windows, sysinfo.cgroupMemInfo and
|
||||
// sysinfo.cgroupCpuInfo will be nil otherwise and cause a SIGSEGV if
|
||||
// an attempt is made to access through them.
|
||||
if runtime.GOOS != "windows" {
|
||||
v.MemoryLimit = sysInfo.MemoryLimit
|
||||
v.SwapLimit = sysInfo.SwapLimit
|
||||
v.KernelMemory = sysInfo.KernelMemory
|
||||
v.OomKillDisable = sysInfo.OomKillDisable
|
||||
v.CPUCfsPeriod = sysInfo.CPUCfsPeriod
|
||||
v.CPUCfsQuota = sysInfo.CPUCfsQuota
|
||||
v.CPUShares = sysInfo.CPUShares
|
||||
v.CPUSet = sysInfo.Cpuset
|
||||
v.Runtimes = daemon.configStore.GetAllRuntimes()
|
||||
v.DefaultRuntime = daemon.configStore.GetDefaultRuntimeName()
|
||||
v.InitBinary = daemon.configStore.GetInitPath()
|
||||
|
||||
v.ContainerdCommit.Expected = dockerversion.ContainerdCommitID
|
||||
if sv, err := daemon.containerd.GetServerVersion(context.Background()); err == nil {
|
||||
v.ContainerdCommit.ID = sv.Revision
|
||||
} else {
|
||||
logrus.Warnf("failed to retrieve containerd version: %v", err)
|
||||
v.ContainerdCommit.ID = "N/A"
|
||||
}
|
||||
|
||||
v.RuncCommit.Expected = dockerversion.RuncCommitID
|
||||
if rv, err := exec.Command(DefaultRuntimeBinary, "--version").Output(); err == nil {
|
||||
parts := strings.Split(strings.TrimSpace(string(rv)), "\n")
|
||||
if len(parts) == 3 {
|
||||
parts = strings.Split(parts[1], ": ")
|
||||
if len(parts) == 2 {
|
||||
v.RuncCommit.ID = strings.TrimSpace(parts[1])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logrus.Warnf("failed to retrieve %s version: %v", DefaultRuntimeBinary, err)
|
||||
v.RuncCommit.ID = "N/A"
|
||||
}
|
||||
if v.RuncCommit.ID == "" {
|
||||
logrus.Warnf("failed to retrieve %s version: unknown output format", DefaultRuntimeBinary)
|
||||
v.RuncCommit.ID = "N/A"
|
||||
}
|
||||
|
||||
v.InitCommit.Expected = dockerversion.InitCommitID
|
||||
if rv, err := exec.Command(DefaultInitBinary, "--version").Output(); err == nil {
|
||||
parts := strings.Split(string(rv), " ")
|
||||
if len(parts) == 3 {
|
||||
v.InitCommit.ID = strings.TrimSpace(parts[2])
|
||||
} else {
|
||||
logrus.Warnf("failed to retrieve %s version: unknown output format", DefaultInitBinary)
|
||||
v.InitCommit.ID = "N/A"
|
||||
}
|
||||
} else {
|
||||
logrus.Warnf("failed to retrieve %s version", DefaultInitBinary)
|
||||
v.InitCommit.ID = "N/A"
|
||||
}
|
||||
}
|
||||
// Retrieve platform specific info
|
||||
daemon.FillPlatformInfo(v, sysInfo)
|
||||
|
||||
hostname := ""
|
||||
if hn, err := os.Hostname(); err != nil {
|
||||
|
|
81
daemon/info_unix.go
Normal file
81
daemon/info_unix.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
// +build !windows
|
||||
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/dockerversion"
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) FillPlatformInfo(v *types.InfoBase, sysInfo *sysinfo.SysInfo) {
|
||||
v.MemoryLimit = sysInfo.MemoryLimit
|
||||
v.SwapLimit = sysInfo.SwapLimit
|
||||
v.KernelMemory = sysInfo.KernelMemory
|
||||
v.OomKillDisable = sysInfo.OomKillDisable
|
||||
v.CPUCfsPeriod = sysInfo.CPUCfsPeriod
|
||||
v.CPUCfsQuota = sysInfo.CPUCfsQuota
|
||||
v.CPUShares = sysInfo.CPUShares
|
||||
v.CPUSet = sysInfo.Cpuset
|
||||
v.Runtimes = daemon.configStore.GetAllRuntimes()
|
||||
v.DefaultRuntime = daemon.configStore.GetDefaultRuntimeName()
|
||||
v.InitBinary = daemon.configStore.GetInitPath()
|
||||
|
||||
v.ContainerdCommit.Expected = dockerversion.ContainerdCommitID
|
||||
if sv, err := daemon.containerd.GetServerVersion(context.Background()); err == nil {
|
||||
v.ContainerdCommit.ID = sv.Revision
|
||||
} else {
|
||||
logrus.Warnf("failed to retrieve containerd version: %v", err)
|
||||
v.ContainerdCommit.ID = "N/A"
|
||||
}
|
||||
|
||||
v.RuncCommit.Expected = dockerversion.RuncCommitID
|
||||
if rv, err := exec.Command(DefaultRuntimeBinary, "--version").Output(); err == nil {
|
||||
parts := strings.Split(strings.TrimSpace(string(rv)), "\n")
|
||||
if len(parts) == 3 {
|
||||
parts = strings.Split(parts[1], ": ")
|
||||
if len(parts) == 2 {
|
||||
v.RuncCommit.ID = strings.TrimSpace(parts[1])
|
||||
}
|
||||
}
|
||||
|
||||
if v.RuncCommit.ID == "" {
|
||||
logrus.Warnf("failed to retrieve %s version: unknown output format: %s", DefaultRuntimeBinary, string(rv))
|
||||
v.RuncCommit.ID = "N/A"
|
||||
}
|
||||
} else {
|
||||
logrus.Warnf("failed to retrieve %s version: %v", DefaultRuntimeBinary, err)
|
||||
v.RuncCommit.ID = "N/A"
|
||||
}
|
||||
|
||||
v.InitCommit.Expected = dockerversion.InitCommitID
|
||||
if rv, err := exec.Command(DefaultInitBinary, "--version").Output(); err == nil {
|
||||
parts := strings.Split(strings.TrimSpace(string(rv)), " - ")
|
||||
if len(parts) == 2 {
|
||||
if dockerversion.InitCommitID[0] == 'v' {
|
||||
vs := strings.TrimPrefix(parts[0], "tini version ")
|
||||
v.InitCommit.ID = "v" + vs
|
||||
} else {
|
||||
// Get the sha1
|
||||
gitParts := strings.Split(parts[1], ".")
|
||||
if len(gitParts) == 2 && gitParts[0] == "git" {
|
||||
v.InitCommit.ID = gitParts[1]
|
||||
v.InitCommit.Expected = dockerversion.InitCommitID[0:len(gitParts[1])]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if v.InitCommit.ID == "" {
|
||||
logrus.Warnf("failed to retrieve %s version: unknown output format: %s", DefaultInitBinary, string(rv))
|
||||
v.InitCommit.ID = "N/A"
|
||||
}
|
||||
} else {
|
||||
logrus.Warnf("failed to retrieve %s version", DefaultInitBinary)
|
||||
v.InitCommit.ID = "N/A"
|
||||
}
|
||||
}
|
9
daemon/info_windows.go
Normal file
9
daemon/info_windows.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) FillPlatformInfo(v *types.InfoBase, sysInfo *sysinfo.SysInfo) {
|
||||
}
|
|
@ -39,7 +39,7 @@ func (daemon *Daemon) StateChanged(id string, e libcontainerd.StateInfo) error {
|
|||
}
|
||||
|
||||
c.Lock()
|
||||
c.Wait()
|
||||
c.StreamConfig.Wait()
|
||||
c.Reset(false)
|
||||
|
||||
restart, wait, err := c.RestartManager().ShouldRestart(e.ExitCode, false, time.Since(c.StartedAt))
|
||||
|
@ -88,7 +88,7 @@ func (daemon *Daemon) StateChanged(id string, e libcontainerd.StateInfo) error {
|
|||
defer execConfig.Unlock()
|
||||
execConfig.ExitCode = &ec
|
||||
execConfig.Running = false
|
||||
execConfig.Wait()
|
||||
execConfig.StreamConfig.Wait()
|
||||
if err := execConfig.CloseStreams(); err != nil {
|
||||
logrus.Errorf("%s: %s", c.ID, err)
|
||||
}
|
||||
|
|
|
@ -6,8 +6,11 @@ package dockerversion
|
|||
// Default build-time variable for library-import.
|
||||
// This file is overridden on build with build-time informations.
|
||||
const (
|
||||
GitCommit string = "library-import"
|
||||
Version string = "library-import"
|
||||
BuildTime string = "library-import"
|
||||
IAmStatic string = "library-import"
|
||||
GitCommit string = "library-import"
|
||||
Version string = "library-import"
|
||||
BuildTime string = "library-import"
|
||||
IAmStatic string = "library-import"
|
||||
ContainerdCommitID string = "library-import"
|
||||
RuncCommitID string = "library-import"
|
||||
InitCommitID string = "library-import"
|
||||
)
|
||||
|
|
|
@ -73,7 +73,7 @@ filesystem does not support `d_type`. For example, XFS does not support `d_type`
|
|||
if it is formatted with the `ftype=0` option.
|
||||
|
||||
Please also refer to [#27358](https://github.com/docker/docker/issues/27358) for
|
||||
futher information.
|
||||
further information.
|
||||
|
||||
### Three argument form in `docker import`
|
||||
**Deprecated In Release: [v0.6.7](https://github.com/docker/docker/releases/tag/v0.6.7)**
|
||||
|
|
|
@ -4113,9 +4113,9 @@ an empty value or the default cluster-wide value.
|
|||
|
||||
JSON Parameters:
|
||||
|
||||
- **Annotations** – Optional medata to associate with the service.
|
||||
- **Name** – User-defined name for the service.
|
||||
- **Labels** – A map of labels to associate with the service (e.g.,
|
||||
- **Annotations** – Optional medata to associate with the node.
|
||||
- **Name** – User-defined name for the node.
|
||||
- **Labels** – A map of labels to associate with the node (e.g.,
|
||||
`{"key":"value", "key2":"value2"}`).
|
||||
- **Role** - Role of the node (worker/manager).
|
||||
- **Availability** - Availability of the node (active/pause/drain).
|
||||
|
|
|
@ -1686,7 +1686,7 @@ Delete stopped containers
|
|||
|
||||
**Example request, with digest information**:
|
||||
|
||||
GET /v1.25/v1.25/images/json?digests=1 HTTP/1.1
|
||||
GET /v1.25/images/json?digests=1 HTTP/1.1
|
||||
|
||||
**Example response, with digest information**:
|
||||
|
||||
|
@ -1743,7 +1743,7 @@ Build an image from a Dockerfile
|
|||
|
||||
**Example request**:
|
||||
|
||||
POST /v1.25/v1.25/build HTTP/1.1
|
||||
POST /v1.25/build HTTP/1.1
|
||||
|
||||
{% raw %}
|
||||
{{ TAR STREAM }}
|
||||
|
@ -4713,9 +4713,9 @@ an empty value or the default cluster-wide value.
|
|||
|
||||
JSON Parameters:
|
||||
|
||||
- **Annotations** – Optional medata to associate with the service.
|
||||
- **Name** – User-defined name for the service.
|
||||
- **Labels** – A map of labels to associate with the service (e.g.,
|
||||
- **Annotations** – Optional medata to associate with the node.
|
||||
- **Name** – User-defined name for the node.
|
||||
- **Labels** – A map of labels to associate with the node (e.g.,
|
||||
`{"key":"value", "key2":"value2"}`).
|
||||
- **Role** - Role of the node (worker/manager).
|
||||
- **Availability** - Availability of the node (active/pause/drain).
|
||||
|
@ -6060,9 +6060,9 @@ Create a secret
|
|||
|
||||
### Inspect a secret
|
||||
|
||||
`GET /secrets/(secret id)`
|
||||
`GET /secrets/(id)`
|
||||
|
||||
Get details on a secret
|
||||
Get details on the secret `id`
|
||||
|
||||
**Example request**:
|
||||
|
||||
|
@ -6088,6 +6088,7 @@ Get details on a secret
|
|||
|
||||
- **200** – no error
|
||||
- **404** – unknown secret
|
||||
- **406** – node is not part of a swarm
|
||||
- **500** – server error
|
||||
|
||||
### Remove a secret
|
||||
|
|
|
@ -14,7 +14,7 @@ advisory: "experimental"
|
|||
will be rejected.
|
||||
-->
|
||||
|
||||
# stack deploy (experimental)
|
||||
# deploy (alias for stack deploy) (experimental)
|
||||
|
||||
```markdown
|
||||
Usage: docker deploy [OPTIONS] STACK
|
||||
|
@ -58,5 +58,7 @@ axqh55ipl40h vossibility-stack_vossibility-collector replicated 1/1
|
|||
|
||||
* [stack config](stack_config.md)
|
||||
* [stack deploy](stack_deploy.md)
|
||||
* [stack ls](stack_ls.md)
|
||||
* [stack ps](stack_ps.md)
|
||||
* [stack rm](stack_rm.md)
|
||||
* [stack tasks](stack_tasks.md)
|
||||
* [stack services](stack_services.md)
|
||||
|
|
|
@ -62,7 +62,7 @@ Options:
|
|||
--iptables Enable addition of iptables rules (default true)
|
||||
--ipv6 Enable IPv6 networking
|
||||
--label value Set key=value labels to the daemon (default [])
|
||||
--live-restore Enable live restore of docker when containers are still running
|
||||
--live-restore Enable live restore of docker when containers are still running (Linux only)
|
||||
--log-driver string Default driver for container logs (default "json-file")
|
||||
-l, --log-level string Set the logging level ("debug", "info", "warn", "error", "fatal") (default "info")
|
||||
--log-opt value Default log driver options for containers (default map[])
|
||||
|
@ -1234,7 +1234,6 @@ This is a full example of the allowed configuration options on Windows:
|
|||
"storage-driver": "",
|
||||
"storage-opts": [],
|
||||
"labels": [],
|
||||
"live-restore": true,
|
||||
"log-driver": "",
|
||||
"mtu": 0,
|
||||
"pidfile": "",
|
||||
|
|
|
@ -49,10 +49,11 @@ The plugin can subsequently be enabled for local use or pushed to the public reg
|
|||
|
||||
## Related information
|
||||
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin disable](plugin_disable.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin inspect](plugin_inspect.md)
|
||||
* [plugin install](plugin_install.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin push](plugin_push.md)
|
||||
* [plugin rm](plugin_rm.md)
|
||||
* [plugin set](plugin_set.md)
|
||||
|
|
|
@ -53,10 +53,11 @@ tiborvass/no-remove latest A test plugin for Docker false
|
|||
|
||||
## Related information
|
||||
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin create](plugin_create.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin inspect](plugin_inspect.md)
|
||||
* [plugin install](plugin_install.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin push](plugin_push.md)
|
||||
* [plugin rm](plugin_rm.md)
|
||||
* [plugin set](plugin_set.md)
|
||||
|
|
|
@ -54,9 +54,10 @@ tiborvass/no-remove latest A test plugin for Docker true
|
|||
## Related information
|
||||
|
||||
* [plugin create](plugin_create.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin disable](plugin_disable.md)
|
||||
* [plugin inspect](plugin_inspect.md)
|
||||
* [plugin install](plugin_install.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin push](plugin_push.md)
|
||||
* [plugin rm](plugin_rm.md)
|
||||
* [plugin set](plugin_set.md)
|
||||
|
|
|
@ -154,9 +154,10 @@ $ docker plugin inspect -f '{{.Id}}' tiborvass/no-remove:latest
|
|||
## Related information
|
||||
|
||||
* [plugin create](plugin_create.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin disable](plugin_disable.md)
|
||||
* [plugin install](plugin_install.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin push](plugin_push.md)
|
||||
* [plugin rm](plugin_rm.md)
|
||||
* [plugin set](plugin_set.md)
|
||||
|
|
|
@ -60,9 +60,10 @@ tiborvass/no-remove latest A test plugin for Docker true
|
|||
## Related information
|
||||
|
||||
* [plugin create](plugin_create.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin disable](plugin_disable.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin inspect](plugin_inspect.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin push](plugin_push.md)
|
||||
* [plugin rm](plugin_rm.md)
|
||||
* [plugin set](plugin_set.md)
|
||||
|
|
|
@ -43,9 +43,10 @@ tiborvass/no-remove latest A test plugin for Docker true
|
|||
## Related information
|
||||
|
||||
* [plugin create](plugin_create.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin disable](plugin_disable.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin inspect](plugin_inspect.md)
|
||||
* [plugin install](plugin_install.md)
|
||||
* [plugin push](plugin_push.md)
|
||||
* [plugin rm](plugin_rm.md)
|
||||
* [plugin set](plugin_set.md)
|
||||
|
|
50
docs/reference/commandline/plugin_push.md
Normal file
50
docs/reference/commandline/plugin_push.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
title: "plugin push"
|
||||
description: "the plugin push command description and usage"
|
||||
keywords: "plugin, push"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/docker Github
|
||||
repository at https://github.com/docker/docker/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
```markdown
|
||||
Usage: docker plugin push NAME[:TAG]
|
||||
|
||||
Push a plugin to a registry
|
||||
|
||||
Options:
|
||||
--help Print usage
|
||||
```
|
||||
|
||||
Use `docker plugin create` to create the plugin. Once the plugin is ready for distribution,
|
||||
use `docker plugin push` to share your images to the Docker Hub registry or to a self-hosted one.
|
||||
|
||||
Registry credentials are managed by [docker login](login.md).
|
||||
|
||||
The following example shows how to push a sample `user/plugin`.
|
||||
|
||||
```bash
|
||||
|
||||
$ docker plugin ls
|
||||
NAME TAG DESCRIPTION ENABLED
|
||||
user/plugin latest A sample plugin for Docker false
|
||||
|
||||
$ docker plugin push user/plugin
|
||||
```
|
||||
|
||||
## Related information
|
||||
|
||||
* [plugin create](plugin_create.md)
|
||||
* [plugin disable](plugin_disable.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin inspect](plugin_inspect.md)
|
||||
* [plugin install](plugin_install.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin rm](plugin_rm.md)
|
||||
* [plugin set](plugin_set.md)
|
|
@ -46,9 +46,10 @@ tiborvass/no-remove
|
|||
## Related information
|
||||
|
||||
* [plugin create](plugin_create.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin disable](plugin_disable.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin inspect](plugin_inspect.md)
|
||||
* [plugin install](plugin_install.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin push](plugin_push.md)
|
||||
* [plugin set](plugin_set.md)
|
||||
|
|
|
@ -90,9 +90,10 @@ $ docker plugin inspect -f '{{.Settings.Args}}' myplugin
|
|||
## Related information
|
||||
|
||||
* [plugin create](plugin_create.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin disable](plugin_disable.md)
|
||||
* [plugin enable](plugin_enable.md)
|
||||
* [plugin inspect](plugin_inspect.md)
|
||||
* [plugin install](plugin_install.md)
|
||||
* [plugin ls](plugin_ls.md)
|
||||
* [plugin push](plugin_push.md)
|
||||
* [plugin rm](plugin_rm.md)
|
||||
|
|
|
@ -60,7 +60,8 @@ axqh55ipl40h vossibility-stack_vossibility-collector replicated 1/1 ice
|
|||
## Related information
|
||||
|
||||
* [stack config](stack_config.md)
|
||||
* [stack ls](stack_ls.md)
|
||||
* [stack ps](stack_ps.md)
|
||||
* [stack rm](stack_rm.md)
|
||||
* [stack services](stack_services.md)
|
||||
* [stack ps](stack_ps.md)
|
||||
* [stack ls](stack_ls.md)
|
||||
* [deploy](deploy.md)
|
|
@ -212,7 +212,7 @@ environment.
|
|||
|
||||
## service discovery
|
||||
|
||||
Swarm mode [service discovery](https://docs.docker.com/engine/swarm/networking/) is a DNS component
|
||||
Swarm mode [service discovery](https://docs.docker.com/engine/swarm/networking/#use-swarm-mode-service-discovery) is a DNS component
|
||||
internal to the swarm that automatically assigns each service on an overlay
|
||||
network in the swarm a VIP and DNS entry. Containers on the network share DNS
|
||||
mappings for the service via gossip so any container on the network can access
|
||||
|
@ -226,7 +226,7 @@ automatically distributes requests to the service VIP among the active tasks.
|
|||
|
||||
A [swarm](https://docs.docker.com/engine/swarm/) is a cluster of one or more Docker Engines running in [swarm mode](#swarm-mode).
|
||||
|
||||
## Swarm
|
||||
## Docker Swarm
|
||||
|
||||
Do not confuse [Docker Swarm](https://github.com/docker/swarm) with the [swarm mode](#swarm-mode) features in Docker Engine.
|
||||
|
||||
|
|
|
@ -1238,10 +1238,6 @@ since Docker 1.12. In Docker 1.10 and 1.11 this did not happen and it may be nec
|
|||
to use a custom seccomp profile or use `--security-opt seccomp=unconfined` when adding
|
||||
capabilities.
|
||||
|
||||
It is only possible to grant capabilities to a container running as a user other than `root`
|
||||
on a system with a Linux kernel version of 4.3 or later, as this requires "ambient capabilities"
|
||||
to be granted. These will be added if the kernel allows it from Docker version 1.13.
|
||||
|
||||
## Logging drivers (--log-driver)
|
||||
|
||||
The container can have a different logging driver than the Docker daemon. Use
|
||||
|
|
|
@ -17,6 +17,20 @@ const (
|
|||
Version string = "$VERSION"
|
||||
BuildTime string = "$BUILDTIME"
|
||||
IAmStatic string = "${IAMSTATIC:-true}"
|
||||
)
|
||||
|
||||
// AUTOGENERATED FILE; see /go/src/github.com/docker/docker/hack/make/.go-autogen
|
||||
DVEOF
|
||||
|
||||
cat > dockerversion/version_autogen_unix.go <<DVEOF
|
||||
// +build autogen,!windows
|
||||
|
||||
// Package dockerversion is auto-generated at build-time
|
||||
package dockerversion
|
||||
|
||||
// Default build-time variable for library-import.
|
||||
// This file is overridden on build with build-time informations.
|
||||
const (
|
||||
ContainerdCommitID string = "${CONTAINERD_COMMIT}"
|
||||
RuncCommitID string = "${RUNC_COMMIT}"
|
||||
InitCommitID string = "${TINI_COMMIT}"
|
||||
|
|
|
@ -41,6 +41,7 @@ func (s *DockerAuthzV2Suite) TearDownTest(c *check.C) {
|
|||
}
|
||||
|
||||
func (s *DockerAuthzV2Suite) TestAuthZPluginAllowNonVolumeRequest(c *check.C) {
|
||||
testRequires(c, IsAmd64)
|
||||
// Install authz plugin
|
||||
_, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", authzPluginNameWithTag)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
@ -70,6 +71,7 @@ func (s *DockerAuthzV2Suite) TestAuthZPluginAllowNonVolumeRequest(c *check.C) {
|
|||
}
|
||||
|
||||
func (s *DockerAuthzV2Suite) TestAuthZPluginRejectVolumeRequests(c *check.C) {
|
||||
testRequires(c, IsAmd64)
|
||||
// Install authz plugin
|
||||
_, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", authzPluginNameWithTag)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
|
|
@ -81,7 +81,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithPluginDisabled(c *check.C) {
|
|||
// TestDaemonKillLiveRestoreWithPlugins SIGKILLs daemon started with --live-restore.
|
||||
// Plugins should continue to run.
|
||||
func (s *DockerDaemonSuite) TestDaemonKillLiveRestoreWithPlugins(c *check.C) {
|
||||
testRequires(c, Network)
|
||||
testRequires(c, Network, IsAmd64)
|
||||
|
||||
if err := s.d.Start("--live-restore"); err != nil {
|
||||
c.Fatalf("Could not start daemon: %v", err)
|
||||
|
@ -114,7 +114,7 @@ func (s *DockerDaemonSuite) TestDaemonKillLiveRestoreWithPlugins(c *check.C) {
|
|||
// TestDaemonShutdownLiveRestoreWithPlugins SIGTERMs daemon started with --live-restore.
|
||||
// Plugins should continue to run.
|
||||
func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C) {
|
||||
testRequires(c, Network)
|
||||
testRequires(c, Network, IsAmd64)
|
||||
|
||||
if err := s.d.Start("--live-restore"); err != nil {
|
||||
c.Fatalf("Could not start daemon: %v", err)
|
||||
|
@ -185,7 +185,7 @@ func (s *DockerDaemonSuite) TestDaemonShutdownWithPlugins(c *check.C) {
|
|||
|
||||
// TestVolumePlugin tests volume creation using a plugin.
|
||||
func (s *DockerDaemonSuite) TestVolumePlugin(c *check.C) {
|
||||
testRequires(c, Network)
|
||||
testRequires(c, Network, IsAmd64)
|
||||
|
||||
volName := "plugin-volume"
|
||||
volRoot := "/data"
|
||||
|
|
|
@ -117,22 +117,28 @@ func (s *DockerSuite) TestLogsTail(c *check.C) {
|
|||
id := strings.TrimSpace(out)
|
||||
dockerCmd(c, "wait", id)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", "--tail", "5", id)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", "--tail", "0", id)
|
||||
lines := strings.Split(out, "\n")
|
||||
c.Assert(lines, checker.HasLen, 1)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", "--tail", "5", id)
|
||||
lines = strings.Split(out, "\n")
|
||||
c.Assert(lines, checker.HasLen, 6)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", "--tail", "all", id)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", "--tail", "99", id)
|
||||
lines = strings.Split(out, "\n")
|
||||
c.Assert(lines, checker.HasLen, 100)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", "--tail", "all", id)
|
||||
lines = strings.Split(out, "\n")
|
||||
c.Assert(lines, checker.HasLen, testLen+1)
|
||||
|
||||
out, _ = dockerCmd(c, "logs", "--tail", "-1", id)
|
||||
lines = strings.Split(out, "\n")
|
||||
c.Assert(lines, checker.HasLen, testLen+1)
|
||||
|
||||
out, _, _ = dockerCmdWithStdoutStderr(c, "logs", "--tail", "random", id)
|
||||
|
||||
lines = strings.Split(out, "\n")
|
||||
|
||||
c.Assert(lines, checker.HasLen, testLen+1)
|
||||
}
|
||||
|
||||
|
|
|
@ -769,7 +769,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkDriverOptions(c *check.C) {
|
|||
}
|
||||
|
||||
func (s *DockerNetworkSuite) TestDockerPluginV2NetworkDriver(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux, Network)
|
||||
testRequires(c, DaemonIsLinux, Network, IsAmd64)
|
||||
|
||||
var (
|
||||
npName = "mavenugo/test-docker-netplugin"
|
||||
|
|
|
@ -60,7 +60,7 @@ func (s *DockerSuite) TestPluginForceRemove(c *check.C) {
|
|||
}
|
||||
|
||||
func (s *DockerSuite) TestPluginActive(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux, Network)
|
||||
testRequires(c, DaemonIsLinux, Network, IsAmd64)
|
||||
out, _, err := dockerCmdWithError("plugin", "install", "--grant-all-permissions", pNameWithTag)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
|
|
256
man/dockerd.8.md
256
man/dockerd.8.md
|
@ -71,13 +71,13 @@ dockerd - Enable daemon mode
|
|||
[**--userns-remap**[=*default*]]
|
||||
|
||||
# DESCRIPTION
|
||||
**dockerd** is used for starting the Docker daemon(i.e., to command the daemon to manage images,
|
||||
containers etc.) So **dockerd** is a server, as a daemon.
|
||||
**dockerd** is used for starting the Docker daemon (i.e., to command the daemon
|
||||
to manage images, containers etc). So **dockerd** is a server, as a daemon.
|
||||
|
||||
To run the Docker daemon you can specify **dockerd**.
|
||||
You can check the daemon options using **dockerd --help**.
|
||||
Daemon options should be specified after the **dockerd** keyword in the following
|
||||
format.
|
||||
Daemon options should be specified after the **dockerd** keyword in the
|
||||
following format.
|
||||
|
||||
**dockerd [OPTIONS]**
|
||||
|
||||
|
@ -87,27 +87,31 @@ format.
|
|||
Set additional OCI compatible runtime.
|
||||
|
||||
**--api-cors-header**=""
|
||||
Set CORS headers in the remote API. Default is cors disabled. Give urls like "http://foo, http://bar, ...". Give "*" to allow all.
|
||||
Set CORS headers in the remote API. Default is cors disabled. Give urls like
|
||||
"http://foo, http://bar, ...". Give "*" to allow all.
|
||||
|
||||
**--authorization-plugin**=""
|
||||
Set authorization plugins to load
|
||||
|
||||
**-b**, **--bridge**=""
|
||||
Attach containers to a pre\-existing network bridge; use 'none' to disable container networking
|
||||
Attach containers to a pre\-existing network bridge; use 'none' to disable
|
||||
container networking
|
||||
|
||||
**--bip**=""
|
||||
Use the provided CIDR notation address for the dynamically created bridge (docker0); Mutually exclusive of \-b
|
||||
Use the provided CIDR notation address for the dynamically created bridge
|
||||
(docker0); Mutually exclusive of \-b
|
||||
|
||||
**--cgroup-parent**=""
|
||||
Set parent cgroup for all containers. Default is "/docker" for fs cgroup driver and "system.slice" for systemd cgroup driver.
|
||||
Set parent cgroup for all containers. Default is "/docker" for fs cgroup
|
||||
driver and "system.slice" for systemd cgroup driver.
|
||||
|
||||
**--cluster-store**=""
|
||||
URL of the distributed storage backend
|
||||
|
||||
**--cluster-advertise**=""
|
||||
Specifies the 'host:port' or `interface:port` combination that this particular
|
||||
daemon instance should use when advertising itself to the cluster. The daemon
|
||||
is reached through this value.
|
||||
Specifies the 'host:port' or `interface:port` combination that this
|
||||
particular daemon instance should use when advertising itself to the cluster.
|
||||
The daemon is reached through this value.
|
||||
|
||||
**--cluster-store-opt**=""
|
||||
Specifies options for the Key/Value store.
|
||||
|
@ -122,7 +126,8 @@ format.
|
|||
Enable debug mode. Default is false.
|
||||
|
||||
**--default-gateway**=""
|
||||
IPv4 address of the container default gateway; this address must be part of the bridge subnet (which is defined by \-b or \--bip)
|
||||
IPv4 address of the container default gateway; this address must be part of
|
||||
the bridge subnet (which is defined by \-b or \--bip)
|
||||
|
||||
**--default-gateway-v6**=""
|
||||
IPv6 address of the container default gateway
|
||||
|
@ -146,13 +151,15 @@ format.
|
|||
Set runtime execution options. See RUNTIME EXECUTION OPTIONS.
|
||||
|
||||
**--exec-root**=""
|
||||
Path to use as the root of the Docker execution state files. Default is `/var/run/docker`.
|
||||
Path to use as the root of the Docker execution state files. Default is
|
||||
`/var/run/docker`.
|
||||
|
||||
**--experimental**=""
|
||||
Enable the daemon experimental features.
|
||||
|
||||
**--fixed-cidr**=""
|
||||
IPv4 subnet for fixed IPs (e.g., 10.20.0.0/16); this subnet must be nested in the bridge subnet (which is defined by \-b or \-\-bip)
|
||||
IPv4 subnet for fixed IPs (e.g., 10.20.0.0/16); this subnet must be nested in
|
||||
the bridge subnet (which is defined by \-b or \-\-bip).
|
||||
|
||||
**--fixed-cidr-v6**=""
|
||||
IPv6 subnet for global IPv6 addresses (e.g., 2a00:1450::/64)
|
||||
|
@ -173,28 +180,46 @@ unix://[/path/to/socket] to use.
|
|||
Print usage statement
|
||||
|
||||
**--icc**=*true*|*false*
|
||||
Allow unrestricted inter\-container and Docker daemon host communication. If disabled, containers can still be linked together using the **--link** option (see **docker-run(1)**). Default is true.
|
||||
Allow unrestricted inter\-container and Docker daemon host communication. If
|
||||
disabled, containers can still be linked together using the **--link** option
|
||||
(see **docker-run(1)**). Default is true.
|
||||
|
||||
**--init**
|
||||
Run an init process inside containers for signal forwarding and process reaping.
|
||||
Run an init process inside containers for signal forwarding and process
|
||||
reaping.
|
||||
|
||||
**--init-path**
|
||||
Path to the docker-init binary.
|
||||
Path to the docker-init binary.
|
||||
|
||||
**--insecure-registry**=[]
|
||||
Enable insecure registry communication, i.e., enable un-encrypted and/or untrusted communication.
|
||||
Enable insecure registry communication, i.e., enable un-encrypted and/or
|
||||
untrusted communication.
|
||||
|
||||
List of insecure registries can contain an element with CIDR notation to specify a whole subnet. Insecure registries accept HTTP and/or accept HTTPS with certificates from unknown CAs.
|
||||
List of insecure registries can contain an element with CIDR notation to
|
||||
specify a whole subnet. Insecure registries accept HTTP and/or accept HTTPS
|
||||
with certificates from unknown CAs.
|
||||
|
||||
Enabling `--insecure-registry` is useful when running a local registry. However, because its use creates security vulnerabilities it should ONLY be enabled for testing purposes. For increased security, users should add their CA to their system's list of trusted CAs instead of using `--insecure-registry`.
|
||||
Enabling `--insecure-registry` is useful when running a local registry.
|
||||
However, because its use creates security vulnerabilities it should ONLY be
|
||||
enabled for testing purposes. For increased security, users should add their
|
||||
CA to their system's list of trusted CAs instead of using
|
||||
`--insecure-registry`.
|
||||
|
||||
**--ip**=""
|
||||
Default IP address to use when binding container ports. Default is `0.0.0.0`.
|
||||
|
||||
**--ip-forward**=*true*|*false*
|
||||
Enables IP forwarding on the Docker host. The default is `true`. This flag interacts with the IP forwarding setting on your host system's kernel. If your system has IP forwarding disabled, this setting enables it. If your system has IP forwarding enabled, setting this flag to `--ip-forward=false` has no effect.
|
||||
Enables IP forwarding on the Docker host. The default is `true`. This flag
|
||||
interacts with the IP forwarding setting on your host system's kernel. If
|
||||
your system has IP forwarding disabled, this setting enables it. If your
|
||||
system has IP forwarding enabled, setting this flag to `--ip-forward=false`
|
||||
has no effect.
|
||||
|
||||
This setting will also enable IPv6 forwarding if you have both `--ip-forward=true` and `--fixed-cidr-v6` set. Note that this may reject Router Advertisements and interfere with the host's existing IPv6 configuration. For more information, please consult the documentation about "Advanced Networking - IPv6".
|
||||
This setting will also enable IPv6 forwarding if you have both
|
||||
`--ip-forward=true` and `--fixed-cidr-v6` set. Note that this may reject
|
||||
Router Advertisements and interfere with the host's existing IPv6
|
||||
configuration. For more information, please consult the documentation about
|
||||
"Advanced Networking - IPv6".
|
||||
|
||||
**--ip-masq**=*true*|*false*
|
||||
Enable IP masquerading for bridge's IP range. Default is true.
|
||||
|
@ -203,12 +228,18 @@ Path to the docker-init binary.
|
|||
Enable Docker's addition of iptables rules. Default is true.
|
||||
|
||||
**--ipv6**=*true*|*false*
|
||||
Enable IPv6 support. Default is false. Docker will create an IPv6-enabled bridge with address fe80::1 which will allow you to create IPv6-enabled containers. Use together with `--fixed-cidr-v6` to provide globally routable IPv6 addresses. IPv6 forwarding will be enabled if not used with `--ip-forward=false`. This may collide with your host's current IPv6 settings. For more information please consult the documentation about "Advanced Networking - IPv6".
|
||||
Enable IPv6 support. Default is false. Docker will create an IPv6-enabled
|
||||
bridge with address fe80::1 which will allow you to create IPv6-enabled
|
||||
containers. Use together with `--fixed-cidr-v6` to provide globally routable
|
||||
IPv6 addresses. IPv6 forwarding will be enabled if not used with
|
||||
`--ip-forward=false`. This may collide with your host's current IPv6
|
||||
settings. For more information please consult the documentation about
|
||||
"Advanced Networking - IPv6".
|
||||
|
||||
**--isolation**="*default*"
|
||||
Isolation specifies the type of isolation technology used by containers. Note
|
||||
that the default on Windows server is `process`, and the default on Windows client
|
||||
is `hyperv`. Linux only supports `default`.
|
||||
Isolation specifies the type of isolation technology used by containers.
|
||||
Note that the default on Windows server is `process`, and the default on
|
||||
Windows client is `hyperv`. Linux only supports `default`.
|
||||
|
||||
**-l**, **--log-level**="*debug*|*info*|*warn*|*error*|*fatal*"
|
||||
Set the logging level. Default is `info`.
|
||||
|
@ -217,7 +248,9 @@ is `hyperv`. Linux only supports `default`.
|
|||
Set key=value labels to the daemon (displayed in `docker info`)
|
||||
|
||||
**--live-restore**=*false*
|
||||
Enable live restore of running containers when the daemon starts so that they are not restarted.
|
||||
Enable live restore of running containers when the daemon starts so that they
|
||||
are not restarted. This option is applicable only for docker daemon running
|
||||
on Linux host.
|
||||
|
||||
**--log-driver**="*json-file*|*syslog*|*journald*|*gelf*|*fluentd*|*awslogs*|*splunk*|*etwlogs*|*gcplogs*|*none*"
|
||||
Default driver for container logs. Default is `json-file`.
|
||||
|
@ -239,12 +272,13 @@ is `hyperv`. Linux only supports `default`.
|
|||
Path to use for daemon PID file. Default is `/var/run/docker.pid`
|
||||
|
||||
**--raw-logs**
|
||||
Output daemon logs in full timestamp format without ANSI coloring. If this flag is not set,
|
||||
the daemon outputs condensed, colorized logs if a terminal is detected, or full ("raw")
|
||||
output otherwise.
|
||||
Output daemon logs in full timestamp format without ANSI coloring. If this
|
||||
flag is not set, the daemon outputs condensed, colorized logs if a terminal
|
||||
is detected, or full ("raw") output otherwise.
|
||||
|
||||
**--registry-mirror**=*<scheme>://<host>*
|
||||
Prepend a registry mirror to be used for image pulls. May be specified multiple times.
|
||||
Prepend a registry mirror to be used for image pulls. May be specified
|
||||
multiple times.
|
||||
|
||||
**-s**, **--storage-driver**=""
|
||||
Force the Docker runtime to use a specific storage driver.
|
||||
|
@ -262,9 +296,10 @@ output otherwise.
|
|||
Set storage driver options. See STORAGE DRIVER OPTIONS.
|
||||
|
||||
**--swarm-default-advertise-addr**=*IP|INTERFACE*
|
||||
Set default address or interface for swarm to advertise as its externally-reachable address to other cluster
|
||||
members. This can be a hostname, an IP address, or an interface such as `eth0`. A port cannot be specified with
|
||||
this option.
|
||||
Set default address or interface for swarm to advertise as its
|
||||
externally-reachable address to other cluster members. This can be a
|
||||
hostname, an IP address, or an interface such as `eth0`. A port cannot be
|
||||
specified with this option.
|
||||
|
||||
**--tls**=*true*|*false*
|
||||
Use TLS; implied by --tlsverify. Default is false.
|
||||
|
@ -283,13 +318,19 @@ output otherwise.
|
|||
Default is false.
|
||||
|
||||
**--userland-proxy**=*true*|*false*
|
||||
Rely on a userland proxy implementation for inter-container and outside-to-container loopback communications. Default is true.
|
||||
Rely on a userland proxy implementation for inter-container and
|
||||
outside-to-container loopback communications. Default is true.
|
||||
|
||||
**--userland-proxy-path**=""
|
||||
Path to the userland proxy binary.
|
||||
|
||||
**--userns-remap**=*default*|*uid:gid*|*user:group*|*user*|*uid*
|
||||
Enable user namespaces for containers on the daemon. Specifying "default" will cause a new user and group to be created to handle UID and GID range remapping for the user namespace mappings used for contained processes. Specifying a user (or uid) and optionally a group (or gid) will cause the daemon to lookup the user and group's subordinate ID ranges for use as the user namespace mappings for contained processes.
|
||||
Enable user namespaces for containers on the daemon. Specifying "default"
|
||||
will cause a new user and group to be created to handle UID and GID range
|
||||
remapping for the user namespace mappings used for contained processes.
|
||||
Specifying a user (or uid) and optionally a group (or gid) will cause the
|
||||
daemon to lookup the user and group's subordinate ID ranges for use as the
|
||||
user namespace mappings for contained processes.
|
||||
|
||||
# STORAGE DRIVER OPTIONS
|
||||
|
||||
|
@ -402,8 +443,8 @@ exits.
|
|||
For example, when a container exits, its associated thin device is removed. If
|
||||
that device has leaked into some other mount namespace and can't be removed,
|
||||
the container exit still succeeds and this option causes the system to schedule
|
||||
the device for deferred removal. It does not wait in a loop trying to remove a busy
|
||||
device.
|
||||
the device for deferred removal. It does not wait in a loop trying to remove a
|
||||
busy device.
|
||||
|
||||
Example use: `dockerd --storage-opt dm.use_deferred_removal=true`
|
||||
|
||||
|
@ -431,23 +472,23 @@ namespaces.
|
|||
|
||||
#### dm.loopdatasize
|
||||
|
||||
**Note**: This option configures devicemapper loopback, which should not be used in production.
|
||||
**Note**: This option configures devicemapper loopback, which should not be
|
||||
used in production.
|
||||
|
||||
Specifies the size to use when creating the loopback file for the
|
||||
"data" device which is used for the thin pool. The default size is
|
||||
100G. The file is sparse, so it will not initially take up
|
||||
this much space.
|
||||
Specifies the size to use when creating the loopback file for the "data" device
|
||||
which is used for the thin pool. The default size is 100G. The file is sparse,
|
||||
so it will not initially take up this much space.
|
||||
|
||||
Example use: `dockerd --storage-opt dm.loopdatasize=200G`
|
||||
|
||||
#### dm.loopmetadatasize
|
||||
|
||||
**Note**: This option configures devicemapper loopback, which should not be used in production.
|
||||
**Note**: This option configures devicemapper loopback, which should not be
|
||||
used in production.
|
||||
|
||||
Specifies the size to use when creating the loopback file for the
|
||||
"metadata" device which is used for the thin pool. The default size
|
||||
is 2G. The file is sparse, so it will not initially take up
|
||||
this much space.
|
||||
Specifies the size to use when creating the loopback file for the "metadata"
|
||||
device which is used for the thin pool. The default size is 2G. The file is
|
||||
sparse, so it will not initially take up this much space.
|
||||
|
||||
Example use: `dockerd --storage-opt dm.loopmetadatasize=4G`
|
||||
|
||||
|
@ -455,17 +496,16 @@ Example use: `dockerd --storage-opt dm.loopmetadatasize=4G`
|
|||
|
||||
(Deprecated, use `dm.thinpooldev`)
|
||||
|
||||
Specifies a custom blockdevice to use for data for a
|
||||
Docker-managed thin pool. It is better to use `dm.thinpooldev` - see
|
||||
the documentation for it above for discussion of the advantages.
|
||||
Specifies a custom blockdevice to use for data for a Docker-managed thin pool.
|
||||
It is better to use `dm.thinpooldev` - see the documentation for it above for
|
||||
discussion of the advantages.
|
||||
|
||||
#### dm.metadatadev
|
||||
|
||||
(Deprecated, use `dm.thinpooldev`)
|
||||
|
||||
Specifies a custom blockdevice to use for metadata for a
|
||||
Docker-managed thin pool. See `dm.datadev` for why this is
|
||||
deprecated.
|
||||
Specifies a custom blockdevice to use for metadata for a Docker-managed thin
|
||||
pool. See `dm.datadev` for why this is deprecated.
|
||||
|
||||
#### dm.blocksize
|
||||
|
||||
|
@ -476,24 +516,22 @@ Example use: `dockerd --storage-opt dm.blocksize=512K`
|
|||
|
||||
#### dm.blkdiscard
|
||||
|
||||
Enables or disables the use of `blkdiscard` when removing devicemapper
|
||||
devices. This is disabled by default due to the additional latency,
|
||||
but as a special case with loopback devices it will be enabled, in
|
||||
order to re-sparsify the loopback file on image/container removal.
|
||||
Enables or disables the use of `blkdiscard` when removing devicemapper devices.
|
||||
This is disabled by default due to the additional latency, but as a special
|
||||
case with loopback devices it will be enabled, in order to re-sparsify the
|
||||
loopback file on image/container removal.
|
||||
|
||||
Disabling this on loopback can lead to *much* faster container removal
|
||||
times, but it also prevents the space used in `/var/lib/docker` directory
|
||||
from being returned to the system for other use when containers are
|
||||
removed.
|
||||
Disabling this on loopback can lead to *much* faster container removal times,
|
||||
but it also prevents the space used in `/var/lib/docker` directory from being
|
||||
returned to the system for other use when containers are removed.
|
||||
|
||||
Example use: `dockerd --storage-opt dm.blkdiscard=false`
|
||||
|
||||
#### dm.override_udev_sync_check
|
||||
|
||||
By default, the devicemapper backend attempts to synchronize with the
|
||||
`udev` device manager for the Linux kernel. This option allows
|
||||
disabling that synchronization, to continue even though the
|
||||
configuration may be buggy.
|
||||
By default, the devicemapper backend attempts to synchronize with the `udev`
|
||||
device manager for the Linux kernel. This option allows disabling that
|
||||
synchronization, to continue even though the configuration may be buggy.
|
||||
|
||||
To view the `udev` sync support of a Docker daemon that is using the
|
||||
`devicemapper` driver, run:
|
||||
|
@ -506,10 +544,9 @@ To view the `udev` sync support of a Docker daemon that is using the
|
|||
When `udev` sync support is `true`, then `devicemapper` and `udev` can
|
||||
coordinate the activation and deactivation of devices for containers.
|
||||
|
||||
When `udev` sync support is `false`, a race condition occurs between
|
||||
the `devicemapper` and `udev` during create and cleanup. The race
|
||||
condition results in errors and failures. (For information on these
|
||||
failures, see
|
||||
When `udev` sync support is `false`, a race condition occurs between the
|
||||
`devicemapper` and `udev` during create and cleanup. The race condition results
|
||||
in errors and failures. (For information on these failures, see
|
||||
[docker#4036](https://github.com/docker/docker/issues/4036))
|
||||
|
||||
To allow the `docker` daemon to start, regardless of whether `udev` sync is
|
||||
|
@ -517,15 +554,14 @@ To allow the `docker` daemon to start, regardless of whether `udev` sync is
|
|||
|
||||
$ dockerd --storage-opt dm.override_udev_sync_check=true
|
||||
|
||||
When this value is `true`, the driver continues and simply warns you
|
||||
the errors are happening.
|
||||
When this value is `true`, the driver continues and simply warns you the errors
|
||||
are happening.
|
||||
|
||||
**Note**: The ideal is to pursue a `docker` daemon and environment
|
||||
that does support synchronizing with `udev`. For further discussion on
|
||||
this topic, see
|
||||
**Note**: The ideal is to pursue a `docker` daemon and environment that does
|
||||
support synchronizing with `udev`. For further discussion on this topic, see
|
||||
[docker#4036](https://github.com/docker/docker/issues/4036).
|
||||
Otherwise, set this flag for migrating existing Docker daemons to a
|
||||
daemon with a supported environment.
|
||||
Otherwise, set this flag for migrating existing Docker daemons to a daemon with
|
||||
a supported environment.
|
||||
|
||||
#### dm.min_free_space
|
||||
|
||||
|
@ -536,14 +572,13 @@ free space checking logic. If user does not specify a value for this option,
|
|||
the Engine uses a default value of 10%.
|
||||
|
||||
Whenever a new a thin pool device is created (during `docker pull` or during
|
||||
container creation), the Engine checks if the minimum free space is
|
||||
available. If the space is unavailable, then device creation fails and any
|
||||
relevant `docker` operation fails.
|
||||
container creation), the Engine checks if the minimum free space is available.
|
||||
If the space is unavailable, then device creation fails and any relevant
|
||||
`docker` operation fails.
|
||||
|
||||
To recover from this error, you must create more free space in the thin pool to
|
||||
recover from the error. You can create free space by deleting some images
|
||||
and containers from tge thin pool. You can also add
|
||||
more storage to the thin pool.
|
||||
recover from the error. You can create free space by deleting some images and
|
||||
containers from tge thin pool. You can also add more storage to the thin pool.
|
||||
|
||||
To add more space to an LVM (logical volume management) thin pool, just add
|
||||
more storage to the group container thin pool; this should automatically
|
||||
|
@ -555,13 +590,13 @@ Example use:: `dockerd --storage-opt dm.min_free_space=10%`
|
|||
|
||||
#### dm.xfs_nospace_max_retries
|
||||
|
||||
Specifies the maximum number of retries XFS should attempt to complete
|
||||
IO when ENOSPC (no space) error is returned by underlying storage device.
|
||||
Specifies the maximum number of retries XFS should attempt to complete IO when
|
||||
ENOSPC (no space) error is returned by underlying storage device.
|
||||
|
||||
By default XFS retries infinitely for IO to finish and this can result
|
||||
in unkillable process. To change this behavior one can set
|
||||
xfs_nospace_max_retries to say 0 and XFS will not retry IO after getting
|
||||
ENOSPC and will shutdown filesystem.
|
||||
By default XFS retries infinitely for IO to finish and this can result in
|
||||
unkillable process. To change this behavior one can set xfs_nospace_max_retries
|
||||
to say 0 and XFS will not retry IO after getting ENOSPC and will shutdown
|
||||
filesystem.
|
||||
|
||||
Example use:
|
||||
|
||||
|
@ -572,9 +607,9 @@ Example use:
|
|||
|
||||
#### zfs.fsname
|
||||
|
||||
Set zfs filesystem under which docker will create its own datasets.
|
||||
By default docker will pick up the zfs filesystem where docker graph
|
||||
(`/var/lib/docker`) is located.
|
||||
Set zfs filesystem under which docker will create its own datasets. By default
|
||||
docker will pick up the zfs filesystem where docker graph (`/var/lib/docker`)
|
||||
is located.
|
||||
|
||||
Example use: `dockerd -s zfs --storage-opt zfs.fsname=zroot/docker`
|
||||
|
||||
|
@ -582,20 +617,19 @@ Example use: `dockerd -s zfs --storage-opt zfs.fsname=zroot/docker`
|
|||
|
||||
#### btrfs.min_space
|
||||
|
||||
Specifies the mininum size to use when creating the subvolume which is used
|
||||
for containers. If user uses disk quota for btrfs when creating or running
|
||||
a container with **--storage-opt size** option, docker should ensure the
|
||||
**size** cannot be smaller than **btrfs.min_space**.
|
||||
Specifies the mininum size to use when creating the subvolume which is used for
|
||||
containers. If user uses disk quota for btrfs when creating or running a
|
||||
container with **--storage-opt size** option, docker should ensure the **size**
|
||||
cannot be smaller than **btrfs.min_space**.
|
||||
|
||||
Example use: `docker daemon -s btrfs --storage-opt btrfs.min_space=10G`
|
||||
|
||||
# CLUSTER STORE OPTIONS
|
||||
|
||||
The daemon uses libkv to advertise
|
||||
the node within the cluster. Some Key/Value backends support mutual
|
||||
TLS, and the client TLS settings used by the daemon can be configured
|
||||
using the **--cluster-store-opt** flag, specifying the paths to PEM encoded
|
||||
files.
|
||||
The daemon uses libkv to advertise the node within the cluster. Some Key/Value
|
||||
backends support mutual TLS, and the client TLS settings used by the daemon can
|
||||
be configured using the **--cluster-store-opt** flag, specifying the paths to
|
||||
PEM encoded files.
|
||||
|
||||
#### kv.cacertfile
|
||||
|
||||
|
@ -604,19 +638,19 @@ Specifies the path to a local file with PEM encoded CA certificates to trust
|
|||
#### kv.certfile
|
||||
|
||||
Specifies the path to a local file with a PEM encoded certificate. This
|
||||
certificate is used as the client cert for communication with the
|
||||
Key/Value store.
|
||||
certificate is used as the client cert for communication with the Key/Value
|
||||
store.
|
||||
|
||||
#### kv.keyfile
|
||||
|
||||
Specifies the path to a local file with a PEM encoded private key. This
|
||||
private key is used as the client key for communication with the
|
||||
Key/Value store.
|
||||
private key is used as the client key for communication with the Key/Value
|
||||
store.
|
||||
|
||||
# Access authorization
|
||||
|
||||
Docker's access authorization can be extended by authorization plugins that your
|
||||
organization can purchase or build themselves. You can install one or more
|
||||
Docker's access authorization can be extended by authorization plugins that
|
||||
your organization can purchase or build themselves. You can install one or more
|
||||
authorization plugins when you start the Docker `daemon` using the
|
||||
`--authorization-plugin=PLUGIN_ID` option.
|
||||
|
||||
|
@ -624,10 +658,10 @@ authorization plugins when you start the Docker `daemon` using the
|
|||
dockerd --authorization-plugin=plugin1 --authorization-plugin=plugin2,...
|
||||
```
|
||||
|
||||
The `PLUGIN_ID` value is either the plugin's name or a path to its specification
|
||||
file. The plugin's implementation determines whether you can specify a name or
|
||||
path. Consult with your Docker administrator to get information about the
|
||||
plugins available to you.
|
||||
The `PLUGIN_ID` value is either the plugin's name or a path to its
|
||||
specification file. The plugin's implementation determines whether you can
|
||||
specify a name or path. Consult with your Docker administrator to get
|
||||
information about the plugins available to you.
|
||||
|
||||
Once a plugin is installed, requests made to the `daemon` through the command
|
||||
line or Docker's remote API are allowed or denied by the plugin. If you have
|
||||
|
|
|
@ -44,7 +44,7 @@ func TailFile(f io.ReadSeeker, n int) ([][]byte, error) {
|
|||
break
|
||||
} else {
|
||||
b = make([]byte, blockSize)
|
||||
if _, err := f.Seek(step, os.SEEK_END); err != nil {
|
||||
if _, err := f.Seek(left, os.SEEK_SET); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := f.Read(b); err != nil {
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/libcontainerd"
|
||||
"github.com/docker/docker/oci"
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
"github.com/docker/docker/plugin/v2"
|
||||
|
@ -48,6 +49,25 @@ func (pm *Manager) restore(p *v2.Plugin) error {
|
|||
return pm.containerdClient.Restore(p.GetID(), attachToLog(p.GetID()))
|
||||
}
|
||||
|
||||
func shutdownPlugin(p *v2.Plugin, containerdClient libcontainerd.Client) {
|
||||
pluginID := p.GetID()
|
||||
|
||||
err := containerdClient.Signal(pluginID, int(syscall.SIGTERM))
|
||||
if err != nil {
|
||||
logrus.Errorf("Sending SIGTERM to plugin failed with error: %v", err)
|
||||
} else {
|
||||
select {
|
||||
case <-p.ExitChan:
|
||||
logrus.Debug("Clean shutdown of plugin")
|
||||
case <-time.After(time.Second * 10):
|
||||
logrus.Debug("Force shutdown plugin")
|
||||
if err := containerdClient.Signal(pluginID, int(syscall.SIGKILL)); err != nil {
|
||||
logrus.Errorf("Sending SIGKILL to plugin failed with error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pm *Manager) disable(p *v2.Plugin) error {
|
||||
if !p.IsEnabled() {
|
||||
return fmt.Errorf("plugin %s is already disabled", p.Name())
|
||||
|
@ -55,9 +75,8 @@ func (pm *Manager) disable(p *v2.Plugin) error {
|
|||
p.Lock()
|
||||
p.Restart = false
|
||||
p.Unlock()
|
||||
if err := pm.containerdClient.Signal(p.GetID(), int(syscall.SIGKILL)); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
shutdownPlugin(p, pm.containerdClient)
|
||||
pm.pluginStore.SetState(p, false)
|
||||
return nil
|
||||
}
|
||||
|
@ -71,25 +90,11 @@ func (pm *Manager) Shutdown() {
|
|||
continue
|
||||
}
|
||||
if pm.containerdClient != nil && p.IsEnabled() {
|
||||
pluginID := p.GetID()
|
||||
p.Lock()
|
||||
p.ExitChan = make(chan bool)
|
||||
p.Restart = false
|
||||
p.Unlock()
|
||||
err := pm.containerdClient.Signal(p.PluginObj.ID, int(syscall.SIGTERM))
|
||||
if err != nil {
|
||||
logrus.Errorf("Sending SIGTERM to plugin failed with error: %v", err)
|
||||
} else {
|
||||
select {
|
||||
case <-p.ExitChan:
|
||||
logrus.Debug("Clean shutdown of plugin")
|
||||
case <-time.After(time.Second * 10):
|
||||
logrus.Debug("Force shutdown plugin")
|
||||
if err := pm.containerdClient.Signal(pluginID, int(syscall.SIGKILL)); err != nil {
|
||||
logrus.Errorf("Sending SIGKILL to plugin failed with error: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
shutdownPlugin(p, pm.containerdClient)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -269,7 +269,7 @@ func (r *Root) validateName(name string) error {
|
|||
return validationError{fmt.Errorf("volume name is too short, names should be at least two alphanumeric characters")}
|
||||
}
|
||||
if !volumeNameRegex.MatchString(name) {
|
||||
return validationError{fmt.Errorf("%q includes invalid characters for a local volume name, only %q are allowed", name, utils.RestrictedNameChars)}
|
||||
return validationError{fmt.Errorf("%q includes invalid characters for a local volume name, only %q are allowed. If you intented to pass a host directory, use absolute path.", name, utils.RestrictedNameChars)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue