diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f9d0e35c0..f5e53f7412 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1018,7 +1018,7 @@ by another client (#15489) #### Security - Fix tar breakout vulnerability * Extractions are now sandboxed chroot -- Security options are no longer committed to images +- Security options are no longer comitted to images #### Runtime - Fix deadlock in `docker ps -f exited=1` @@ -1444,7 +1444,7 @@ by another client (#15489) * Update issue filing instructions * Warn against the use of symlinks for Docker's storage folder * Replace the Firefox example with an IceWeasel example -* Rewrite the PostgresSQL example using a Dockerfile and add more details to it +* Rewrite the PostgreSQL example using a Dockerfile and add more details to it * Improve the OS X documentation #### Remote API diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index 52721c2dde..f662cac366 100644 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -36,6 +36,7 @@ RUN apt-get update && apt-get install -y \ libapparmor-dev \ libc6-dev \ libcap-dev \ + libltdl-dev \ libsqlite3-dev \ libsystemd-dev \ mercurial \ diff --git a/api/client/container/cp.go b/api/client/container/cp.go index 6870ef3c18..a0031c8b00 100644 --- a/api/client/container/cp.go +++ b/api/client/container/cp.go @@ -44,6 +44,7 @@ func NewCopyCommand(dockerCli *client.DockerCli) *cobra.Command { docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH`, Short: "Copy files/folders between a container and the local filesystem", Long: strings.Join([]string{ + "Copy files/folders between a container and the local filesystem\n", "\nUse '-' as the source to read a tar archive from stdin\n", "and extract it to a directory destination in a container.\n", "Use '-' as the destination to stream a tar archive of a\n", diff --git a/api/client/container/ps.go b/api/client/container/ps.go index 3693ae75b9..cc4add938b 100644 --- a/api/client/container/ps.go +++ b/api/client/container/ps.go @@ -55,7 +55,7 @@ func NewPsCommand(dockerCli *client.DockerCli) *cobra.Command { flags.BoolVarP(&opts.all, "all", "a", false, "Show all containers (default shows just running)") flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output") flags.BoolVarP(&opts.nLatest, "latest", "l", false, "Show the latest created container (includes all states)") - flags.IntVarP(&opts.last, "", "n", -1, "Show n last created containers (includes all states)") + flags.IntVarP(&opts.last, "last", "n", -1, "Show n last created containers (includes all states)") flags.StringVarP(&opts.format, "format", "", "", "Pretty-print containers using a Go template") flags.StringSliceVarP(&opts.filter, "filter", "f", []string{}, "Filter output based on conditions provided") diff --git a/api/client/image/tag.go b/api/client/image/tag.go index 5c0b569fb5..665e3430c7 100644 --- a/api/client/image/tag.go +++ b/api/client/image/tag.go @@ -18,7 +18,7 @@ func NewTagCommand(dockerCli *client.DockerCli) *cobra.Command { var opts tagOptions cmd := &cobra.Command{ - Use: "tag IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]", + Use: "tag IMAGE[:TAG] IMAGE[:TAG]", Short: "Tag an image into a repository", Args: cli.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/api/client/info.go b/api/client/info.go index de7e5828f1..a84e6217a4 100644 --- a/api/client/info.go +++ b/api/client/info.go @@ -51,7 +51,6 @@ func (cli *DockerCli) CmdInfo(args ...string) error { fmt.Fprintf(cli.out, "%s: %s\n", pair[0], pair[1]) } } - ioutils.FprintfIfNotEmpty(cli.out, "Execution Driver: %s\n", info.ExecutionDriver) ioutils.FprintfIfNotEmpty(cli.out, "Logging Driver: %s\n", info.LoggingDriver) ioutils.FprintfIfNotEmpty(cli.out, "Cgroup Driver: %s\n", info.CgroupDriver) diff --git a/api/client/network/remove.go b/api/client/network/remove.go index 01a591833b..f5b0196d97 100644 --- a/api/client/network/remove.go +++ b/api/client/network/remove.go @@ -33,7 +33,7 @@ func runRemove(dockerCli *client.DockerCli, networks []string) error { status = 1 continue } - fmt.Fprintf(dockerCli.Err(), "%s\n", name) + fmt.Fprintf(dockerCli.Out(), "%s\n", name) } if status != 0 { diff --git a/api/client/node/cmd.go b/api/client/node/cmd.go index 9971745ede..96c8e5bc09 100644 --- a/api/client/node/cmd.go +++ b/api/client/node/cmd.go @@ -35,9 +35,10 @@ func NewNodeCommand(dockerCli *client.DockerCli) *cobra.Command { return cmd } -func nodeReference(client apiclient.APIClient, ctx context.Context, ref string) (string, error) { - // The special value "self" for a node reference is mapped to the current - // node, hence the node ID is retrieved using the `/info` endpoint. +// Reference returns the reference of a node. The special value "self" for a node +// reference is mapped to the current node, hence the node ID is retrieved using +// the `/info` endpoint. +func Reference(client apiclient.APIClient, ctx context.Context, ref string) (string, error) { if ref == "self" { info, err := client.Info(ctx) if err != nil { diff --git a/api/client/node/inspect.go b/api/client/node/inspect.go index 2ac0cd40fa..022cb92b47 100644 --- a/api/client/node/inspect.go +++ b/api/client/node/inspect.go @@ -45,7 +45,7 @@ func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error { client := dockerCli.Client() ctx := context.Background() getRef := func(ref string) (interface{}, []byte, error) { - nodeRef, err := nodeReference(client, ctx, ref) + nodeRef, err := Reference(client, ctx, ref) if err != nil { return nil, nil, err } diff --git a/api/client/node/tasks.go b/api/client/node/tasks.go index f09d815027..d30c5e700d 100644 --- a/api/client/node/tasks.go +++ b/api/client/node/tasks.go @@ -44,7 +44,7 @@ func runTasks(dockerCli *client.DockerCli, opts tasksOptions) error { client := dockerCli.Client() ctx := context.Background() - nodeRef, err := nodeReference(client, ctx, opts.nodeID) + nodeRef, err := Reference(client, ctx, opts.nodeID) if err != nil { return nil } @@ -55,10 +55,9 @@ func runTasks(dockerCli *client.DockerCli, opts tasksOptions) error { filter := opts.filter.Value() filter.Add("node", node.ID) - if !opts.all && !filter.Include("desired_state") { - filter.Add("desired_state", string(swarm.TaskStateRunning)) - filter.Add("desired_state", string(swarm.TaskStateAccepted)) - + if !opts.all && !filter.Include("desired-state") { + filter.Add("desired-state", string(swarm.TaskStateRunning)) + filter.Add("desired-state", string(swarm.TaskStateAccepted)) } tasks, err := client.TaskList( diff --git a/api/client/registry/logout.go b/api/client/registry/logout.go index b7497a4743..dad27644a6 100644 --- a/api/client/registry/logout.go +++ b/api/client/registry/logout.go @@ -45,7 +45,7 @@ func runLogout(dockerCli *client.DockerCli, serverAddress string) error { fmt.Fprintf(dockerCli.Out(), "Remove login credentials for %s\n", serverAddress) if err := client.EraseCredentials(dockerCli.ConfigFile(), serverAddress); err != nil { - fmt.Fprintf(dockerCli.Out(), "WARNING: could not erase credentials: %v\n", err) + fmt.Fprintf(dockerCli.Err(), "WARNING: could not erase credentials: %v\n", err) } return nil diff --git a/api/client/service/create.go b/api/client/service/create.go index 10fcb20f9a..be707c5f5d 100644 --- a/api/client/service/create.go +++ b/api/client/service/create.go @@ -5,6 +5,7 @@ import ( "github.com/docker/docker/api/client" "github.com/docker/docker/cli" + "github.com/docker/engine-api/types" "github.com/spf13/cobra" "golang.org/x/net/context" ) @@ -33,7 +34,7 @@ func newCreateCommand(dockerCli *client.DockerCli) *cobra.Command { func runCreate(dockerCli *client.DockerCli, opts *serviceOptions) error { apiClient := dockerCli.Client() - headers := map[string][]string{} + createOpts := types.ServiceCreateOptions{} service, err := opts.ToService() if err != nil { @@ -49,10 +50,10 @@ func runCreate(dockerCli *client.DockerCli, opts *serviceOptions) error { if err != nil { return err } - headers["X-Registry-Auth"] = []string{encodedAuth} + createOpts.EncodedRegistryAuth = encodedAuth } - response, err := apiClient.ServiceCreate(ctx, service, headers) + response, err := apiClient.ServiceCreate(ctx, service, createOpts) if err != nil { return err } diff --git a/api/client/service/inspect.go b/api/client/service/inspect.go index 8df91ceace..4b17ce837d 100644 --- a/api/client/service/inspect.go +++ b/api/client/service/inspect.go @@ -169,7 +169,7 @@ func printContainerSpec(out io.Writer, containerSpec swarm.ContainerSpec) { for _, v := range containerSpec.Mounts { fmt.Fprintf(out, " Target = %s\n", v.Target) fmt.Fprintf(out, " Source = %s\n", v.Source) - fmt.Fprintf(out, " Writable = %v\n", v.Writable) + fmt.Fprintf(out, " ReadOnly = %v\n", v.ReadOnly) fmt.Fprintf(out, " Type = %v\n", v.Type) } } diff --git a/api/client/service/opts.go b/api/client/service/opts.go index e7ac8513bf..b2465977c5 100644 --- a/api/client/service/opts.go +++ b/api/client/service/opts.go @@ -176,10 +176,16 @@ func (m *MountOpt) Set(value string) error { } } + // Set writable as the default for _, field := range fields { parts := strings.SplitN(field, "=", 2) - if len(parts) == 1 && strings.ToLower(parts[0]) == "writable" { - mount.Writable = true + if len(parts) == 1 && strings.ToLower(parts[0]) == "readonly" { + mount.ReadOnly = true + continue + } + + if len(parts) == 1 && strings.ToLower(parts[0]) == "volume-nocopy" { + volumeOptions().NoCopy = true continue } @@ -195,15 +201,16 @@ func (m *MountOpt) Set(value string) error { mount.Source = value case "target": mount.Target = value - case "writable": - mount.Writable, err = strconv.ParseBool(value) + case "readonly": + ro, err := strconv.ParseBool(value) if err != nil { - return fmt.Errorf("invalid value for writable: %s", value) + return fmt.Errorf("invalid value for readonly: %s", value) } + mount.ReadOnly = ro case "bind-propagation": bindOptions().Propagation = swarm.MountPropagation(strings.ToUpper(value)) - case "volume-populate": - volumeOptions().Populate, err = strconv.ParseBool(value) + case "volume-nocopy": + volumeOptions().NoCopy, err = strconv.ParseBool(value) if err != nil { return fmt.Errorf("invalid value for populate: %s", value) } @@ -229,6 +236,17 @@ func (m *MountOpt) Set(value string) error { return fmt.Errorf("target is required") } + if mount.VolumeOptions != nil && mount.Source == "" { + return fmt.Errorf("source is required when specifying volume-* options") + } + + if mount.Type == swarm.MountType("BIND") && mount.VolumeOptions != nil { + return fmt.Errorf("cannot mix 'volume-*' options with mount type '%s'", swarm.MountTypeBind) + } + if mount.Type == swarm.MountType("VOLUME") && mount.BindOptions != nil { + return fmt.Errorf("cannot mix 'bind-*' options with mount type '%s'", swarm.MountTypeVolume) + } + m.values = append(m.values, mount) return nil } @@ -458,7 +476,7 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) { flags.Var(&opts.replicas, flagReplicas, "Number of tasks") - flags.StringVar(&opts.restartPolicy.condition, flagRestartCondition, "", "Restart when condition is met (none, on_failure, or any)") + flags.StringVar(&opts.restartPolicy.condition, flagRestartCondition, "", "Restart when condition is met (none, on-failure, or any)") flags.Var(&opts.restartPolicy.delay, flagRestartDelay, "Delay between restart attempts") flags.Var(&opts.restartPolicy.maxAttempts, flagRestartMaxAttempts, "Maximum number of restarts before giving up") flags.Var(&opts.restartPolicy.window, flagRestartWindow, "Window used to evaluate the restart policy") @@ -469,7 +487,7 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) { flags.DurationVar(&opts.update.delay, flagUpdateDelay, time.Duration(0), "Delay between updates") flags.StringSliceVar(&opts.networks, flagNetwork, []string{}, "Network attachments") - flags.StringVar(&opts.endpoint.mode, flagEndpointMode, "", "Endpoint mode(Valid values: vip, dnsrr)") + flags.StringVar(&opts.endpoint.mode, flagEndpointMode, "", "Endpoint mode (vip or dnsrr)") flags.VarP(&opts.endpoint.ports, flagPublish, "p", "Publish a port as a node port") flags.BoolVar(&opts.registryAuth, flagRegistryAuth, false, "Send registry authentication details to Swarm agents") diff --git a/api/client/service/opts_test.go b/api/client/service/opts_test.go index 808ce236ef..c2a17115f5 100644 --- a/api/client/service/opts_test.go +++ b/api/client/service/opts_test.go @@ -111,5 +111,53 @@ func TestMountOptSetErrorInvalidField(t *testing.T) { func TestMountOptSetErrorInvalidWritable(t *testing.T) { var mount MountOpt - assert.Error(t, mount.Set("type=VOLUME,writable=yes"), "invalid value for writable: yes") + assert.Error(t, mount.Set("type=VOLUME,readonly=no"), "invalid value for readonly: no") +} + +func TestMountOptDefaultEnableWritable(t *testing.T) { + var m MountOpt + assert.NilError(t, m.Set("type=bind,target=/foo,source=/foo")) + assert.Equal(t, m.values[0].ReadOnly, false) + + m = MountOpt{} + assert.NilError(t, m.Set("type=bind,target=/foo,source=/foo,readonly")) + assert.Equal(t, m.values[0].ReadOnly, true) + + m = MountOpt{} + assert.NilError(t, m.Set("type=bind,target=/foo,source=/foo,readonly=1")) + assert.Equal(t, m.values[0].ReadOnly, true) + + m = MountOpt{} + assert.NilError(t, m.Set("type=bind,target=/foo,source=/foo,readonly=0")) + assert.Equal(t, m.values[0].ReadOnly, false) +} + +func TestMountOptVolumeNoCopy(t *testing.T) { + var m MountOpt + assert.Error(t, m.Set("type=volume,target=/foo,volume-nocopy"), "source is required") + + m = MountOpt{} + assert.NilError(t, m.Set("type=volume,target=/foo,source=foo")) + assert.Equal(t, m.values[0].VolumeOptions == nil, true) + + m = MountOpt{} + assert.NilError(t, m.Set("type=volume,target=/foo,source=foo,volume-nocopy=true")) + assert.Equal(t, m.values[0].VolumeOptions != nil, true) + assert.Equal(t, m.values[0].VolumeOptions.NoCopy, true) + + m = MountOpt{} + assert.NilError(t, m.Set("type=volume,target=/foo,source=foo,volume-nocopy")) + assert.Equal(t, m.values[0].VolumeOptions != nil, true) + assert.Equal(t, m.values[0].VolumeOptions.NoCopy, true) + + m = MountOpt{} + assert.NilError(t, m.Set("type=volume,target=/foo,source=foo,volume-nocopy=1")) + assert.Equal(t, m.values[0].VolumeOptions != nil, true) + assert.Equal(t, m.values[0].VolumeOptions.NoCopy, true) +} + +func TestMountOptTypeConflict(t *testing.T) { + var m MountOpt + assert.Error(t, m.Set("type=bind,target=/foo,source=/foo,volume-nocopy=true"), "cannot mix") + assert.Error(t, m.Set("type=volume,target=/foo,source=/foo,bind-propagation=rprivate"), "cannot mix") } diff --git a/api/client/service/scale.go b/api/client/service/scale.go index 2643fdcf27..1a3ea80eaf 100644 --- a/api/client/service/scale.go +++ b/api/client/service/scale.go @@ -9,6 +9,7 @@ import ( "github.com/docker/docker/api/client" "github.com/docker/docker/cli" + "github.com/docker/engine-api/types" "github.com/spf13/cobra" ) @@ -77,7 +78,7 @@ func runServiceScale(dockerCli *client.DockerCli, serviceID string, scale string } serviceMode.Replicated.Replicas = &uintScale - err = client.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, nil) + err = client.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{}) if err != nil { return err } diff --git a/api/client/service/tasks.go b/api/client/service/tasks.go index 7520b1f16d..779e642939 100644 --- a/api/client/service/tasks.go +++ b/api/client/service/tasks.go @@ -5,6 +5,7 @@ import ( "github.com/docker/docker/api/client" "github.com/docker/docker/api/client/idresolver" + "github.com/docker/docker/api/client/node" "github.com/docker/docker/api/client/task" "github.com/docker/docker/cli" "github.com/docker/docker/opts" @@ -51,9 +52,21 @@ func runTasks(dockerCli *client.DockerCli, opts tasksOptions) error { filter := opts.filter.Value() filter.Add("service", service.ID) - if !opts.all && !filter.Include("desired_state") { - filter.Add("desired_state", string(swarm.TaskStateRunning)) - filter.Add("desired_state", string(swarm.TaskStateAccepted)) + if !opts.all && !filter.Include("desired-state") { + filter.Add("desired-state", string(swarm.TaskStateRunning)) + filter.Add("desired-state", string(swarm.TaskStateAccepted)) + } + + if filter.Include("node") { + nodeFilters := filter.Get("node") + for _, nodeFilter := range nodeFilters { + nodeReference, err := node.Reference(client, ctx, nodeFilter) + if err != nil { + return err + } + filter.Del("node", nodeFilter) + filter.Add("node", nodeReference) + } } tasks, err := client.TaskList(ctx, types.TaskListOptions{Filter: filter}) diff --git a/api/client/service/update.go b/api/client/service/update.go index cd6f1537db..78f98a3283 100644 --- a/api/client/service/update.go +++ b/api/client/service/update.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/cli" "github.com/docker/docker/opts" runconfigopts "github.com/docker/docker/runconfig/opts" + "github.com/docker/engine-api/types" "github.com/docker/engine-api/types/swarm" "github.com/docker/go-connections/nat" "github.com/spf13/cobra" @@ -39,7 +40,7 @@ func newUpdateCommand(dockerCli *client.DockerCli) *cobra.Command { func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, serviceID string) error { apiClient := dockerCli.Client() ctx := context.Background() - headers := map[string][]string{} + updateOpts := types.ServiceUpdateOptions{} service, _, err := apiClient.ServiceInspectWithRaw(ctx, serviceID) if err != nil { @@ -64,10 +65,10 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, serviceID stri if err != nil { return err } - headers["X-Registry-Auth"] = []string{encodedAuth} + updateOpts.EncodedRegistryAuth = encodedAuth } - err = apiClient.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, headers) + err = apiClient.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, updateOpts) if err != nil { return err } diff --git a/api/client/stack/cmd.go b/api/client/stack/cmd.go index c095441b9c..82a7a1ffa6 100644 --- a/api/client/stack/cmd.go +++ b/api/client/stack/cmd.go @@ -29,7 +29,7 @@ func NewStackCommand(dockerCli *client.DockerCli) *cobra.Command { return cmd } -// NewTopLevelDeployCommand return a command for `docker deploy` +// NewTopLevelDeployCommand returns a command for `docker deploy` func NewTopLevelDeployCommand(dockerCli *client.DockerCli) *cobra.Command { cmd := newDeployCommand(dockerCli) // Remove the aliases at the top level diff --git a/api/client/stack/deploy.go b/api/client/stack/deploy.go index 4dcd19dc4d..745b568427 100644 --- a/api/client/stack/deploy.go +++ b/api/client/stack/deploy.go @@ -184,13 +184,13 @@ func deployServices( if service, exists := existingServiceMap[name]; exists { fmt.Fprintf(out, "Updating service %s (id: %s)\n", name, service.ID) - // TODO(nishanttotla): Pass headers with X-Registry-Auth + // TODO(nishanttotla): Pass auth token if err := apiClient.ServiceUpdate( ctx, service.ID, service.Version, serviceSpec, - nil, + types.ServiceUpdateOptions{}, ); err != nil { return err } @@ -198,7 +198,7 @@ func deployServices( fmt.Fprintf(out, "Creating service %s\n", name) // TODO(nishanttotla): Pass headers with X-Registry-Auth - if _, err := apiClient.ServiceCreate(ctx, serviceSpec, nil); err != nil { + if _, err := apiClient.ServiceCreate(ctx, serviceSpec, types.ServiceCreateOptions{}); err != nil { return err } } diff --git a/api/client/stack/opts.go b/api/client/stack/opts.go index 5cabe5c432..81af1dfe2f 100644 --- a/api/client/stack/opts.go +++ b/api/client/stack/opts.go @@ -35,6 +35,7 @@ func loadBundlefile(stderr io.Writer, namespace string, path string) (*bundlefil if err != nil { return nil, err } + defer reader.Close() bundle, err := bundlefile.LoadFile(reader) if err != nil { diff --git a/api/client/stack/remove.go b/api/client/stack/remove.go index 1d066d42e6..9ba91e5c23 100644 --- a/api/client/stack/remove.go +++ b/api/client/stack/remove.go @@ -63,6 +63,11 @@ func runRemove(dockerCli *client.DockerCli, opts removeOptions) error { } } + if len(services) == 0 && len(networks) == 0 { + fmt.Fprintf(dockerCli.Out(), "Nothing found in stack: %s\n", namespace) + return nil + } + if hasError { return fmt.Errorf("Failed to remove some resources") } diff --git a/api/client/stack/tasks.go b/api/client/stack/tasks.go index 5ed1fbae35..85fa0f6cb7 100644 --- a/api/client/stack/tasks.go +++ b/api/client/stack/tasks.go @@ -3,6 +3,8 @@ package stack import ( + "fmt" + "golang.org/x/net/context" "github.com/docker/docker/api/client" @@ -43,14 +45,15 @@ func newTasksCommand(dockerCli *client.DockerCli) *cobra.Command { } func runTasks(dockerCli *client.DockerCli, opts tasksOptions) error { + namespace := opts.namespace client := dockerCli.Client() ctx := context.Background() filter := opts.filter.Value() filter.Add("label", labelNamespace+"="+opts.namespace) - if !opts.all && !filter.Include("desired_state") { - filter.Add("desired_state", string(swarm.TaskStateRunning)) - filter.Add("desired_state", string(swarm.TaskStateAccepted)) + if !opts.all && !filter.Include("desired-state") { + filter.Add("desired-state", string(swarm.TaskStateRunning)) + filter.Add("desired-state", string(swarm.TaskStateAccepted)) } tasks, err := client.TaskList(ctx, types.TaskListOptions{Filter: filter}) @@ -58,5 +61,10 @@ func runTasks(dockerCli *client.DockerCli, opts tasksOptions) error { return err } + if len(tasks) == 0 { + fmt.Fprintf(dockerCli.Out(), "Nothing found in stack: %s\n", namespace) + return nil + } + return task.Print(dockerCli, ctx, tasks, idresolver.New(client, opts.noResolve)) } diff --git a/api/client/swarm/init.go b/api/client/swarm/init.go index ca09b0aebc..83ffb47847 100644 --- a/api/client/swarm/init.go +++ b/api/client/swarm/init.go @@ -12,6 +12,13 @@ import ( "github.com/spf13/pflag" ) +const ( + generatedSecretEntropyBytes = 16 + generatedSecretBase = 36 + // floor(log(2^128-1, 36)) + 1 + maxGeneratedSecretLength = 25 +) + type initOptions struct { swarmOptions listenAddr NodeAddrOption @@ -46,6 +53,12 @@ func runInit(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts initOptions client := dockerCli.Client() ctx := context.Background() + // If no secret was specified, we create a random one + if !flags.Changed("secret") { + opts.secret = generateRandomSecret() + fmt.Fprintf(dockerCli.Out(), "No --secret provided. Generated random secret:\n\t%s\n\n", opts.secret) + } + req := swarm.InitRequest{ ListenAddr: opts.listenAddr.String(), ForceNewCluster: opts.forceNewCluster, @@ -56,6 +69,27 @@ func runInit(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts initOptions if err != nil { return err } - fmt.Printf("Swarm initialized: current node (%s) is now a manager.\n", nodeID) + + fmt.Fprintf(dockerCli.Out(), "Swarm initialized: current node (%s) is now a manager.\n\n", nodeID) + + // Fetch CAHash and Address from the API + info, err := client.Info(ctx) + if err != nil { + return err + } + + node, _, err := client.NodeInspectWithRaw(ctx, nodeID) + if err != nil { + return err + } + + if node.ManagerStatus != nil && info.Swarm.CACertHash != "" { + var secretArgs string + if opts.secret != "" { + secretArgs = "--secret " + opts.secret + } + fmt.Fprintf(dockerCli.Out(), "To add a worker to this swarm, run the following command:\n\tdocker swarm join %s \\\n\t--ca-hash %s \\\n\t%s\n", secretArgs, info.Swarm.CACertHash, node.ManagerStatus.Addr) + } + return nil } diff --git a/api/client/swarm/opts.go b/api/client/swarm/opts.go index 72d6a7a827..92011fea23 100644 --- a/api/client/swarm/opts.go +++ b/api/client/swarm/opts.go @@ -14,10 +14,10 @@ import ( const ( defaultListenAddr = "0.0.0.0:2377" - // WORKER constant for worker name - WORKER = "WORKER" - // MANAGER constant for manager name - MANAGER = "MANAGER" + + worker = "WORKER" + manager = "MANAGER" + none = "NONE" flagAutoAccept = "auto-accept" flagCertExpiry = "cert-expiry" @@ -30,8 +30,8 @@ const ( var ( defaultPolicies = []swarm.Policy{ - {Role: WORKER, Autoaccept: true}, - {Role: MANAGER, Autoaccept: false}, + {Role: worker, Autoaccept: true}, + {Role: manager, Autoaccept: false}, } ) @@ -86,40 +86,33 @@ func NewListenAddrOption() NodeAddrOption { // AutoAcceptOption is a value type for auto-accept policy type AutoAcceptOption struct { - values map[string]bool + values map[string]struct{} } // String prints a string representation of this option func (o *AutoAcceptOption) String() string { keys := []string{} - for key, value := range o.values { - keys = append(keys, fmt.Sprintf("%s=%v", strings.ToLower(key), value)) + for key := range o.values { + keys = append(keys, fmt.Sprintf("%s=true", strings.ToLower(key))) } return strings.Join(keys, ", ") } // Set sets a new value on this option -func (o *AutoAcceptOption) Set(value string) error { - value = strings.ToUpper(value) - switch value { - case "", "NONE": - if accept, ok := o.values[WORKER]; ok && accept { - return fmt.Errorf("value NONE is incompatible with %s", WORKER) +func (o *AutoAcceptOption) Set(acceptValues string) error { + for _, value := range strings.Split(acceptValues, ",") { + value = strings.ToUpper(value) + switch value { + case none, worker, manager: + o.values[value] = struct{}{} + default: + return fmt.Errorf("must be one / combination of %s, %s; or NONE", worker, manager) } - if accept, ok := o.values[MANAGER]; ok && accept { - return fmt.Errorf("value NONE is incompatible with %s", MANAGER) - } - o.values[WORKER] = false - o.values[MANAGER] = false - case WORKER, MANAGER: - if accept, ok := o.values[value]; ok && !accept { - return fmt.Errorf("value NONE is incompatible with %s", value) - } - o.values[value] = true - default: - return fmt.Errorf("must be one of %s, %s, NONE", WORKER, MANAGER) } - + // NONE must stand alone, so if any non-NONE setting exist with it, error with conflict + if o.isPresent(none) && len(o.values) > 1 { + return fmt.Errorf("value NONE cannot be specified alongside other node types") + } return nil } @@ -133,7 +126,11 @@ func (o *AutoAcceptOption) Policies(secret *string) []swarm.Policy { policies := []swarm.Policy{} for _, p := range defaultPolicies { if len(o.values) != 0 { - p.Autoaccept = o.values[string(p.Role)] + if _, ok := o.values[string(p.Role)]; ok { + p.Autoaccept = true + } else { + p.Autoaccept = false + } } p.Secret = secret policies = append(policies, p) @@ -141,9 +138,15 @@ func (o *AutoAcceptOption) Policies(secret *string) []swarm.Policy { return policies } +// isPresent returns whether the key exists in the set or not +func (o *AutoAcceptOption) isPresent(key string) bool { + _, c := o.values[key] + return c +} + // NewAutoAcceptOption returns a new auto-accept option func NewAutoAcceptOption() AutoAcceptOption { - return AutoAcceptOption{values: make(map[string]bool)} + return AutoAcceptOption{values: make(map[string]struct{})} } // ExternalCAOption is a Value type for parsing external CA specifications. @@ -237,7 +240,7 @@ func parseExternalCA(caSpec string) (*swarm.ExternalCA, error) { func addSwarmFlags(flags *pflag.FlagSet, opts *swarmOptions) { flags.Var(&opts.autoAccept, flagAutoAccept, "Auto acceptance policy (worker, manager or none)") - flags.StringVar(&opts.secret, flagSecret, "", "Set secret value needed to accept nodes into cluster") + flags.StringVar(&opts.secret, flagSecret, "", "Set secret value needed to join a cluster") flags.Int64Var(&opts.taskHistoryLimit, flagTaskHistoryLimit, 10, "Task history retention limit") flags.DurationVar(&opts.dispatcherHeartbeat, flagDispatcherHeartbeat, time.Duration(5*time.Second), "Dispatcher heartbeat period") flags.DurationVar(&opts.nodeCertExpiry, flagCertExpiry, time.Duration(90*24*time.Hour), "Validity period for node certificates") diff --git a/api/client/swarm/opts_test.go b/api/client/swarm/opts_test.go index d0390cfee5..a6dcdb5254 100644 --- a/api/client/swarm/opts_test.go +++ b/api/client/swarm/opts_test.go @@ -40,35 +40,51 @@ func TestNodeAddrOptionSetInvalidFormat(t *testing.T) { func TestAutoAcceptOptionSetWorker(t *testing.T) { opt := NewAutoAcceptOption() assert.NilError(t, opt.Set("worker")) - assert.Equal(t, opt.values[WORKER], true) + assert.Equal(t, opt.isPresent(worker), true) } func TestAutoAcceptOptionSetManager(t *testing.T) { opt := NewAutoAcceptOption() assert.NilError(t, opt.Set("manager")) - assert.Equal(t, opt.values[MANAGER], true) + assert.Equal(t, opt.isPresent(manager), true) } func TestAutoAcceptOptionSetInvalid(t *testing.T) { opt := NewAutoAcceptOption() - assert.Error(t, opt.Set("bogus"), "must be one of") + assert.Error(t, opt.Set("bogus"), "must be one / combination") +} + +func TestAutoAcceptOptionSetEmpty(t *testing.T) { + opt := NewAutoAcceptOption() + assert.Error(t, opt.Set(""), "must be one / combination") } func TestAutoAcceptOptionSetNone(t *testing.T) { opt := NewAutoAcceptOption() assert.NilError(t, opt.Set("none")) - assert.Equal(t, opt.values[MANAGER], false) - assert.Equal(t, opt.values[WORKER], false) + assert.Equal(t, opt.isPresent(manager), false) + assert.Equal(t, opt.isPresent(worker), false) +} + +func TestAutoAcceptOptionSetTwo(t *testing.T) { + opt := NewAutoAcceptOption() + assert.NilError(t, opt.Set("worker,manager")) + assert.Equal(t, opt.isPresent(manager), true) + assert.Equal(t, opt.isPresent(worker), true) } func TestAutoAcceptOptionSetConflict(t *testing.T) { opt := NewAutoAcceptOption() - assert.NilError(t, opt.Set("manager")) - assert.Error(t, opt.Set("none"), "value NONE is incompatible with MANAGER") + assert.Error(t, opt.Set("none,manager"), "value NONE cannot be specified alongside other node types") opt = NewAutoAcceptOption() - assert.NilError(t, opt.Set("none")) - assert.Error(t, opt.Set("worker"), "value NONE is incompatible with WORKER") + assert.Error(t, opt.Set("none,worker"), "value NONE cannot be specified alongside other node types") + + opt = NewAutoAcceptOption() + assert.Error(t, opt.Set("worker,none,manager"), "value NONE cannot be specified alongside other node types") + + opt = NewAutoAcceptOption() + assert.Error(t, opt.Set("worker,manager,none"), "value NONE cannot be specified alongside other node types") } func TestAutoAcceptOptionPoliciesDefault(t *testing.T) { @@ -78,12 +94,12 @@ func TestAutoAcceptOptionPoliciesDefault(t *testing.T) { policies := opt.Policies(&secret) assert.Equal(t, len(policies), 2) assert.Equal(t, policies[0], swarm.Policy{ - Role: WORKER, + Role: worker, Autoaccept: true, Secret: &secret, }) assert.Equal(t, policies[1], swarm.Policy{ - Role: MANAGER, + Role: manager, Autoaccept: false, Secret: &secret, }) @@ -98,12 +114,12 @@ func TestAutoAcceptOptionPoliciesWithManager(t *testing.T) { policies := opt.Policies(&secret) assert.Equal(t, len(policies), 2) assert.Equal(t, policies[0], swarm.Policy{ - Role: WORKER, + Role: worker, Autoaccept: false, Secret: &secret, }) assert.Equal(t, policies[1], swarm.Policy{ - Role: MANAGER, + Role: manager, Autoaccept: true, Secret: &secret, }) diff --git a/api/client/swarm/secret.go b/api/client/swarm/secret.go new file mode 100644 index 0000000000..e98f1d6626 --- /dev/null +++ b/api/client/swarm/secret.go @@ -0,0 +1,19 @@ +package swarm + +import ( + cryptorand "crypto/rand" + "fmt" + "math/big" +) + +func generateRandomSecret() string { + var secretBytes [generatedSecretEntropyBytes]byte + + if _, err := cryptorand.Read(secretBytes[:]); err != nil { + panic(fmt.Errorf("failed to read random bytes: %v", err)) + } + + var nn big.Int + nn.SetBytes(secretBytes[:]) + return fmt.Sprintf("%0[1]*s", maxGeneratedSecretLength, nn.Text(generatedSecretBase)) +} diff --git a/api/client/swarm/update.go b/api/client/swarm/update.go index cc7bcaa167..147dd0807f 100644 --- a/api/client/swarm/update.go +++ b/api/client/swarm/update.go @@ -47,7 +47,8 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts swarmOpti return err } - fmt.Println("Swarm updated.") + fmt.Fprintln(dockerCli.Out(), "Swarm updated.") + return nil } diff --git a/api/client/task/print.go b/api/client/task/print.go index 4909f159d5..bdb069ccf0 100644 --- a/api/client/task/print.go +++ b/api/client/task/print.go @@ -16,7 +16,7 @@ import ( ) const ( - psTaskItemFmt = "%s\t%s\t%s\t%s\t%s %s\t%s\t%s\n" + psTaskItemFmt = "%s\t%s\t%s\t%s\t%s %s ago\t%s\t%s\n" ) type tasksBySlot []swarm.Task @@ -69,7 +69,7 @@ func Print(dockerCli *client.DockerCli, ctx context.Context, tasks []swarm.Task, serviceValue, task.Spec.ContainerSpec.Image, client.PrettyPrint(task.Status.State), - units.HumanDuration(time.Since(task.Status.Timestamp)), + strings.ToLower(units.HumanDuration(time.Since(task.Status.Timestamp))), client.PrettyPrint(task.DesiredState), nodeValue, ) diff --git a/api/client/volume/remove.go b/api/client/volume/remove.go index 09bd17ff0c..f47c93ba46 100644 --- a/api/client/volume/remove.go +++ b/api/client/volume/remove.go @@ -33,7 +33,7 @@ func runRemove(dockerCli *client.DockerCli, volumes []string) error { status = 1 continue } - fmt.Fprintf(dockerCli.Err(), "%s\n", name) + fmt.Fprintf(dockerCli.Out(), "%s\n", name) } if status != 0 { diff --git a/api/common.go b/api/common.go index f83097c087..d62e65e8af 100644 --- a/api/common.go +++ b/api/common.go @@ -1,14 +1,18 @@ package api import ( + "encoding/json" + "encoding/pem" "fmt" "mime" + "os" "path/filepath" "sort" "strconv" "strings" "github.com/Sirupsen/logrus" + "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/system" "github.com/docker/engine-api/types" "github.com/docker/libtrust" @@ -135,7 +139,11 @@ func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) { if err != nil { return nil, fmt.Errorf("Error generating key: %s", err) } - if err := libtrust.SaveKey(trustKeyPath, trustKey); err != nil { + encodedKey, err := serializePrivateKey(trustKey, filepath.Ext(trustKeyPath)) + if err != nil { + return nil, fmt.Errorf("Error serializing key: %s", err) + } + if err := ioutils.AtomicWriteFile(trustKeyPath, encodedKey, os.FileMode(0600)); err != nil { return nil, fmt.Errorf("Error saving key file: %s", err) } } else if err != nil { @@ -143,3 +151,19 @@ func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) { } return trustKey, nil } + +func serializePrivateKey(key libtrust.PrivateKey, ext string) (encoded []byte, err error) { + if ext == ".json" || ext == ".jwk" { + encoded, err = json.Marshal(key) + if err != nil { + return nil, fmt.Errorf("unable to encode private key JWK: %s", err) + } + } else { + pemBlock, err := key.PEMBlock() + if err != nil { + return nil, fmt.Errorf("unable to encode private key PEM: %s", err) + } + encoded = pem.EncodeToMemory(pemBlock) + } + return +} diff --git a/api/server/middleware/debug.go b/api/server/middleware/debug.go index 6af8aa54d1..e0167f0a71 100644 --- a/api/server/middleware/debug.go +++ b/api/server/middleware/debug.go @@ -5,6 +5,7 @@ import ( "encoding/json" "io" "net/http" + "strings" "github.com/Sirupsen/logrus" "github.com/docker/docker/api/server/httputils" @@ -40,9 +41,7 @@ func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWri var postForm map[string]interface{} if err := json.Unmarshal(b, &postForm); err == nil { - if _, exists := postForm["password"]; exists { - postForm["password"] = "*****" - } + maskSecretKeys(postForm) formStr, errMarshal := json.Marshal(postForm) if errMarshal == nil { logrus.Debugf("form data: %s", string(formStr)) @@ -54,3 +53,24 @@ func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWri return handler(ctx, w, r, vars) } } + +func maskSecretKeys(inp interface{}) { + if arr, ok := inp.([]interface{}); ok { + for _, f := range arr { + maskSecretKeys(f) + } + return + } + if form, ok := inp.(map[string]interface{}); ok { + loop0: + for k, v := range form { + for _, m := range []string{"password", "secret"} { + if strings.EqualFold(m, k) { + form[k] = "*****" + continue loop0 + } + } + maskSecretKeys(v) + } + } +} diff --git a/api/server/router/container/backend.go b/api/server/router/container/backend.go index b3cc625ff2..444260af9f 100644 --- a/api/server/router/container/backend.go +++ b/api/server/router/container/backend.go @@ -32,17 +32,17 @@ type copyBackend interface { // stateBackend includes functions to implement to provide container state lifecycle functionality. type stateBackend interface { - ContainerCreate(types.ContainerCreateConfig) (types.ContainerCreateResponse, error) + ContainerCreate(config types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error) ContainerKill(name string, sig uint64) error ContainerPause(name string) error ContainerRename(oldName, newName string) error ContainerResize(name string, height, width int) error ContainerRestart(name string, seconds int) error ContainerRm(name string, config *types.ContainerRmConfig) error - ContainerStart(name string, hostConfig *container.HostConfig) error + ContainerStart(name string, hostConfig *container.HostConfig, validateHostname bool) error ContainerStop(name string, seconds int) error ContainerUnpause(name string) error - ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error) + ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) ([]string, error) ContainerWait(name string, timeout time.Duration) (int, error) } diff --git a/api/server/router/container/container_routes.go b/api/server/router/container/container_routes.go index cff1046baf..977ce2522d 100644 --- a/api/server/router/container/container_routes.go +++ b/api/server/router/container/container_routes.go @@ -132,10 +132,10 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon // including r.TransferEncoding // allow a nil body for backwards compatibility + version := httputils.VersionFromContext(ctx) var hostConfig *container.HostConfig // A non-nil json object is at least 7 characters. if r.ContentLength > 7 || r.ContentLength == -1 { - version := httputils.VersionFromContext(ctx) if versions.GreaterThanOrEqualTo(version, "1.24") { return validationError{fmt.Errorf("starting container with HostConfig was deprecated since v1.10 and removed in v1.12")} } @@ -151,7 +151,8 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon hostConfig = c } - if err := s.backend.ContainerStart(vars["name"], hostConfig); err != nil { + validateHostname := versions.GreaterThanOrEqualTo(version, "1.24") + if err := s.backend.ContainerStart(vars["name"], hostConfig, validateHostname); err != nil { return err } w.WriteHeader(http.StatusNoContent) @@ -311,6 +312,7 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon return err } + version := httputils.VersionFromContext(ctx) var updateConfig container.UpdateConfig decoder := json.NewDecoder(r.Body) @@ -324,7 +326,8 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon } name := vars["name"] - warnings, err := s.backend.ContainerUpdate(name, hostConfig) + validateHostname := versions.GreaterThanOrEqualTo(version, "1.24") + warnings, err := s.backend.ContainerUpdate(name, hostConfig, validateHostname) if err != nil { return err } @@ -351,13 +354,14 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo version := httputils.VersionFromContext(ctx) adjustCPUShares := versions.LessThan(version, "1.19") + validateHostname := versions.GreaterThanOrEqualTo(version, "1.24") ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{ Name: name, Config: config, HostConfig: hostConfig, NetworkingConfig: networkingConfig, AdjustCPUShares: adjustCPUShares, - }) + }, validateHostname) if err != nil { return err } diff --git a/api/server/router/network/network_routes.go b/api/server/router/network/network_routes.go index 7e5b94cb91..ebf2ce2872 100644 --- a/api/server/router/network/network_routes.go +++ b/api/server/router/network/network_routes.go @@ -81,6 +81,10 @@ func (n *networkRouter) postNetworkCreate(ctx context.Context, w http.ResponseWr return err } + if _, err := n.clusterProvider.GetNetwork(create.Name); err == nil { + return libnetwork.NetworkNameError(create.Name) + } + nw, err := n.backend.CreateNetwork(create) if err != nil { if _, ok := err.(libnetwork.ManagerRedirectError); !ok { diff --git a/builder/builder.go b/builder/builder.go index 65e7f02346..125e56ab22 100644 --- a/builder/builder.go +++ b/builder/builder.go @@ -116,7 +116,7 @@ type Backend interface { // ContainerAttachRaw attaches to container. ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool) error // ContainerCreate creates a new Docker container and returns potential warnings - ContainerCreate(types.ContainerCreateConfig) (types.ContainerCreateResponse, error) + ContainerCreate(config types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error) // ContainerRm removes a container specified by `id`. ContainerRm(name string, config *types.ContainerRmConfig) error // Commit creates a new Docker image from an existing Docker container. @@ -124,7 +124,7 @@ type Backend interface { // ContainerKill stops the container execution abruptly. ContainerKill(containerID string, sig uint64) error // ContainerStart starts a new container - ContainerStart(containerID string, hostConfig *container.HostConfig) error + ContainerStart(containerID string, hostConfig *container.HostConfig, validateHostname bool) error // ContainerWait stops processing until the given container is stopped. ContainerWait(containerID string, timeout time.Duration) (int, error) // ContainerUpdateCmdOnBuild updates container.Path and container.Args diff --git a/builder/dockerfile/internals.go b/builder/dockerfile/internals.go index a5a46e538a..50755f2642 100644 --- a/builder/dockerfile/internals.go +++ b/builder/dockerfile/internals.go @@ -181,7 +181,7 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD return nil } - container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: b.runConfig}) + container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: b.runConfig}, true) if err != nil { return err } @@ -421,7 +421,7 @@ func (b *Builder) processImageFrom(img builder.Image) error { fmt.Fprintf(b.Stderr, "# Executing %d build %s...\n", nTriggers, word) } - // Copy the ONBUILD triggers, and remove them from the config, since the config will be committed. + // Copy the ONBUILD triggers, and remove them from the config, since the config will be comitted. onBuildTriggers := b.runConfig.OnBuild b.runConfig.OnBuild = []string{} @@ -508,7 +508,7 @@ func (b *Builder) create() (string, error) { c, err := b.docker.ContainerCreate(types.ContainerCreateConfig{ Config: b.runConfig, HostConfig: hostConfig, - }) + }, true) if err != nil { return "", err } @@ -552,7 +552,7 @@ func (b *Builder) run(cID string) (err error) { } }() - if err := b.docker.ContainerStart(cID, nil); err != nil { + if err := b.docker.ContainerStart(cID, nil, true); err != nil { return err } diff --git a/cli/required.go b/cli/required.go index 9276a5740a..8ee02c8429 100644 --- a/cli/required.go +++ b/cli/required.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" ) -// NoArgs validate args and returns an error if there are any args +// NoArgs validates args and returns an error if there are any args func NoArgs(cmd *cobra.Command, args []string) error { if len(args) == 0 { return nil diff --git a/container/state.go b/container/state.go index 3922897165..081d91f41e 100644 --- a/container/state.go +++ b/container/state.go @@ -195,7 +195,7 @@ func (s *State) ExitCode() int { return res } -// SetExitCode set current exitcode for the state. Take lock before if state +// SetExitCode sets current exitcode for the state. Take lock before if state // may be shared. func (s *State) SetExitCode(ec int) { s.exitCode = ec @@ -214,7 +214,7 @@ func (s *State) SetRunning(pid int, initial bool) { } } -// SetStoppedLocking locks the container state is sets it to "stopped". +// SetStoppedLocking locks the container state and sets it to "stopped". func (s *State) SetStoppedLocking(exitStatus *ExitStatus) { s.Lock() s.SetStopped(exitStatus) @@ -290,7 +290,7 @@ func (s *State) SetRemovalInProgress() bool { return false } -// ResetRemovalInProgress make the RemovalInProgress state to false. +// ResetRemovalInProgress makes the RemovalInProgress state to false. func (s *State) ResetRemovalInProgress() { s.Lock() s.RemovalInProgress = false diff --git a/contrib/completion/bash/docker b/contrib/completion/bash/docker index 272ee41701..f9b6e26242 100644 --- a/contrib/completion/bash/docker +++ b/contrib/completion/bash/docker @@ -21,6 +21,8 @@ # setting environment variables. # # DOCKER_COMPLETION_SHOW_NETWORK_IDS +# DOCKER_COMPLETION_SHOW_NODE_IDS +# DOCKER_COMPLETION_SHOW_SERVICE_IDS # "no" - Show names only (default) # "yes" - Show names and ids # @@ -197,53 +199,84 @@ __docker_complete_runtimes() { COMPREPLY=( $(compgen -W "$(__docker_runtimes)" -- "$cur") ) } +# Returns a list of all nodes. Additional arguments to `docker node` +# may be specified in order to filter the node list, e.g. +# `__docker_nodes --filter role=manager` +# By default, only node names are completed. +# Set DOCKER_COMPLETION_SHOW_NODE_IDS=yes to also complete node IDs. +# An optional first argument `--id|--name` may be used to limit +# the output to the IDs or names of matching nodes. This setting takes +# precedence over the environment setting. __docker_nodes() { - local fields='$1,$2' # node names & IDs - __docker_q node ls | sed -e 's/\*//g' | awk "NR>1 {print $fields}" + local fields='$2' # default: node name only + [ "${DOCKER_COMPLETION_SHOW_NODE_IDS}" = yes ] && fields='$1,$2' # ID and name + + if [ "$1" = "--id" ] ; then + fields='$1' # IDs only + shift + elif [ "$1" = "--name" ] ; then + fields='$2' # names only + shift + fi + __docker_q node ls "$@" | tr -d '*' | awk "NR>1 {print $fields}" } +# Applies completion of nodes based on the current value of `$cur` or +# the value of the optional first argument `--cur`, if given. +# Additional filters may be appended, see `__docker_nodes`. __docker_complete_nodes() { - COMPREPLY=( $(compgen -W "$(__docker_nodes $1)" -- "$cur") ) + local current=$cur + if [ "$1" = "--cur" ] ; then + current="$2" + shift 2 + fi + COMPREPLY=( $(compgen -W "$(__docker_nodes "$@")" -- "$current") ) } __docker_complete_nodes_plus_self() { - COMPREPLY=( $(compgen -W "$(__docker_nodes $1) self" -- "$cur") ) -} - -__docker_pending_nodes() { - local fields='$1' # node ID - __docker_q node ls --filter membership=pending | awk "NR>1 {print $fields}" -} - -__docker_complete_pending_nodes() { - COMPREPLY=( $(compgen -W "$(__docker_pending_nodes $1)" -- "$cur") ) -} - -__docker_manager_nodes() { - local fields='$1,$2' # node names & IDs - __docker_q node ls --filter role=manager | awk "NR>1 {print $fields}" -} - -__docker_complete_manager_nodes() { - COMPREPLY=( $(compgen -W "$(__docker_manager_nodes $1)" -- "$cur") ) -} - -__docker_worker_nodes() { - local fields='$1,$2' # node names & IDs - __docker_q node ls --filter role=worker | awk "NR>1 {print $fields}" -} - -__docker_complete_worker_nodes() { - COMPREPLY=( $(compgen -W "$(__docker_worker_nodes $1)" -- "$cur") ) + __docker_complete_nodes "$@" + COMPREPLY+=( self ) } +# Returns a list of all services. Additional arguments to `docker service ls` +# may be specified in order to filter the service list, e.g. +# `__docker_services --filter name=xxx` +# By default, only node names are completed. +# Set DOCKER_COMPLETION_SHOW_SERVICE_IDS=yes to also complete service IDs. +# An optional first argument `--id|--name` may be used to limit +# the output to the IDs or names of matching services. This setting takes +# precedence over the environment setting. __docker_services() { - local fields='$1,$2' # service names & IDs - __docker_q service ls | awk "NR>1 {print $fields}" + local fields='$2' # default: service name only + [ "${DOCKER_COMPLETION_SHOW_SERVICE_IDS}" = yes ] && fields='$1,$2' # ID & name + + if [ "$1" = "--id" ] ; then + fields='$1' # IDs only + shift + elif [ "$1" = "--name" ] ; then + fields='$2' # names only + shift + fi + __docker_q service ls "$@" | awk "NR>1 {print $fields}" } +# Applies completion of services based on the current value of `$cur` or +# the value of the optional first argument `--cur`, if given. +# Additional filters may be appended, see `__docker_services`. __docker_complete_services() { - COMPREPLY=( $(compgen -W "$(__docker_services $1)" -- "$cur") ) + local current=$cur + if [ "$1" = "--cur" ] ; then + current="$2" + shift 2 + fi + COMPREPLY=( $(compgen -W "$(__docker_services "$@")" -- "$current") ) +} + +# Appends the word passed as an argument to every word in `$COMPREPLY`. +# Normally you do this with `compgen -S`. This function exists so that you can use +# the __docker_complete_XXX functions in cases where you need a suffix. +__docker_append_to_completions() { + COMPREPLY=( ${COMPREPLY[@]/%/"$1"} ) } # Finds the position of the first word that is neither option nor an option's argument. @@ -1579,15 +1612,29 @@ _docker_service_list() { } _docker_service_ls() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + id) + __docker_complete_services --cur "${cur##*=}" --id + return + ;; + name) + __docker_complete_services --cur "${cur##*=}" --name + return + ;; + esac + case "$prev" in - --format|-f) + --filter|-f) + COMPREPLY=( $( compgen -W "id label name" -S = -- "$cur" ) ) + __docker_nospace return ;; esac case "$cur" in -*) - COMPREPLY=( $( compgen -W "-f --filter --help --quiet -q" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--filter -f --help --quiet -q" -- "$cur" ) ) ;; esac } @@ -1612,15 +1659,30 @@ _docker_service_scale() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - COMPREPLY=( $(compgen -S "=" -W "$(__docker_services $1)" -- "$cur") ) + __docker_complete_services + __docker_append_to_completions "=" __docker_nospace ;; esac } _docker_service_tasks() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + desired-state) + COMPREPLY=( $( compgen -W "accepted running" -- "${cur##*=}" ) ) + return + ;; + name) + __docker_complete_services --cur "${cur##*=}" --name + return + ;; + esac + case "$prev" in - --format|-f) + --filter|-f) + COMPREPLY=( $( compgen -W "desired-state id name" -S = -- "$cur" ) ) + __docker_nospace return ;; esac @@ -1630,7 +1692,11 @@ _docker_service_tasks() { COMPREPLY=( $( compgen -W "--all -a --filter -f --help --no-resolve -n" -- "$cur" ) ) ;; *) - __docker_complete_services + local counter=$(__docker_pos_first_nonflag '--filter|-f') + if [ $cword -eq $counter ]; then + __docker_complete_services + fi + ;; esac } @@ -1701,7 +1767,7 @@ _docker_service_update() { return ;; --restart-condition) - COMPREPLY=( $( compgen -W "any none on_failure" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "any none on-failure" -- "$cur" ) ) return ;; --user|-u) @@ -1750,7 +1816,13 @@ _docker_swarm_init() { COMPREPLY=( $( compgen -W "manager none worker" -- "$cur" ) ) return ;; - --listen-addr|--secret) + --listen-addr) + if [[ $cur == *: ]] ; then + COMPREPLY=( $( compgen -W "2377" -- "${cur##*:}" ) ) + fi + return + ;; + --secret) return ;; esac @@ -1778,7 +1850,13 @@ _docker_swarm_inspect() { _docker_swarm_join() { case "$prev" in - --ca-hash|--listen-addr|--secret) + --ca-hash|--secret) + return + ;; + --listen-addr) + if [[ $cur == *: ]] ; then + COMPREPLY=( $( compgen -W "2377" -- "${cur##*:}" ) ) + fi return ;; esac @@ -1787,6 +1865,9 @@ _docker_swarm_join() { -*) COMPREPLY=( $( compgen -W "--ca-hash --help --listen-addr --manager --secret" -- "$cur" ) ) ;; + *:) + COMPREPLY=( $( compgen -W "2377" -- "${cur##*:}" ) ) + ;; esac } @@ -1845,7 +1926,7 @@ _docker_node_accept() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_complete_pending_nodes + __docker_complete_nodes --id --filter membership=pending esac } @@ -1855,7 +1936,7 @@ _docker_node_demote() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_complete_manager_nodes + __docker_complete_nodes --filter role=manager esac } @@ -1880,8 +1961,22 @@ _docker_node_list() { } _docker_node_ls() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + id) + __docker_complete_nodes --cur "${cur##*=}" --id + return + ;; + name) + __docker_complete_nodes --cur "${cur##*=}" --name + return + ;; + esac + case "$prev" in --filter|-f) + COMPREPLY=( $( compgen -W "id label name" -S = -- "$cur" ) ) + __docker_nospace return ;; esac @@ -1899,7 +1994,7 @@ _docker_node_promote() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_complete_worker_nodes + __docker_complete_nodes --filter role=worker esac } @@ -1918,8 +2013,22 @@ _docker_node_rm() { } _docker_node_tasks() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + desired-state) + COMPREPLY=( $( compgen -W "accepted running" -- "${cur##*=}" ) ) + return + ;; + name) + __docker_complete_services --cur "${cur##*=}" --name + return + ;; + esac + case "$prev" in --filter|-f) + COMPREPLY=( $( compgen -W "desired-state id label name" -S = -- "$cur" ) ) + __docker_nospace return ;; esac @@ -1929,7 +2038,11 @@ _docker_node_tasks() { COMPREPLY=( $( compgen -W "--all -a --filter -f --help --no-resolve -n" -- "$cur" ) ) ;; *) - __docker_complete_nodes_plus_self + local counter=$(__docker_pos_first_nonflag '--filter|-f') + if [ $cword -eq $counter ]; then + __docker_complete_nodes_plus_self + fi + ;; esac } diff --git a/contrib/completion/zsh/_docker b/contrib/completion/zsh/_docker index beec0594fc..e020ddb182 100644 --- a/contrib/completion/zsh/_docker +++ b/contrib/completion/zsh/_docker @@ -299,6 +299,17 @@ __docker_complete_pid() { return ret } +__docker_complete_runtimes() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + emulate -L zsh + setopt extendedglob + local -a runtimes_opts + runtimes_opts=(${(ps: :)${(f)${${"$(_call_program commands docker $docker_options info)"##*$'\n'Runtimes: }%%$'\n'^ *}}}) + _describe -t runtimes-opts "runtimes options" runtimes_opts && ret=0 +} + __docker_complete_ps_filters() { [[ $PREFIX = -* ]] && return 1 integer ret=1 @@ -630,6 +641,602 @@ __docker_network_subcommand() { return ret } +# BO node + +__docker_node_complete_ls_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (id) + __docker_complete_nodes_ids && ret=0 + ;; + (membership) + membership_opts=('accepted' 'pending' 'rejected') + _describe -t membership-opts "membership options" membership_opts && ret=0 + ;; + (name) + __docker_complete_nodes_names && ret=0 + ;; + (role) + role_opts=('manager' 'worker') + _describe -t role-opts "role options" role_opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('id' 'label' 'membership' 'name' 'role') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_node_complete_tasks_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (desired-state) + state_opts=('accepted' 'running') + _describe -t state-opts "desired state options" state_opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('desired-state' 'id' 'label' 'name') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_nodes() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local line s + declare -a lines nodes args + + type=$1; shift + filter=$1; shift + [[ $filter != "none" ]] && args=("-f $filter") + + lines=(${(f)"$(_call_program commands docker $docker_options node ls $args)"}) + + # 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]}) + + # Node ID + if [[ $type = (ids|all) ]]; then + for line in $lines; do + s="${line[${begin[ID]},${end[ID]}]%% ##}" + nodes=($nodes $s) + done + fi + + # Names + if [[ $type = (names|all) ]]; then + for line in $lines; do + s="${line[${begin[NAME]},${end[NAME]}]%% ##}" + nodes=($nodes $s) + done + fi + + _describe -t nodes-list "nodes" nodes "$@" && ret=0 + return ret +} + +__docker_complete_nodes() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes all none "$@" +} + +__docker_complete_nodes_ids() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes ids none "$@" +} + +__docker_complete_nodes_names() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes names none "$@" +} + +__docker_complete_pending_nodes() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes all "membership=pending" "$@" +} + +__docker_complete_manager_nodes() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes all "role=manager" "$@" +} + +__docker_complete_worker_nodes() { + [[ $PREFIX = -* ]] && return 1 + __docker_nodes all "role=worker" "$@" +} + +__docker_node_commands() { + local -a _docker_node_subcommands + _docker_node_subcommands=( + "accept:Accept a node in the swarm" + "demote:Demote a node as manager in the swarm" + "inspect:Display detailed information on one or more nodes" + "ls:List nodes in the swarm" + "promote:Promote a node as manager in the swarm" + "rm:Remove a node from the swarm" + "tasks:List tasks running on a node" + "update:Update a node" + ) + _describe -t docker-node-commands "docker node command" _docker_node_subcommands +} + +__docker_node_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (accept|rm|remove) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:node:__docker_complete_pending_nodes" && ret=0 + ;; + (demote) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:node:__docker_complete_manager_nodes" && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " \ + "($help -p --pretty)"{-p,--pretty}"[Print the information in a human friendly format]" \ + "($help -)*:node:__docker_complete_nodes" && ret=0 + ;; + (ls|list) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*"{-f=,--filter=}"[Provide filter values]:filter:->filter-options" \ + "($help -q --quiet)"{-q,--quiet}"[Only display IDs]" && ret=0 + case $state in + (filter-options) + __docker_node_complete_ls_filters && ret=0 + ;; + esac + ;; + (promote) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:node:__docker_complete_worker_nodes" && ret=0 + ;; + (tasks) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all)"{-a,--all}"[Display all instances]" \ + "($help)*"{-f=,--filter=}"[Provide filter values]:filter:->filter-options" \ + "($help -n --no-resolve)"{-n,--no-resolve}"[Do not map IDs to Names]" \ + "($help -)1:node:__docker_complete_nodes" && ret=0 + case $state in + (filter-options) + __docker_node_complete_tasks_filters && ret=0 + ;; + esac + ;; + (update) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--availability=[Availability of the node]:availability:(active pause drain)" \ + "($help)--membership=[Membership of the node]:membership:(accepted rejected)" \ + "($help)--role=[Role of the node]:role:(manager worker)" \ + "($help -)1:node:__docker_complete_nodes" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_node_commands" && ret=0 + ;; + esac + + return ret +} + +# EO node + +# BO plugin + +__docker_complete_plugins() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local line s + declare -a lines plugins + + lines=(${(f)"$(_call_program commands docker $docker_options plugin ls)"}) + + # 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]}) + + # Name + for line in $lines; do + s="${line[${begin[NAME]},${end[NAME]}]%% ##}" + s="$s:${(l:7:: :::)${${line[${begin[TAG]},${end[TAG]}]}%% ##}}" + plugins=($plugins $s) + done + + _describe -t plugins-list "plugins" plugins "$@" && ret=0 + return ret +} + +__docker_plugin_commands() { + local -a _docker_plugin_subcommands + _docker_plugin_subcommands=( + "disable:Disable a plugin" + "enable:Enable a plugin" + "inspect:Return low-level information about a plugin" + "install:Install a plugin" + "ls:List plugins" + "push:Push a plugin" + "rm:Remove a plugin" + "set:Change settings for a plugin" + ) + _describe -t docker-plugin-commands "docker plugin command" _docker_plugin_subcommands +} + +__docker_plugin_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (disable|enable|inspect|install|ls|push|rm) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)1:plugin:__docker_complete_plugins" && ret=0 + ;; + (set) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)1:plugin:__docker_complete_plugins" \ + "($help-)*:key=value: " && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_plugin_commands" && ret=0 + ;; + esac + + return ret +} + +# EO plugin + +# BO service + +__docker_service_complete_ls_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (id) + __docker_complete_services_ids && ret=0 + ;; + (name) + __docker_complete_services_names && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('id' 'label' 'name') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_service_complete_tasks_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (desired-state) + state_opts=('accepted' 'running') + _describe -t state-opts "desired state options" state_opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('desired-state' 'id' 'label' 'name') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_services() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local line s + declare -a lines services + + type=$1; shift + + lines=(${(f)"$(_call_program commands docker $docker_options service ls)"}) + + # 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]}) + + # Service ID + if [[ $type = (ids|all) ]]; then + for line in $lines; do + s="${line[${begin[ID]},${end[ID]}]%% ##}" + s="$s:${(l:7:: :::)${${line[${begin[IMAGE]},${end[IMAGE]}]}%% ##}}" + services=($services $s) + done + fi + + # Names + if [[ $type = (names|all) ]]; then + for line in $lines; do + s="${line[${begin[NAME]},${end[NAME]}]%% ##}" + s="$s:${(l:7:: :::)${${line[${begin[IMAGE]},${end[IMAGE]}]}%% ##}}" + services=($services $s) + done + fi + + _describe -t services-list "services" services "$@" && ret=0 + return ret +} + +__docker_complete_services() { + [[ $PREFIX = -* ]] && return 1 + __docker_services all "$@" +} + +__docker_complete_services_ids() { + [[ $PREFIX = -* ]] && return 1 + __docker_services ids "$@" +} + +__docker_complete_services_names() { + [[ $PREFIX = -* ]] && return 1 + __docker_services names "$@" +} + +__docker_service_commands() { + local -a _docker_service_subcommands + _docker_service_subcommands=( + "create:Create a new service" + "inspect:Display detailed information on one or more services" + "ls:List services" + "rm:Remove a service" + "scale:Scale one or multiple services" + "tasks:List the tasks of a service" + "update:Update a service" + ) + _describe -t docker-service-commands "docker service command" _docker_service_subcommands +} + +__docker_service_subcommand() { + local -a _command_args opts_help opts_create_update + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + opts_create_update=( + "($help)*--constraint=[Placement constraints]:constraint: " + "($help)--endpoint-mode=[Placement constraints]:mode:(VIP DNSRR)" + "($help)*"{-e=,--env=}"[Set environment variables]:env: " + "($help)*--label=[Service labels]:label: " + "($help)--limit-cpu=[Limit CPUs]:value: " + "($help)--limit-memory=[Limit Memory]:value: " + "($help)--mode=[Limit Memory]:mode:(global replicated)" + "($help)*"{-m=,--mount=}"[Attach a mount to the service]:mount: " + "($help)--name=[Service name]:name: " + "($help)*--network=[Network attachments]:network: " + "($help)*"{-p=,--publish=}"[Publish a port as a node port]:port: " + "($help)--replicas=[Number of tasks]:replicas: " + "($help)--reserve-cpu=[Reserve CPUs]:value: " + "($help)--reserve-memory=[Reserve Memory]:value: " + "($help)--restart-condition=[Restart when condition is met]:mode:(any none on-failure)" + "($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)--stop-grace-period=[Time to wait before force killing a container]:grace period: " + "($help)--update-delay=[Delay between updates]:delay: " + "($help)--update-parallelism=[Maximum number of tasks updated simultaneously]:number: " + "($help -u --user)"{-u=,--user=}"[Username or UID]:user:_users" + "($help -w --workdir)"{-w=,--workdir=}"[Working directory inside the container]:directory:_directories" + ) + + case "$words[1]" in + (create) + _arguments $(__docker_arguments) \ + $opts_help \ + $opts_create_update \ + "($help -): :__docker_images" \ + "($help -):command: _command_names -e" \ + "($help -)*::arguments: _normal" && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " \ + "($help -p --pretty)"{-p,--pretty}"[Print the information in a human friendly format]" \ + "($help -)*:service:__docker_complete_services" && ret=0 + ;; + (ls|list) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*"{-f=,--filter=}"[Filter output based on conditions provided]:filter:->filter-options" \ + "($help -q --quiet)"{-q,--quiet}"[Only display IDs]" && ret=0 + case $state in + (filter-options) + __docker_service_complete_ls_filters && ret=0 + ;; + esac + ;; + (rm|remove) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:service:__docker_complete_services" && ret=0 + ;; + (scale) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -)*:service:->values" && ret=0 + case $state in + (values) + if compset -P '*='; then + _message 'replicas' && ret=0 + else + __docker_complete_services -qS "=" + fi + ;; + esac + ;; + (tasks) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all)"{-a,--all}"[Display all tasks]" \ + "($help)*"{-f=,--filter=}"[Provide filter values]:filter:->filter-options" \ + "($help -n --no-resolve)"{-n,--no-resolve}"[Do not map IDs to Names]" \ + "($help -)1:service:__docker_complete_services" && ret=0 + case $state in + (filter-options) + __docker_service_complete_tasks_filters && ret=0 + ;; + esac + ;; + (update) + _arguments $(__docker_arguments) \ + $opts_help \ + $opts_create_update \ + "($help)--arg=[Service command args]:arguments: _normal" \ + "($help)--command=[Service command]:command: _command_names -e" \ + "($help)--image=[Service image tag]:image:__docker_repositories" \ + "($help -)1:service:__docker_complete_services" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_service_commands" && ret=0 + ;; + esac + + return ret +} + +# EO service + +# BO swarm + +__docker_swarm_commands() { + local -a _docker_swarm_subcommands + _docker_swarm_subcommands=( + "init:Initialize a Swarm" + "inspect:Inspect the Swarm" + "join:Join a Swarm as a node and/or manager" + "leave:Leave a Swarm" + "update:Update the Swarm" + ) + _describe -t docker-swarm-commands "docker swarm command" _docker_swarm_subcommands +} + +__docker_swarm_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (init) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--auto-accept=[Acceptance policy]:policy:(manager none worker)" \ + "($help)*--external-ca=[Specifications of one or more certificate signing endpoints]:endpoint: " \ + "($help)--force-new-cluster[Force create a new cluster from current state]" \ + "($help)--listen-addr[Listen address]:ip\:port: " \ + "($help)--secret[Set secret value needed to accept nodes into cluster]:secret: " && ret=0 + ;; + (inspect) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -f --format)"{-f=,--format=}"[Format the output using the given go template]:template: " && ret=0 + ;; + (join) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--ca-hash=[Hash of the Root Certificate Authority certificate used for trusted join]:hash: " \ + "($help)--listen-addr[Listen address]:ip\:port: " \ + "($help)--manager[Try joining as a manager]" \ + "($help)--secret[Secret for node acceptance]:secret: " \ + "($help -):host\:port: " && ret=0 + ;; + (leave) + _arguments $(__docker_arguments) \ + $opts_help && ret=0 + ;; + (update) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--auto-accept=[Acceptance policy]:policy:(manager none worker)" \ + "($help)--cert-expiry=[Validity period for node certificates]:duration: " \ + "($help)--dispatcher-heartbeat=[Dispatcher heartbeat period]:duration: " \ + "($help)--secret[Set secret value needed to accept nodes into cluster]:secret: " \ + "($help)--task-history-limit[Task history retention limit]:limit: " && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_network_commands" && ret=0 + ;; + esac + + return ret +} + +# EO swarm + __docker_volume_complete_ls_filters() { [[ $PREFIX = -* ]] && return 1 integer ret=1 @@ -933,6 +1540,7 @@ __docker_subcommand() { (daemon) _arguments $(__docker_arguments) \ $opts_help \ + "($help)*--add-runtime=[Register an additional OCI compatible runtime]:runtime:__docker_complete_runtimes" \ "($help)--api-cors-header=[CORS headers in the remote API]:CORS headers: " \ "($help)*--authorization-plugin=[Authorization plugins to load]" \ "($help -b --bridge)"{-b=,--bridge=}"[Attach containers to a network bridge]:bridge:_net_interfaces" \ @@ -1162,6 +1770,23 @@ __docker_subcommand() { ;; esac ;; + (node) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_node_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_node_subcommand && ret=0 + ;; + esac + ;; (pause|unpause) _arguments $(__docker_arguments) \ $opts_help \ @@ -1251,6 +1876,7 @@ __docker_subcommand() { "($help)--health-timeout=[Maximum time to allow one check to run]:time: " \ "($help)--no-healthcheck[Disable any container-specified HEALTHCHECK]" \ "($help)--rm[Remove intermediate containers when it exits]" \ + "($help)--runtime=[Name of the runtime to be used for that container]:runtime:__docker_complete_runtimes" \ "($help)--sig-proxy[Proxy all received signals to the process (non-TTY mode only)]" \ "($help)--stop-signal=[Signal to kill a container]:signal:_signals" \ "($help)--storage-opt=[Set storage driver options per container]:storage options:->storage-opt" \ @@ -1297,6 +1923,23 @@ __docker_subcommand() { ;; esac ;; + (service) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_service_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_service_subcommand && ret=0 + ;; + esac + ;; (start) _arguments $(__docker_arguments) \ $opts_help \ @@ -1312,6 +1955,23 @@ __docker_subcommand() { "($help)--no-stream[Disable streaming stats and only pull the first result]" \ "($help -)*:containers:__docker_runningcontainers" && ret=0 ;; + (swarm) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_swarm_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_swarm_subcommand && ret=0 + ;; + esac + ;; (tag) _arguments $(__docker_arguments) \ $opts_help \ diff --git a/contrib/init/systemd/docker.service b/contrib/init/systemd/docker.service index 92d72467e2..c3f3472472 100644 --- a/contrib/init/systemd/docker.service +++ b/contrib/init/systemd/docker.service @@ -11,8 +11,10 @@ Type=notify # for containers run by docker ExecStart=/usr/bin/dockerd -H fd:// ExecReload=/bin/kill -s HUP $MAINPID -LimitNOFILE=1048576 -LimitNPROC=1048576 +# Having non-zero Limit*s causes performance problems due to accounting overhead +# in the kernel. We recommend using cgroups to do container-local accounting. +LimitNOFILE=infinity +LimitNPROC=infinity LimitCORE=infinity # Uncomment TasksMax if your systemd version supports it. # Only systemd 226 and above support this version. diff --git a/daemon/cluster/cluster.go b/daemon/cluster/cluster.go index 7241cd4711..fa3ece8fa3 100644 --- a/daemon/cluster/cluster.go +++ b/daemon/cluster/cluster.go @@ -22,6 +22,7 @@ import ( "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/runconfig" apitypes "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/filters" types "github.com/docker/engine-api/types/swarm" swarmagent "github.com/docker/swarmkit/agent" swarmapi "github.com/docker/swarmkit/api" @@ -411,18 +412,18 @@ func (c *Cluster) Leave(force bool) error { if err == nil { if active && reachable-2 <= unreachable { if reachable == 1 && unreachable == 0 { - msg += "Leaving last manager will remove all current state of the cluster. Use `--force` to ignore this message. " + msg += "Removing the last manager will erase all current state of the cluster. Use `--force` to ignore this message. " c.Unlock() return fmt.Errorf(msg) } - msg += fmt.Sprintf("Leaving cluster will leave you with %v managers out of %v. This means Raft quorum will be lost and your cluster will become inaccessible. ", reachable-1, reachable+unreachable) + msg += fmt.Sprintf("Leaving the cluster will leave you with %v managers out of %v. This means Raft quorum will be lost and your cluster will become inaccessible. ", reachable-1, reachable+unreachable) } } } else { msg += "Doing so may lose the consensus of your cluster. " } - msg += "Only way to restore a cluster that has lost consensus is to reinitialize it with `--force-new-cluster`. Use `--force` to ignore this message." + msg += "The only way to restore a cluster that has lost consensus is to reinitialize it with `--force-new-cluster`. Use `--force` to ignore this message." c.Unlock() return fmt.Errorf(msg) } @@ -653,7 +654,7 @@ func (c *Cluster) GetServices(options apitypes.ServiceListOptions) ([]types.Serv return nil, err } - var services []types.Service + services := []types.Service{} for _, service := range r.Services { services = append(services, convert.ServiceFromGRPC(*service)) @@ -724,6 +725,13 @@ func (c *Cluster) UpdateService(serviceID string, version uint64, spec types.Ser return c.errNoManager() } + ctx := c.getRequestContext() + + err := populateNetworkID(ctx, c.client, &spec) + if err != nil { + return err + } + serviceSpec, err := convert.ServiceSpecToGRPC(spec) if err != nil { return err @@ -884,7 +892,33 @@ func (c *Cluster) GetTasks(options apitypes.TaskListOptions) ([]types.Task, erro return nil, c.errNoManager() } - filters, err := newListTasksFilters(options.Filter) + byName := func(filter filters.Args) error { + if filter.Include("service") { + serviceFilters := filter.Get("service") + for _, serviceFilter := range serviceFilters { + service, err := c.GetService(serviceFilter) + if err != nil { + return err + } + filter.Del("service", serviceFilter) + filter.Add("service", service.ID) + } + } + if filter.Include("node") { + nodeFilters := filter.Get("node") + for _, nodeFilter := range nodeFilters { + node, err := c.GetNode(nodeFilter) + if err != nil { + return err + } + filter.Del("node", nodeFilter) + filter.Add("node", node.ID) + } + } + return nil + } + + filters, err := newListTasksFilters(options.Filter, byName) if err != nil { return nil, err } @@ -1031,7 +1065,7 @@ func getNetwork(ctx context.Context, c swarmapi.ControlClient, input string) (*s } if l := len(rl.Networks); l > 1 { - return nil, fmt.Errorf("network %s is ambigious (%d matches found)", input, l) + return nil, fmt.Errorf("network %s is ambiguous (%d matches found)", input, l) } return rl.Networks[0], nil diff --git a/daemon/cluster/convert/container.go b/daemon/cluster/convert/container.go index c943537ad4..83cc5342bc 100644 --- a/daemon/cluster/convert/container.go +++ b/daemon/cluster/convert/container.go @@ -26,7 +26,7 @@ func containerSpecFromGRPC(c *swarmapi.ContainerSpec) types.ContainerSpec { Target: m.Target, Source: m.Source, Type: types.MountType(strings.ToLower(swarmapi.Mount_MountType_name[int32(m.Type)])), - Writable: m.Writable, + ReadOnly: m.ReadOnly, } if m.BindOptions != nil { @@ -37,8 +37,8 @@ func containerSpecFromGRPC(c *swarmapi.ContainerSpec) types.ContainerSpec { if m.VolumeOptions != nil { mount.VolumeOptions = &types.VolumeOptions{ - Populate: m.VolumeOptions.Populate, - Labels: m.VolumeOptions.Labels, + NoCopy: m.VolumeOptions.NoCopy, + Labels: m.VolumeOptions.Labels, } if m.VolumeOptions.DriverConfig != nil { mount.VolumeOptions.DriverConfig = &types.Driver{ @@ -77,7 +77,7 @@ func containerToGRPC(c types.ContainerSpec) (*swarmapi.ContainerSpec, error) { mount := swarmapi.Mount{ Target: m.Target, Source: m.Source, - Writable: m.Writable, + ReadOnly: m.ReadOnly, } if mountType, ok := swarmapi.Mount_MountType_value[strings.ToUpper(string(m.Type))]; ok { @@ -98,8 +98,8 @@ func containerToGRPC(c types.ContainerSpec) (*swarmapi.ContainerSpec, error) { if m.VolumeOptions != nil { mount.VolumeOptions = &swarmapi.Mount_VolumeOptions{ - Populate: m.VolumeOptions.Populate, - Labels: m.VolumeOptions.Labels, + NoCopy: m.VolumeOptions.NoCopy, + Labels: m.VolumeOptions.Labels, } if m.VolumeOptions.DriverConfig != nil { mount.VolumeOptions.DriverConfig = &swarmapi.Driver{ diff --git a/daemon/cluster/convert/service.go b/daemon/cluster/convert/service.go index 60df93a59e..912d601354 100644 --- a/daemon/cluster/convert/service.go +++ b/daemon/cluster/convert/service.go @@ -219,7 +219,8 @@ func restartPolicyToGRPC(p *types.RestartPolicy) (*swarmapi.RestartPolicy, error var rp *swarmapi.RestartPolicy if p != nil { rp = &swarmapi.RestartPolicy{} - if condition, ok := swarmapi.RestartPolicy_RestartCondition_value[strings.ToUpper(string(p.Condition))]; ok { + sanatizedCondition := strings.ToUpper(strings.Replace(string(p.Condition), "-", "_", -1)) + if condition, ok := swarmapi.RestartPolicy_RestartCondition_value[sanatizedCondition]; ok { rp.Condition = swarmapi.RestartPolicy_RestartCondition(condition) } else if string(p.Condition) == "" { rp.Condition = swarmapi.RestartOnAny diff --git a/daemon/cluster/convert/swarm.go b/daemon/cluster/convert/swarm.go index e9131a3f24..331c199c84 100644 --- a/daemon/cluster/convert/swarm.go +++ b/daemon/cluster/convert/swarm.go @@ -136,13 +136,13 @@ func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolic hashPwd, _ = bcrypt.GenerateFromPassword([]byte(*p.Secret), 0) hashs[*p.Secret] = hashPwd } - policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{ + policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_Secret{ Data: hashPwd, Alg: "bcrypt", } } } else if oldSecret := getOldSecret(oldSpec, policy.Role); oldSecret != nil { // else use the old one. - policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{ + policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_Secret{ Data: oldSecret.Data, Alg: oldSecret.Alg, } @@ -153,7 +153,7 @@ func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolic return nil } -func getOldSecret(oldSpec *swarmapi.ClusterSpec, role swarmapi.NodeRole) *swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret { +func getOldSecret(oldSpec *swarmapi.ClusterSpec, role swarmapi.NodeRole) *swarmapi.AcceptancePolicy_RoleAdmissionPolicy_Secret { if oldSpec == nil { return nil } diff --git a/daemon/cluster/executor/backend.go b/daemon/cluster/executor/backend.go index e23ebee343..3a4ff0fc1b 100644 --- a/daemon/cluster/executor/backend.go +++ b/daemon/cluster/executor/backend.go @@ -2,10 +2,13 @@ package executor import ( "io" + "time" clustertypes "github.com/docker/docker/daemon/cluster/provider" "github.com/docker/engine-api/types" "github.com/docker/engine-api/types/container" + "github.com/docker/engine-api/types/events" + "github.com/docker/engine-api/types/filters" "github.com/docker/engine-api/types/network" "github.com/docker/libnetwork/cluster" networktypes "github.com/docker/libnetwork/types" @@ -18,8 +21,8 @@ type Backend interface { DeleteManagedNetwork(name string) error SetupIngress(req clustertypes.NetworkCreateRequest, nodeIP string) error PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error - CreateManagedContainer(types.ContainerCreateConfig) (types.ContainerCreateResponse, error) - ContainerStart(name string, hostConfig *container.HostConfig) error + CreateManagedContainer(config types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error) + ContainerStart(name string, hostConfig *container.HostConfig, validateHostname bool) error ContainerStop(name string, seconds int) error ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error @@ -33,4 +36,6 @@ type Backend interface { SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error SetClusterProvider(provider cluster.Provider) IsSwarmCompatible() error + SubscribeToEvents(since, until time.Time, filter filters.Args) ([]events.Message, chan interface{}) + UnsubscribeFromEvents(listener chan interface{}) } diff --git a/daemon/cluster/executor/container/adapter.go b/daemon/cluster/executor/container/adapter.go index 9a959ae4cc..38ff63afc2 100644 --- a/daemon/cluster/executor/container/adapter.go +++ b/daemon/cluster/executor/container/adapter.go @@ -7,10 +7,14 @@ import ( "io" "strings" "syscall" + "time" "github.com/Sirupsen/logrus" + "github.com/docker/docker/api/server/httputils" executorpkg "github.com/docker/docker/daemon/cluster/executor" "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/events" + "github.com/docker/engine-api/types/versions" "github.com/docker/libnetwork" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" @@ -115,13 +119,16 @@ func (c *containerAdapter) removeNetworks(ctx context.Context) error { func (c *containerAdapter) create(ctx context.Context, backend executorpkg.Backend) error { var cr types.ContainerCreateResponse var err error + version := httputils.VersionFromContext(ctx) + validateHostname := versions.GreaterThanOrEqualTo(version, "1.24") + if cr, err = backend.CreateManagedContainer(types.ContainerCreateConfig{ Name: c.container.name(), Config: c.container.config(), HostConfig: c.container.hostConfig(), // Use the first network in container create NetworkingConfig: c.container.createNetworkingConfig(), - }); err != nil { + }, validateHostname); err != nil { return err } @@ -145,7 +152,9 @@ func (c *containerAdapter) create(ctx context.Context, backend executorpkg.Backe } func (c *containerAdapter) start(ctx context.Context) error { - return c.backend.ContainerStart(c.container.name(), nil) + version := httputils.VersionFromContext(ctx) + validateHostname := versions.GreaterThanOrEqualTo(version, "1.24") + return c.backend.ContainerStart(c.container.name(), nil, validateHostname) } func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, error) { @@ -161,9 +170,40 @@ func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, er // events issues a call to the events API and returns a channel with all // events. The stream of events can be shutdown by cancelling the context. -// -// A chan struct{} is returned that will be closed if the event processing -// fails and needs to be restarted. +func (c *containerAdapter) events(ctx context.Context) <-chan events.Message { + log.G(ctx).Debugf("waiting on events") + buffer, l := c.backend.SubscribeToEvents(time.Time{}, time.Time{}, c.container.eventFilter()) + eventsq := make(chan events.Message, len(buffer)) + + for _, event := range buffer { + eventsq <- event + } + + go func() { + defer c.backend.UnsubscribeFromEvents(l) + + for { + select { + case ev := <-l: + jev, ok := ev.(events.Message) + if !ok { + log.G(ctx).Warnf("unexpected event message: %q", ev) + continue + } + select { + case eventsq <- jev: + case <-ctx.Done(): + return + } + case <-ctx.Done(): + return + } + } + }() + + return eventsq +} + func (c *containerAdapter) wait(ctx context.Context) error { return c.backend.ContainerWaitWithContext(ctx, c.container.name()) } diff --git a/daemon/cluster/executor/container/container.go b/daemon/cluster/executor/container/container.go index 36a8cb246f..31782be6d4 100644 --- a/daemon/cluster/executor/container/container.go +++ b/daemon/cluster/executor/container/container.go @@ -13,6 +13,8 @@ import ( "github.com/docker/docker/reference" "github.com/docker/engine-api/types" enginecontainer "github.com/docker/engine-api/types/container" + "github.com/docker/engine-api/types/events" + "github.com/docker/engine-api/types/filters" "github.com/docker/engine-api/types/network" "github.com/docker/swarmkit/agent/exec" "github.com/docker/swarmkit/api" @@ -88,21 +90,6 @@ func (c *containerConfig) image() string { return reference.WithDefaultTag(ref).String() } -func (c *containerConfig) volumes() map[string]struct{} { - r := make(map[string]struct{}) - - for _, mount := range c.spec().Mounts { - // pick off all the volume mounts. - if mount.Type != api.MountTypeVolume { - continue - } - - r[fmt.Sprintf("%s:%s", mount.Target, getMountMask(&mount))] = struct{}{} - } - - return r -} - func (c *containerConfig) config() *enginecontainer.Config { config := &enginecontainer.Config{ Labels: c.labels(), @@ -160,26 +147,67 @@ func (c *containerConfig) labels() map[string]string { return labels } -func (c *containerConfig) bindMounts() []string { - var r []string - - for _, val := range c.spec().Mounts { - mask := getMountMask(&val) - if val.Type == api.MountTypeBind { - r = append(r, fmt.Sprintf("%s:%s:%s", val.Source, val.Target, mask)) +// volumes gets placed into the Volumes field on the containerConfig. +func (c *containerConfig) volumes() map[string]struct{} { + r := make(map[string]struct{}) + // Volumes *only* creates anonymous volumes. The rest is mixed in with + // binds, which aren't actually binds. Basically, any volume that + // results in a single component must be added here. + // + // This is reversed engineered from the behavior of the engine API. + for _, mount := range c.spec().Mounts { + if mount.Type == api.MountTypeVolume && mount.Source == "" { + r[mount.Target] = struct{}{} } } + return r +} + +func (c *containerConfig) tmpfs() map[string]string { + r := make(map[string]string) + + for _, spec := range c.spec().Mounts { + if spec.Type != api.MountTypeTmpfs { + continue + } + + r[spec.Target] = getMountMask(&spec) + } return r } +func (c *containerConfig) binds() []string { + var r []string + for _, mount := range c.spec().Mounts { + if mount.Type == api.MountTypeBind || (mount.Type == api.MountTypeVolume && mount.Source != "") { + spec := fmt.Sprintf("%s:%s", mount.Source, mount.Target) + mask := getMountMask(&mount) + if mask != "" { + spec = fmt.Sprintf("%s:%s", spec, mask) + } + r = append(r, spec) + } + } + return r +} + func getMountMask(m *api.Mount) string { - maskOpts := []string{"ro"} - if m.Writable { - maskOpts[0] = "rw" + var maskOpts []string + if m.ReadOnly { + maskOpts = append(maskOpts, "ro") } - if m.BindOptions != nil { + switch m.Type { + case api.MountTypeVolume: + if m.VolumeOptions != nil && m.VolumeOptions.NoCopy { + maskOpts = append(maskOpts, "nocopy") + } + case api.MountTypeBind: + if m.BindOptions == nil { + break + } + switch m.BindOptions.Propagation { case api.MountPropagationPrivate: maskOpts = append(maskOpts, "private") @@ -194,21 +222,66 @@ func getMountMask(m *api.Mount) string { case api.MountPropagationRSlave: maskOpts = append(maskOpts, "rslave") } - } + case api.MountTypeTmpfs: + if m.TmpfsOptions == nil { + break + } - if m.VolumeOptions != nil { - if !m.VolumeOptions.Populate { - maskOpts = append(maskOpts, "nocopy") + if m.TmpfsOptions.Mode != 0 { + maskOpts = append(maskOpts, fmt.Sprintf("mode=%o", m.TmpfsOptions.Mode)) + } + + if m.TmpfsOptions.SizeBytes != 0 { + // calculate suffix here, making this linux specific, but that is + // okay, since API is that way anyways. + + // we do this by finding the suffix that divides evenly into the + // value, returing the value itself, with no suffix, if it fails. + // + // For the most part, we don't enforce any semantic to this values. + // The operating system will usually align this and enforce minimum + // and maximums. + var ( + size = m.TmpfsOptions.SizeBytes + suffix string + ) + for _, r := range []struct { + suffix string + divisor int64 + }{ + {"g", 1 << 30}, + {"m", 1 << 20}, + {"k", 1 << 10}, + } { + if size%r.divisor == 0 { + size = size / r.divisor + suffix = r.suffix + break + } + } + + maskOpts = append(maskOpts, fmt.Sprintf("size=%d%s", size, suffix)) } } + return strings.Join(maskOpts, ",") } func (c *containerConfig) hostConfig() *enginecontainer.HostConfig { - return &enginecontainer.HostConfig{ + hc := &enginecontainer.HostConfig{ Resources: c.resources(), - Binds: c.bindMounts(), + Binds: c.binds(), + Tmpfs: c.tmpfs(), } + + if c.task.LogDriver != nil { + hc.LogConfig = enginecontainer.LogConfig{ + Type: c.task.LogDriver.Name, + Config: c.task.LogDriver.Options, + } + } + + return hc } // This handles the case of volumes that are defined inside a service Mount @@ -421,3 +494,11 @@ func (c *containerConfig) networkCreateRequest(name string) (clustertypes.Networ return clustertypes.NetworkCreateRequest{na.Network.ID, types.NetworkCreateRequest{Name: name, NetworkCreate: options}}, nil } + +func (c containerConfig) eventFilter() filters.Args { + filter := filters.NewArgs() + filter.Add("type", events.ContainerEventType) + filter.Add("name", c.name()) + filter.Add("label", fmt.Sprintf("%v.task.id=%v", systemLabelPrefix, c.task.ID)) + return filter +} diff --git a/daemon/cluster/executor/container/controller.go b/daemon/cluster/executor/container/controller.go index ddb65ae033..410d874caa 100644 --- a/daemon/cluster/executor/container/controller.go +++ b/daemon/cluster/executor/container/controller.go @@ -5,6 +5,7 @@ import ( executorpkg "github.com/docker/docker/daemon/cluster/executor" "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/events" "github.com/docker/swarmkit/agent/exec" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" @@ -150,20 +151,39 @@ func (r *controller) Wait(pctx context.Context) error { ctx, cancel := context.WithCancel(pctx) defer cancel() + healthErr := make(chan error, 1) + go func() { + ectx, cancel := context.WithCancel(ctx) // cancel event context on first event + defer cancel() + if err := r.checkHealth(ectx); err == ErrContainerUnhealthy { + healthErr <- ErrContainerUnhealthy + if err := r.Shutdown(ectx); err != nil { + log.G(ectx).WithError(err).Debug("shutdown failed on unhealthy") + } + } + }() + err := r.adapter.wait(ctx) if ctx.Err() != nil { return ctx.Err() } + if err != nil { ee := &exitError{} - if err.Error() != "" { - ee.cause = err - } if ec, ok := err.(exec.ExitCoder); ok { ee.code = ec.ExitCode() } + select { + case e := <-healthErr: + ee.cause = e + default: + if err.Error() != "" { + ee.cause = err + } + } return ee } + return nil } @@ -247,6 +267,21 @@ func (r *controller) Close() error { return nil } +func (r *controller) matchevent(event events.Message) bool { + if event.Type != events.ContainerEventType { + return false + } + + // TODO(stevvooe): Filter based on ID matching, in addition to name. + + // Make sure the events are for this container. + if event.Actor.Attributes["name"] != r.adapter.container.name() { + return false + } + + return true +} + func (r *controller) checkClosed() error { select { case <-r.closed: @@ -286,3 +321,26 @@ func (e *exitError) ExitCode() int { func (e *exitError) Cause() error { return e.cause } + +// checkHealth blocks until unhealthy container is detected or ctx exits +func (r *controller) checkHealth(ctx context.Context) error { + eventq := r.adapter.events(ctx) + + for { + select { + case <-ctx.Done(): + return nil + case <-r.closed: + return nil + case event := <-eventq: + if !r.matchevent(event) { + continue + } + + switch event.Action { + case "health_status: unhealthy": + return ErrContainerUnhealthy + } + } + } +} diff --git a/daemon/cluster/executor/container/errors.go b/daemon/cluster/executor/container/errors.go index 6c03d36071..63e1233566 100644 --- a/daemon/cluster/executor/container/errors.go +++ b/daemon/cluster/executor/container/errors.go @@ -9,4 +9,7 @@ var ( // ErrContainerDestroyed returned when a container is prematurely destroyed // during a wait call. ErrContainerDestroyed = fmt.Errorf("dockerexec: container destroyed") + + // ErrContainerUnhealthy returned if controller detects the health check failure + ErrContainerUnhealthy = fmt.Errorf("dockerexec: unhealthy container") ) diff --git a/daemon/cluster/executor/container/health_test.go b/daemon/cluster/executor/container/health_test.go new file mode 100644 index 0000000000..472624b54d --- /dev/null +++ b/daemon/cluster/executor/container/health_test.go @@ -0,0 +1,102 @@ +// +build !windows + +package container + +import ( + "testing" + "time" + + "github.com/docker/docker/container" + "github.com/docker/docker/daemon" + "github.com/docker/docker/daemon/events" + containertypes "github.com/docker/engine-api/types/container" + "github.com/docker/swarmkit/api" + "golang.org/x/net/context" +) + +func TestHealthStates(t *testing.T) { + + // set up environment: events, task, container .... + e := events.New() + _, l, _ := e.Subscribe() + defer e.Evict(l) + + task := &api.Task{ + ID: "id", + ServiceID: "sid", + Spec: api.TaskSpec{ + Runtime: &api.TaskSpec_Container{ + Container: &api.ContainerSpec{ + Image: "image_name", + Labels: map[string]string{ + "com.docker.swarm.task.id": "id", + }, + }, + }, + }, + Annotations: api.Annotations{Name: "name"}, + } + + c := &container.Container{ + CommonContainer: container.CommonContainer{ + ID: "id", + Name: "name", + Config: &containertypes.Config{ + Image: "image_name", + Labels: map[string]string{ + "com.docker.swarm.task.id": "id", + }, + }, + }, + } + + daemon := &daemon.Daemon{ + EventsService: e, + } + + controller, err := newController(daemon, task) + if err != nil { + t.Fatalf("create controller fail %v", err) + } + + errChan := make(chan error, 1) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // fire checkHealth + go func() { + err := controller.checkHealth(ctx) + select { + case errChan <- err: + case <-ctx.Done(): + } + }() + + // send an event and expect to get expectedErr + // if expectedErr is nil, shouldn't get any error + logAndExpect := func(msg string, expectedErr error) { + daemon.LogContainerEvent(c, msg) + + timer := time.NewTimer(1 * time.Second) + defer timer.Stop() + + select { + case err := <-errChan: + if err != expectedErr { + t.Fatalf("expect error %v, but get %v", expectedErr, err) + } + case <-timer.C: + if expectedErr != nil { + t.Fatalf("time limit exceeded, didn't get expected error") + } + } + } + + // events that are ignored by checkHealth + logAndExpect("health_status: running", nil) + logAndExpect("health_status: healthy", nil) + logAndExpect("die", nil) + + // unhealthy event will be caught by checkHealth + logAndExpect("health_status: unhealthy", ErrContainerUnhealthy) +} diff --git a/daemon/cluster/filters.go b/daemon/cluster/filters.go index 5890698d00..26fc65627e 100644 --- a/daemon/cluster/filters.go +++ b/daemon/cluster/filters.go @@ -61,18 +61,23 @@ func newListServicesFilters(filter filters.Args) (*swarmapi.ListServicesRequest_ }, nil } -func newListTasksFilters(filter filters.Args) (*swarmapi.ListTasksRequest_Filters, error) { +func newListTasksFilters(filter filters.Args, transformFunc func(filters.Args) error) (*swarmapi.ListTasksRequest_Filters, error) { accepted := map[string]bool{ "name": true, "id": true, "label": true, "service": true, "node": true, - "desired_state": true, + "desired-state": true, } if err := filter.Validate(accepted); err != nil { return nil, err } + if transformFunc != nil { + if err := transformFunc(filter); err != nil { + return nil, err + } + } f := &swarmapi.ListTasksRequest_Filters{ Names: filter.Get("name"), IDPrefixes: filter.Get("id"), @@ -81,11 +86,11 @@ func newListTasksFilters(filter filters.Args) (*swarmapi.ListTasksRequest_Filter NodeIDs: filter.Get("node"), } - for _, s := range filter.Get("desired_state") { + for _, s := range filter.Get("desired-state") { if state, ok := swarmapi.TaskState_value[strings.ToUpper(s)]; ok { f.DesiredStates = append(f.DesiredStates, swarmapi.TaskState(state)) } else if s != "" { - return nil, fmt.Errorf("Invalid desired_state filter: '%s'", s) + return nil, fmt.Errorf("Invalid desired-state filter: '%s'", s) } } diff --git a/daemon/cluster/helpers.go b/daemon/cluster/helpers.go index bb9e10f1f5..be5bf56e87 100644 --- a/daemon/cluster/helpers.go +++ b/daemon/cluster/helpers.go @@ -42,7 +42,7 @@ func getNode(ctx context.Context, c swarmapi.ControlClient, input string) (*swar } if l := len(rl.Nodes); l > 1 { - return nil, fmt.Errorf("node %s is ambigious (%d matches found)", input, l) + return nil, fmt.Errorf("node %s is ambiguous (%d matches found)", input, l) } return rl.Nodes[0], nil @@ -70,7 +70,7 @@ func getService(ctx context.Context, c swarmapi.ControlClient, input string) (*s } if l := len(rl.Services); l > 1 { - return nil, fmt.Errorf("service %s is ambigious (%d matches found)", input, l) + return nil, fmt.Errorf("service %s is ambiguous (%d matches found)", input, l) } return rl.Services[0], nil @@ -99,7 +99,7 @@ func getTask(ctx context.Context, c swarmapi.ControlClient, input string) (*swar } if l := len(rl.Tasks); l > 1 { - return nil, fmt.Errorf("task %s is ambigious (%d matches found)", input, l) + return nil, fmt.Errorf("task %s is ambiguous (%d matches found)", input, l) } return rl.Tasks[0], nil diff --git a/daemon/config.go b/daemon/config.go index 05537f3264..262918b328 100644 --- a/daemon/config.go +++ b/daemon/config.go @@ -271,7 +271,7 @@ func getConflictFreeConfiguration(configFile string, flags *flag.FlagSet) (*Conf } // Override flag values to make sure the values set in the config file with nullable values, like `false`, - // are not overriden by default truthy values from the flags that were not explicitly set. + // are not overridden by default truthy values from the flags that were not explicitly set. // See https://github.com/docker/docker/issues/20289 for an example. // // TODO: Rewrite configuration logic to avoid same issue with other nullable values, like numbers. diff --git a/daemon/container.go b/daemon/container.go index a2d1f47cda..b9f63dedde 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -203,7 +203,7 @@ func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig * // verifyContainerSettings performs validation of the hostconfig and config // structures. -func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) { +func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool, validateHostname bool) ([]string, error) { // First perform verification of settings common across all platforms. if config != nil { @@ -222,10 +222,10 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon } // Validate if the given hostname is RFC 1123 (https://tools.ietf.org/html/rfc1123) compliant. - if len(config.Hostname) > 0 { + if validateHostname && len(config.Hostname) > 0 { // RFC1123 specifies that 63 bytes is the maximium length // Windows has the limitation of 63 bytes in length - // Linux hostname is limited to HOST_NAME_MAX=64, not not including the terminating null byte. + // Linux hostname is limited to HOST_NAME_MAX=64, not including the terminating null byte. // We limit the length to 63 bytes here to match RFC1035 and RFC1123. matched, _ := regexp.MatchString("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$", config.Hostname) if len(config.Hostname) > 63 || !matched { diff --git a/daemon/container_operations.go b/daemon/container_operations.go index 3bd50fa31f..8c731ed0d2 100644 --- a/daemon/container_operations.go +++ b/daemon/container_operations.go @@ -328,7 +328,7 @@ func (daemon *Daemon) updateNetwork(container *container.Container) error { } func errClusterNetworkOnRun(n string) error { - return fmt.Errorf("swarm-scoped network (%s) is not compatible with `docker create` or `docker run`. This network can be only used docker service", n) + return fmt.Errorf("swarm-scoped network (%s) is not compatible with `docker create` or `docker run`. This network can only be used by a docker service", n) } // updateContainerNetworkSettings update the network settings diff --git a/daemon/create.go b/daemon/create.go index 48e7245916..13424f4755 100644 --- a/daemon/create.go +++ b/daemon/create.go @@ -20,21 +20,21 @@ import ( ) // CreateManagedContainer creates a container that is managed by a Service -func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig) (types.ContainerCreateResponse, error) { - return daemon.containerCreate(params, true) +func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error) { + return daemon.containerCreate(params, true, validateHostname) } // ContainerCreate creates a regular container -func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (types.ContainerCreateResponse, error) { - return daemon.containerCreate(params, false) +func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig, validateHostname bool) (types.ContainerCreateResponse, error) { + return daemon.containerCreate(params, false, validateHostname) } -func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, managed bool) (types.ContainerCreateResponse, error) { +func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, managed bool, validateHostname bool) (types.ContainerCreateResponse, error) { if params.Config == nil { return types.ContainerCreateResponse{}, fmt.Errorf("Config cannot be empty in order to create a container") } - warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false) + warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false, validateHostname) if err != nil { return types.ContainerCreateResponse{Warnings: warnings}, err } diff --git a/daemon/daemon.go b/daemon/daemon.go index 26b62489e6..32122bb47e 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -324,7 +324,7 @@ func (daemon *Daemon) waitForNetworks(c *container.Container) { } // Make sure if the container has a network that requires discovery that the discovery service is available before starting for netName := range c.NetworkSettings.Networks { - // If we get `ErrNoSuchNetwork` here, it can assumed that it is due to discovery not being ready + // If we get `ErrNoSuchNetwork` here, we can assume that it is due to discovery not being ready // Most likely this is because the K/V store used for discovery is in a container and needs to be started if _, err := daemon.netController.NetworkByName(netName); err != nil { if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok { @@ -365,7 +365,7 @@ func (daemon *Daemon) registerLink(parent, child *container.Container, alias str return nil } -// SetClusterProvider sets a component for quering the current cluster state. +// SetClusterProvider sets a component for querying the current cluster state. func (daemon *Daemon) SetClusterProvider(clusterProvider cluster.Provider) { daemon.clusterProvider = clusterProvider daemon.netController.SetClusterProvider(clusterProvider) @@ -611,10 +611,10 @@ func (daemon *Daemon) shutdownContainer(c *container.Container) error { // To terminate a process in freezer cgroup, we should send // SIGTERM to this process then unfreeze it, and the process will // force to terminate immediately. - logrus.Debugf("Found container %s is paused, sending SIGTERM before unpause it", c.ID) + logrus.Debugf("Found container %s is paused, sending SIGTERM before unpausing it", c.ID) sig, ok := signal.SignalMap["TERM"] if !ok { - return fmt.Errorf("System doesn not support SIGTERM") + return fmt.Errorf("System does not support SIGTERM") } if err := daemon.kill(c, int(sig)); err != nil { return fmt.Errorf("sending SIGTERM to container %s with error: %v", c.ID, err) @@ -623,7 +623,7 @@ func (daemon *Daemon) shutdownContainer(c *container.Container) error { return fmt.Errorf("Failed to unpause container %s with error: %v", c.ID, err) } if _, err := c.WaitStop(10 * time.Second); err != nil { - logrus.Debugf("container %s failed to exit in 10 second of SIGTERM, sending SIGKILL to force", c.ID) + logrus.Debugf("container %s failed to exit in 10 seconds of SIGTERM, sending SIGKILL to force", c.ID) sig, ok := signal.SignalMap["KILL"] if !ok { return fmt.Errorf("System does not support SIGKILL") @@ -637,7 +637,7 @@ func (daemon *Daemon) shutdownContainer(c *container.Container) error { } // If container failed to exit in 10 seconds of SIGTERM, then using the force if err := daemon.containerStop(c, 10); err != nil { - return fmt.Errorf("Stop container %s with error: %v", c.ID, err) + return fmt.Errorf("Failed to stop container %s with error: %v", c.ID, err) } c.WaitStop(-1 * time.Second) @@ -650,8 +650,12 @@ func (daemon *Daemon) Shutdown() error { // Keep mounts and networking running on daemon shutdown if // we are to keep containers running and restore them. if daemon.configStore.LiveRestore { - return nil + // check if there are any running containers, if none we should do some cleanup + if ls, err := daemon.Containers(&types.ContainerListOptions{}); len(ls) != 0 || err != nil { + return nil + } } + if daemon.containers != nil { logrus.Debug("starting clean shutdown of all containers...") daemon.containers.ApplyAll(func(c *container.Container) { @@ -681,6 +685,8 @@ func (daemon *Daemon) Shutdown() error { } } + pluginShutdown() + if err := daemon.cleanupMounts(); err != nil { return err } diff --git a/daemon/daemon_experimental.go b/daemon/daemon_experimental.go index 3fd0e765da..5244f1df2f 100644 --- a/daemon/daemon_experimental.go +++ b/daemon/daemon_experimental.go @@ -2,8 +2,15 @@ package daemon -import "github.com/docker/engine-api/types/container" +import ( + "github.com/docker/docker/plugin" + "github.com/docker/engine-api/types/container" +) func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *container.HostConfig, config *container.Config) ([]string, error) { return nil, nil } + +func pluginShutdown() { + plugin.GetManager().Shutdown() +} diff --git a/daemon/daemon_stub.go b/daemon/daemon_stub.go index 40e8ddc881..dd1fb09f1f 100644 --- a/daemon/daemon_stub.go +++ b/daemon/daemon_stub.go @@ -7,3 +7,6 @@ import "github.com/docker/engine-api/types/container" func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *container.HostConfig, config *container.Config) ([]string, error) { return nil, nil } + +func pluginShutdown() { +} diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 6df84164a0..afeaedc34e 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -579,7 +579,11 @@ func verifyDaemonSettings(config *Config) error { if config.Runtimes == nil { config.Runtimes = make(map[string]types.Runtime) } - config.Runtimes[stockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary} + stockRuntimeOpts := []string{} + if UsingSystemd(config) { + stockRuntimeOpts = append(stockRuntimeOpts, "--systemd-cgroup=true") + } + config.Runtimes[stockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary, Args: stockRuntimeOpts} return nil } diff --git a/daemon/graphdriver/overlay2/overlay.go b/daemon/graphdriver/overlay2/overlay.go index b48bcb90de..136d058d5d 100644 --- a/daemon/graphdriver/overlay2/overlay.go +++ b/daemon/graphdriver/overlay2/overlay.go @@ -10,6 +10,7 @@ import ( "os" "os/exec" "path" + "strconv" "strings" "syscall" @@ -21,6 +22,7 @@ import ( "github.com/docker/docker/pkg/directory" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/mount" + "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/parsers/kernel" "github.com/opencontainers/runc/libcontainer/label" @@ -92,6 +94,10 @@ func init() { // If overlay filesystem is not supported on the host, graphdriver.ErrNotSupported is returned as error. // If a overlay filesystem is not supported over a existing filesystem then error graphdriver.ErrIncompatibleFS is returned. func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { + opts, err := parseOptions(options) + if err != nil { + return nil, err + } if err := supportsOverlay(); err != nil { return nil, graphdriver.ErrNotSupported @@ -103,7 +109,10 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, err } if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: 4, Major: 0, Minor: 0}) < 0 { - return nil, graphdriver.ErrNotSupported + if !opts.overrideKernelCheck { + return nil, graphdriver.ErrNotSupported + } + logrus.Warnf("Using pre-4.0.0 kernel for overlay2, mount failures may require kernel update") } fsMagic, err := graphdriver.GetFSMagic(home) @@ -144,6 +153,31 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return d, nil } +type overlayOptions struct { + overrideKernelCheck bool +} + +func parseOptions(options []string) (*overlayOptions, error) { + o := &overlayOptions{} + for _, option := range options { + key, val, err := parsers.ParseKeyValueOpt(option) + if err != nil { + return nil, err + } + key = strings.ToLower(key) + switch key { + case "overlay2.override_kernel_check": + o.overrideKernelCheck, err = strconv.ParseBool(val) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("overlay2: Unknown option %s\n", key) + } + } + return o, nil +} + func supportsOverlay() error { // We can try to modprobe overlay first before looking at // proc/filesystems for when overlay is supported diff --git a/daemon/images.go b/daemon/images.go index 52dc67508b..0060cdafb2 100644 --- a/daemon/images.go +++ b/daemon/images.go @@ -167,7 +167,7 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool) ([]*types.Imag } else { continue } - } else if danglingOnly { + } else if danglingOnly && len(newImage.RepoTags) > 0 { continue } diff --git a/daemon/info.go b/daemon/info.go index 00d659a0ff..c9ece28e33 100644 --- a/daemon/info.go +++ b/daemon/info.go @@ -51,6 +51,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) { meminfo, err := system.ReadMemInfo() if err != nil { logrus.Errorf("Could not read system memory info: %v", err) + meminfo = &system.MemInfo{} } sysInfo := sysinfo.New(true) @@ -71,7 +72,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) { if sysInfo.AppArmor { securityOptions = append(securityOptions, "apparmor") } - if sysInfo.Seccomp { + if sysInfo.Seccomp && supportsSeccomp { securityOptions = append(securityOptions, "seccomp") } if selinuxEnabled() { diff --git a/daemon/logs.go b/daemon/logs.go index e0da46d9e4..1b285c691d 100644 --- a/daemon/logs.go +++ b/daemon/logs.go @@ -150,6 +150,10 @@ func (daemon *Daemon) mergeAndVerifyLogConfig(cfg *containertypes.LogConfig) err cfg.Type = daemon.defaultLogConfig.Type } + if cfg.Config == nil { + cfg.Config = make(map[string]string) + } + if cfg.Type == daemon.defaultLogConfig.Type { for k, v := range daemon.defaultLogConfig.Config { if _, ok := cfg.Config[k]; !ok { diff --git a/daemon/logs_test.go b/daemon/logs_test.go new file mode 100644 index 0000000000..f0c6f6e1e9 --- /dev/null +++ b/daemon/logs_test.go @@ -0,0 +1,15 @@ +package daemon + +import ( + "testing" + + containertypes "github.com/docker/engine-api/types/container" +) + +func TestMergeAndVerifyLogConfigNilConfig(t *testing.T) { + d := &Daemon{defaultLogConfig: containertypes.LogConfig{Type: "json-file", Config: map[string]string{"max-file": "1"}}} + cfg := containertypes.LogConfig{Type: d.defaultLogConfig.Type} + if err := d.mergeAndVerifyLogConfig(&cfg); err != nil { + t.Fatal(err) + } +} diff --git a/daemon/network.go b/daemon/network.go index a9944e637c..f852c6b43a 100644 --- a/daemon/network.go +++ b/daemon/network.go @@ -127,6 +127,14 @@ func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nod return } + // Cleanup any stale endpoints that might be left over during previous iterations + epList := n.Endpoints() + for _, ep := range epList { + if err := ep.Delete(true); err != nil { + logrus.Errorf("Failed to delete endpoint %s (%s): %v", ep.Name(), ep.ID(), err) + } + } + if err := n.Delete(); err != nil { logrus.Errorf("Failed to delete stale ingress network %s: %v", n.ID(), err) return diff --git a/daemon/seccomp_disabled.go b/daemon/seccomp_disabled.go index 8f13f5606d..4ad1b7c53f 100644 --- a/daemon/seccomp_disabled.go +++ b/daemon/seccomp_disabled.go @@ -1,4 +1,4 @@ -// +build !seccomp,!windows +// +build linux,!seccomp package daemon @@ -9,6 +9,8 @@ import ( "github.com/opencontainers/specs/specs-go" ) +var supportsSeccomp = false + func setSeccomp(daemon *Daemon, rs *specs.Spec, c *container.Container) error { if c.SeccompProfile != "" && c.SeccompProfile != "unconfined" { return fmt.Errorf("seccomp profiles are not supported on this daemon, you cannot specify a custom seccomp profile") diff --git a/daemon/seccomp_linux.go b/daemon/seccomp_linux.go index 34ffcb5975..e9622787ee 100644 --- a/daemon/seccomp_linux.go +++ b/daemon/seccomp_linux.go @@ -11,6 +11,8 @@ import ( "github.com/opencontainers/specs/specs-go" ) +var supportsSeccomp = true + func setSeccomp(daemon *Daemon, rs *specs.Spec, c *container.Container) error { var profile *specs.Seccomp var err error diff --git a/daemon/seccomp_unsupported.go b/daemon/seccomp_unsupported.go new file mode 100644 index 0000000000..b3691e96af --- /dev/null +++ b/daemon/seccomp_unsupported.go @@ -0,0 +1,5 @@ +// +build !linux + +package daemon + +var supportsSeccomp = false diff --git a/daemon/start.go b/daemon/start.go index 8def3ccd1b..7a0bc2121c 100644 --- a/daemon/start.go +++ b/daemon/start.go @@ -18,7 +18,7 @@ import ( ) // ContainerStart starts a container. -func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig) error { +func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, validateHostname bool) error { container, err := daemon.GetContainer(name) if err != nil { return err @@ -68,7 +68,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos // check if hostConfig is in line with the current system settings. // It may happen cgroups are umounted or the like. - if _, err = daemon.verifyContainerSettings(container.HostConfig, nil, false); err != nil { + if _, err = daemon.verifyContainerSettings(container.HostConfig, nil, false, validateHostname); err != nil { return err } // Adapt for old containers in case we have updates in this function and diff --git a/daemon/top_unix.go b/daemon/top_unix.go index d4a9528c98..935f38f29e 100644 --- a/daemon/top_unix.go +++ b/daemon/top_unix.go @@ -5,12 +5,82 @@ package daemon import ( "fmt" "os/exec" + "regexp" "strconv" "strings" "github.com/docker/engine-api/types" ) +func validatePSArgs(psArgs string) error { + // NOTE: \\s does not detect unicode whitespaces. + // So we use fieldsASCII instead of strings.Fields in parsePSOutput. + // See https://github.com/docker/docker/pull/24358 + re := regexp.MustCompile("\\s+([^\\s]*)=\\s*(PID[^\\s]*)") + for _, group := range re.FindAllStringSubmatch(psArgs, -1) { + if len(group) >= 3 { + k := group[1] + v := group[2] + if k != "pid" { + return fmt.Errorf("specifying \"%s=%s\" is not allowed", k, v) + } + } + } + return nil +} + +// fieldsASCII is similar to strings.Fields but only allows ASCII whitespaces +func fieldsASCII(s string) []string { + fn := func(r rune) bool { + switch r { + case '\t', '\n', '\f', '\r', ' ': + return true + } + return false + } + return strings.FieldsFunc(s, fn) +} + +func parsePSOutput(output []byte, pids []int) (*types.ContainerProcessList, error) { + procList := &types.ContainerProcessList{} + + lines := strings.Split(string(output), "\n") + procList.Titles = fieldsASCII(lines[0]) + + pidIndex := -1 + for i, name := range procList.Titles { + if name == "PID" { + pidIndex = i + } + } + if pidIndex == -1 { + return nil, fmt.Errorf("Couldn't find PID field in ps output") + } + + // loop through the output and extract the PID from each line + for _, line := range lines[1:] { + if len(line) == 0 { + continue + } + fields := fieldsASCII(line) + p, err := strconv.Atoi(fields[pidIndex]) + if err != nil { + return nil, fmt.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err) + } + + for _, pid := range pids { + if pid == p { + // Make sure number of fields equals number of header titles + // merging "overhanging" fields + process := fields[:len(procList.Titles)-1] + process = append(process, strings.Join(fields[len(procList.Titles)-1:], " ")) + procList.Processes = append(procList.Processes, process) + } + } + } + return procList, nil +} + // ContainerTop lists the processes running inside of the given // container by calling ps with the given args, or with the flags // "-ef" if no args are given. An error is returned if the container @@ -21,6 +91,10 @@ func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.Container psArgs = "-ef" } + if err := validatePSArgs(psArgs); err != nil { + return nil, err + } + container, err := daemon.GetContainer(name) if err != nil { return nil, err @@ -43,42 +117,9 @@ func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.Container if err != nil { return nil, fmt.Errorf("Error running ps: %v", err) } - - procList := &types.ContainerProcessList{} - - lines := strings.Split(string(output), "\n") - procList.Titles = strings.Fields(lines[0]) - - pidIndex := -1 - for i, name := range procList.Titles { - if name == "PID" { - pidIndex = i - } - } - if pidIndex == -1 { - return nil, fmt.Errorf("Couldn't find PID field in ps output") - } - - // loop through the output and extract the PID from each line - for _, line := range lines[1:] { - if len(line) == 0 { - continue - } - fields := strings.Fields(line) - p, err := strconv.Atoi(fields[pidIndex]) - if err != nil { - return nil, fmt.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err) - } - - for _, pid := range pids { - if pid == p { - // Make sure number of fields equals number of header titles - // merging "overhanging" fields - process := fields[:len(procList.Titles)-1] - process = append(process, strings.Join(fields[len(procList.Titles)-1:], " ")) - procList.Processes = append(procList.Processes, process) - } - } + procList, err := parsePSOutput(output, pids) + if err != nil { + return nil, err } daemon.LogContainerEvent(container, "top") return procList, nil diff --git a/daemon/top_unix_test.go b/daemon/top_unix_test.go new file mode 100644 index 0000000000..269ab6e947 --- /dev/null +++ b/daemon/top_unix_test.go @@ -0,0 +1,76 @@ +//+build !windows + +package daemon + +import ( + "testing" +) + +func TestContainerTopValidatePSArgs(t *testing.T) { + tests := map[string]bool{ + "ae -o uid=PID": true, + "ae -o \"uid= PID\"": true, // ascii space (0x20) + "ae -o \"uid= PID\"": false, // unicode space (U+2003, 0xe2 0x80 0x83) + "ae o uid=PID": true, + "aeo uid=PID": true, + "ae -O uid=PID": true, + "ae -o pid=PID2 -o uid=PID": true, + "ae -o pid=PID": false, + "ae -o pid=PID -o uid=PIDX": true, // FIXME: we do not need to prohibit this + "aeo pid=PID": false, + "ae": false, + "": false, + } + for psArgs, errExpected := range tests { + err := validatePSArgs(psArgs) + t.Logf("tested %q, got err=%v", psArgs, err) + if errExpected && err == nil { + t.Fatalf("expected error, got %v (%q)", err, psArgs) + } + if !errExpected && err != nil { + t.Fatalf("expected nil, got %v (%q)", err, psArgs) + } + } +} + +func TestContainerTopParsePSOutput(t *testing.T) { + tests := []struct { + output []byte + pids []int + errExpected bool + }{ + {[]byte(` PID COMMAND + 42 foo + 43 bar + 100 baz +`), []int{42, 43}, false}, + {[]byte(` UID COMMAND + 42 foo + 43 bar + 100 baz +`), []int{42, 43}, true}, + // unicode space (U+2003, 0xe2 0x80 0x83) + {[]byte(` PID COMMAND + 42 foo + 43 bar + 100 baz +`), []int{42, 43}, true}, + // the first space is U+2003, the second one is ascii. + {[]byte(` PID COMMAND + 42 foo + 43 bar + 100 baz +`), []int{42, 43}, true}, + } + + for _, f := range tests { + _, err := parsePSOutput(f.output, f.pids) + t.Logf("tested %q, got err=%v", string(f.output), err) + if f.errExpected && err == nil { + t.Fatalf("expected error, got %v (%q)", err, string(f.output)) + } + if !f.errExpected && err != nil { + t.Fatalf("expected nil, got %v (%q)", err, string(f.output)) + } + } +} diff --git a/daemon/update.go b/daemon/update.go index 05a41b2e95..0a5e76d1cd 100644 --- a/daemon/update.go +++ b/daemon/update.go @@ -7,10 +7,10 @@ import ( ) // ContainerUpdate updates configuration of the container -func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error) { +func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) ([]string, error) { var warnings []string - warnings, err := daemon.verifyContainerSettings(hostConfig, nil, true) + warnings, err := daemon.verifyContainerSettings(hostConfig, nil, true, validateHostname) if err != nil { return warnings, err } diff --git a/distribution/errors.go b/distribution/errors.go index cd8dd590df..a9a17bd261 100644 --- a/distribution/errors.go +++ b/distribution/errors.go @@ -89,7 +89,7 @@ func retryOnError(err error) error { } case errcode.Error: switch v.Code { - case errcode.ErrorCodeUnauthorized, errcode.ErrorCodeUnsupported, errcode.ErrorCodeDenied, errcode.ErrorCodeTooManyRequests: + case errcode.ErrorCodeUnauthorized, errcode.ErrorCodeUnsupported, errcode.ErrorCodeDenied, errcode.ErrorCodeTooManyRequests, v2.ErrorCodeNameUnknown: return xfer.DoNotRetry{Err: err} } case *url.Error: diff --git a/distribution/pull.go b/distribution/pull.go index d54acff4f3..dad93b656d 100644 --- a/distribution/pull.go +++ b/distribution/pull.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/Sirupsen/logrus" + "github.com/docker/distribution/digest" "github.com/docker/docker/api" "github.com/docker/docker/distribution/metadata" "github.com/docker/docker/distribution/xfer" @@ -203,3 +204,22 @@ func ValidateRepoName(name string) error { } return nil } + +func addDigestReference(store reference.Store, ref reference.Named, dgst digest.Digest, imageID image.ID) error { + dgstRef, err := reference.WithDigest(ref, dgst) + if err != nil { + return err + } + + if oldTagImageID, err := store.Get(dgstRef); err == nil { + if oldTagImageID != imageID { + // Updating digests not supported by reference store + logrus.Errorf("Image ID for digest %s changed from %s to %s, cannot update", dgst.String(), oldTagImageID, imageID) + } + return nil + } else if err != reference.ErrDoesNotExist { + return err + } + + return store.AddDigest(dgstRef, imageID, true) +} diff --git a/distribution/pull_v2.go b/distribution/pull_v2.go index 607300a316..c78e221f04 100644 --- a/distribution/pull_v2.go +++ b/distribution/pull_v2.go @@ -393,7 +393,7 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat oldTagImageID, err := p.config.ReferenceStore.Get(ref) if err == nil { if oldTagImageID == imageID { - return false, nil + return false, addDigestReference(p.config.ReferenceStore, ref, manifestDigest, imageID) } } else if err != reference.ErrDoesNotExist { return false, err @@ -403,10 +403,14 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat if err = p.config.ReferenceStore.AddDigest(canonical, imageID, true); err != nil { return false, err } - } else if err = p.config.ReferenceStore.AddTag(ref, imageID, true); err != nil { - return false, err + } else { + if err = addDigestReference(p.config.ReferenceStore, ref, manifestDigest, imageID); err != nil { + return false, err + } + if err = p.config.ReferenceStore.AddTag(ref, imageID, true); err != nil { + return false, err + } } - return true, nil } diff --git a/distribution/push_v2.go b/distribution/push_v2.go index 0bb0a1de30..7d331f43d2 100644 --- a/distribution/push_v2.go +++ b/distribution/push_v2.go @@ -200,6 +200,11 @@ func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, ima manifestDigest := digest.FromBytes(canonicalManifest) progress.Messagef(p.config.ProgressOutput, "", "%s: digest: %s size: %d", ref.Tag(), manifestDigest, len(canonicalManifest)) + + if err := addDigestReference(p.config.ReferenceStore, ref, manifestDigest, imageID); err != nil { + return err + } + // Signal digest to the trust client so it can sign the // push, if appropriate. progress.Aux(p.config.ProgressOutput, PushResult{Tag: ref.Tag(), Digest: manifestDigest, Size: len(canonicalManifest)}) diff --git a/docs/admin/b2d_volume_resize.md b/docs/admin/b2d_volume_resize.md index 68bba70415..1e137ab3fa 100644 --- a/docs/admin/b2d_volume_resize.md +++ b/docs/admin/b2d_volume_resize.md @@ -73,7 +73,7 @@ The `boot2docker` command reads its configuration from the `$BOOT2DOCKER_PROFILE This solution increases the volume size by first cloning it, then resizing it using a disk partitioning tool. We recommend -[GParted](http://gparted.sourceforge.net/download.php/index.php). The tool comes +[GParted](https://sourceforge.net/projects/gparted/files/). The tool comes as a bootable ISO, is a free download, and works well with VirtualBox. 1. Stop Boot2Docker @@ -102,7 +102,7 @@ as a bootable ISO, is a free download, and works well with VirtualBox. 5. Download a disk partitioning tool ISO - To resize the volume, we'll use [GParted](http://gparted.sourceforge.net/download.php/). + To resize the volume, we'll use [GParted](https://sourceforge.net/projects/gparted/files/). Once you've downloaded the tool, add the ISO to the Boot2Docker VM IDE bus. You might need to create the bus before you can add the ISO. diff --git a/docs/admin/host_integration.md b/docs/admin/host_integration.md index fd47ea6ec8..f3dde2e251 100644 --- a/docs/admin/host_integration.md +++ b/docs/admin/host_integration.md @@ -84,5 +84,6 @@ and removed when the service is stopped. [Service] ... ExecStart=/usr/bin/docker run --env foo=bar --name redis_server redis - ExecStop=/usr/bin/docker stop -t 2 redis_server ; /usr/bin/docker rm -f redis_server + ExecStop=/usr/bin/docker stop -t 2 redis_server + ExecStopPost=/usr/bin/docker rm -f redis_server ... diff --git a/docs/admin/logging/gcplogs.md b/docs/admin/logging/gcplogs.md index c92c17a102..d19afefa1e 100644 --- a/docs/admin/logging/gcplogs.md +++ b/docs/admin/logging/gcplogs.md @@ -34,7 +34,7 @@ Otherwise, the user must specify which project to log to using the `--gcp-projec log option and Docker will attempt to obtain credentials from the Google Application Default Credential. The `--gcp-project` takes precedence over information discovered from the metadata server -so a Docker daemon running in a Google Cloud Project can be overriden to log to a different +so a Docker daemon running in a Google Cloud Project can be overridden to log to a different Google Cloud Project using `--gcp-project`. ## gcplogs options diff --git a/docs/admin/logging/overview.md b/docs/admin/logging/overview.md index 6108a7569b..2cad6061aa 100644 --- a/docs/admin/logging/overview.md +++ b/docs/admin/logging/overview.md @@ -25,7 +25,7 @@ supported: | `json-file` | Default logging driver for Docker. Writes JSON messages to file. | | `syslog` | Syslog logging driver for Docker. Writes log messages to syslog. | | `journald` | Journald logging driver for Docker. Writes log messages to `journald`. | -| `gelf` | Graylog Extended Log Format (GELF) logging driver for Docker. Writes log messages to a GELF endpoint likeGraylog or Logstash. | +| `gelf` | Graylog Extended Log Format (GELF) logging driver for Docker. Writes log messages to a GELF endpoint like Graylog or Logstash. | | `fluentd` | Fluentd logging driver for Docker. Writes log messages to `fluentd` (forward input). | | `awslogs` | Amazon CloudWatch Logs logging driver for Docker. Writes log messages to Amazon CloudWatch Logs. | | `splunk` | Splunk logging driver for Docker. Writes log messages to `splunk` using HTTP Event Collector. | @@ -155,7 +155,7 @@ option is ignored if the address protocol is not `tcp+tls`. is ignored if the address protocol is not `tcp+tls`. `syslog-tls-skip-verify` configures the TLS verification. This verification is -enabled by default, but it can be overriden by setting this option to `true`. +enabled by default, but it can be overridden by setting this option to `true`. This option is ignored if the address protocol is not `tcp+tls`. `tag` configures a string that is appended to the APP-NAME in the syslog diff --git a/docs/deprecated.md b/docs/deprecated.md index 6941408f58..554272ff49 100644 --- a/docs/deprecated.md +++ b/docs/deprecated.md @@ -17,15 +17,15 @@ The following list of features are deprecated in Engine. ### Three argument form in `docker import` **Deprecated In Release: [v0.6.7](https://github.com/docker/docker/releases/tag/v0.6.7)** -**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)** +**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/)** The `docker import` command format 'file|URL|- [REPOSITORY [TAG]]' is deprecated since November 2013. It's no more supported. ### `-h` shorthand for `--help` -**Deprecated In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)** +**Deprecated In Release: [v1.12.0](https://github.com/docker/docker/releases/)** -**Target For Removal In Release: [v1.14.0](https://github.com/docker/docker/releases/tag/v1.12.0)** +**Target For Removal In Release: [v1.14.0](https://github.com/docker/docker/releases/)** The shorthand (`-h`) is less common than `--help` on Linux and cannot be used on all subcommands (due to it conflicting with, e.g. `-h` / `--hostname` on @@ -48,9 +48,9 @@ The flag `--security-opt` doesn't use the colon separator(`:`) anymore to divide ### `/containers/(id or name)/copy` endpoint -**Deprecated In Release: v1.8** +**Deprecated In Release: [v1.8.0](https://github.com/docker/docker/releases/tag/v1.8.0)** -**Removed In Release: v1.12.0** +**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/)** The endpoint `/containers/(id or name)/copy` is deprecated in favor of `/containers/(id or name)/archive`. @@ -63,14 +63,14 @@ See the events API documentation for the new format. ### `-f` flag on `docker tag` **Deprecated In Release: [v1.10.0](https://github.com/docker/docker/releases/tag/v1.10.0)** -**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)** +**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/)** To make tagging consistent across the various `docker` commands, the `-f` flag on the `docker tag` command is deprecated. It is not longer necessary to specify `-f` to move a tag from one image to another. Nor will `docker` generate an error if the `-f` flag is missing and the specified tag is already in use. ### HostConfig at API container start **Deprecated In Release: [v1.10.0](https://github.com/docker/docker/releases/tag/v1.10.0)** -**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)** +**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/)** Passing an `HostConfig` to `POST /containers/{name}/start` is deprecated in favor of defining it at container creation (`POST /containers/create`). @@ -79,14 +79,14 @@ defining it at container creation (`POST /containers/create`). **Deprecated In Release: [v1.10.0](https://github.com/docker/docker/releases/tag/v1.10.0)** -**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)** +**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/)** The `docker ps --before` and `docker ps --since` options are deprecated. Use `docker ps --filter=before=...` and `docker ps --filter=since=...` instead. ### Docker search 'automated' and 'stars' options -**Deprecated in Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)** +**Deprecated in Release: [v1.12.0](https://github.com/docker/docker/releases/)** **Target For Removal In Release: v1.14** @@ -96,7 +96,7 @@ Use `docker search --filter=is-automated=...` and `docker search --filter=stars= ### Driver Specific Log Tags **Deprecated In Release: [v1.9.0](https://github.com/docker/docker/releases/tag/v1.9.0)** -**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)** +**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/)** Log tags are now generated in a standard way across different logging drivers. Because of which, the driver specific log tag options `syslog-tag`, `gelf-tag` and @@ -162,7 +162,7 @@ The following double-dash options are deprecated and have no replacement: **Deprecated In Release: [v1.5.0](https://github.com/docker/docker/releases/tag/v1.5.0)** -**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)** +**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/)** The single-dash (`-help`) was removed, in favor of the double-dash `--help` @@ -177,7 +177,7 @@ Version 1.9 adds a flag (`--disable-legacy-registry=false`) which prevents the d ### Docker Content Trust ENV passphrase variables name change **Deprecated In Release: [v1.9.0](https://github.com/docker/docker/releases/tag/v1.9.0)** -**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/tag/v1.12.0)** +**Removed In Release: [v1.12.0](https://github.com/docker/docker/releases/)** Since 1.9, Docker Content Trust Offline key has been renamed to Root key and the Tagging key has been renamed to Repository key. Due to this renaming, we're also changing the corresponding environment variables diff --git a/docs/examples/apt-cacher-ng.md b/docs/examples/apt-cacher-ng.md index 6a202f8220..d245ff69d6 100644 --- a/docs/examples/apt-cacher-ng.md +++ b/docs/examples/apt-cacher-ng.md @@ -93,8 +93,8 @@ too. **Option 5** creates a custom network of APT proxy server and Debian-based containers: $ docker network create mynetwork - $ docker run -d -p 3142:3142 --net=mynetwork --name test_apt_cacher_ng eg_apt_cacher_ng - $ docker run --rm -it --net=mynetwork -e http_proxy=http://test_apt_cacher_ng:3142/ debian bash + $ docker run -d -p 3142:3142 --network=mynetwork --name test_apt_cacher_ng eg_apt_cacher_ng + $ docker run --rm -it --network=mynetwork -e http_proxy=http://test_apt_cacher_ng:3142/ debian bash Apt-cacher-ng has some tools that allow you to manage the repository, and they can be used by leveraging the `VOLUME` diff --git a/docs/extend/plugins_network.md b/docs/extend/plugins_network.md index aad01ba29a..ec1ccddfea 100644 --- a/docs/extend/plugins_network.md +++ b/docs/extend/plugins_network.md @@ -18,6 +18,17 @@ LibNetwork, which shares plugin infrastructure with Engine. Effectively, network driver plugins are activated in the same way as other plugins, and use the same kind of protocol. +## Network driver plugins and swarm mode + +Docker 1.12 adds support for cluster management and orchestration called +[swarm mode](../swarm/index.md). Docker Engine running in swarm mode currently +only supports the built-in overlay driver for networking. Therefore existing +networking plugins will not work in swarm mode. + +When you run Docker Engine outside of swarm mode, all networking plugins that +worked in Docker 1.11 will continue to function normally. They do not require +any modification. + ## Using network driver plugins The means of installing and running a network driver plugin depend on the @@ -35,7 +46,7 @@ Some network driver plugins are listed in [plugins](plugins.md) The `mynet` network is now owned by `weave`, so subsequent commands referring to that network will be sent to the plugin, - $ docker run --net=mynet busybox top + $ docker run --network=mynet busybox top ## Write a network plugin diff --git a/docs/installation/binaries.md b/docs/installation/binaries.md index 91baa45cbb..f0dda97e74 100644 --- a/docs/installation/binaries.md +++ b/docs/installation/binaries.md @@ -130,11 +130,13 @@ directory named `docker` in your current location. $ tar -xvzf docker-latest.tgz docker/ -docker/docker-containerd-ctr docker/docker docker/docker-containerd -docker/docker-runc +docker/docker-containerd-ctr docker/docker-containerd-shim +docker/docker-proxy +docker/docker-runc +docker/dockerd ``` Engine requires these binaries to be installed in your host's `$PATH`. @@ -154,7 +156,7 @@ $ mv docker/* /usr/bin/ You can manually start the Engine in daemon mode using: ```bash -$ sudo docker daemon & +$ sudo dockerd & ``` The GitHub repository provides samples of init-scripts you can use to control diff --git a/docs/reference/api/docker_remote_api.md b/docs/reference/api/docker_remote_api.md index 109568c723..0568e8bbe3 100644 --- a/docs/reference/api/docker_remote_api.md +++ b/docs/reference/api/docker_remote_api.md @@ -133,9 +133,12 @@ This section lists each version from latest to oldest. Each listing includes a * `POST /containers/{name:.*}/copy` is now removed and errors out starting from this API version. * API errors are now returned as JSON instead of plain text. * `POST /containers/create` and `POST /containers/(id)/start` allow you to configure kernel parameters (sysctls) for use in the container. -* `POST /v1.23/containers//exec` and `POST /v1.23/exec//start` +* `POST /containers//exec` and `POST /exec//start` no longer expects a "Container" field to be present. This property was not used and is no longer sent by the docker client. +* `POST /containers/create/` now validates the hostname (should be a valid RFC 1123 hostname). +* `POST /containers/create/` `HostConfig.PidMode` field now accepts `container:`, + to have the container join the PID namespace of an existing container. ### v1.23 API changes diff --git a/docs/reference/api/docker_remote_api_v1.18.md b/docs/reference/api/docker_remote_api_v1.18.md index 0112088bf9..22df689d69 100644 --- a/docs/reference/api/docker_remote_api_v1.18.md +++ b/docs/reference/api/docker_remote_api_v1.18.md @@ -169,6 +169,7 @@ Create a container "MemorySwap": 0, "CpuShares": 512, "CpusetCpus": "0,1", + "PidMode": "", "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, "PublishAllPorts": false, "Privileged": false, @@ -242,6 +243,9 @@ Json Parameters: - **CpuShares** - An integer value containing the CPU Shares for container (ie. the relative weight vs other containers). - **CpusetCpus** - String value containing the cgroups CpusetCpus to use. + - **PidMode** - Set the PID (Process) Namespace mode for the container; + `"container:"`: joins another container's PID namespace + `"host"`: use the host's PID namespace inside the container - **PortBindings** - A map of exposed container ports and the host port they should map to. It should be specified in the form `{ /: [{ "HostPort": "" }] }` @@ -373,6 +377,7 @@ Return low-level information on the container `id` "Memory": 0, "MemorySwap": 0, "NetworkMode": "bridge", + "PidMode": "", "PortBindings": {}, "Privileged": false, "ReadonlyRootfs": false, diff --git a/docs/reference/api/docker_remote_api_v1.19.md b/docs/reference/api/docker_remote_api_v1.19.md index 078b3ad429..43ff9c689b 100644 --- a/docs/reference/api/docker_remote_api_v1.19.md +++ b/docs/reference/api/docker_remote_api_v1.19.md @@ -176,6 +176,7 @@ Create a container "CpusetMems": "0,1", "BlkioWeight": 300, "OomKillDisable": false, + "PidMode": "", "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, "PublishAllPorts": false, "Privileged": false, @@ -253,6 +254,9 @@ Json Parameters: - **CpusetMems** - Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems. - **BlkioWeight** - Block IO weight (relative weight) accepts a weight value between 10 and 1000. - **OomKillDisable** - Boolean value, whether to disable OOM Killer for the container or not. + - **PidMode** - Set the PID (Process) Namespace mode for the container; + `"container:"`: joins another container's PID namespace + `"host"`: use the host's PID namespace inside the container - **PortBindings** - A map of exposed container ports and the host port they should map to. A JSON object in the form `{ /: [{ "HostPort": "" }] }` @@ -388,6 +392,7 @@ Return low-level information on the container `id` "MemorySwap": 0, "OomKillDisable": false, "NetworkMode": "bridge", + "PidMode": "", "PortBindings": {}, "Privileged": false, "ReadonlyRootfs": false, diff --git a/docs/reference/api/docker_remote_api_v1.20.md b/docs/reference/api/docker_remote_api_v1.20.md index 05bfeff6b3..e381a243d1 100644 --- a/docs/reference/api/docker_remote_api_v1.20.md +++ b/docs/reference/api/docker_remote_api_v1.20.md @@ -177,6 +177,7 @@ Create a container "BlkioWeight": 300, "MemorySwappiness": 60, "OomKillDisable": false, + "PidMode": "", "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, "PublishAllPorts": false, "Privileged": false, @@ -256,6 +257,9 @@ Json Parameters: - **BlkioWeight** - Block IO weight (relative weight) accepts a weight value between 10 and 1000. - **MemorySwappiness** - Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. - **OomKillDisable** - Boolean value, whether to disable OOM Killer for the container or not. + - **PidMode** - Set the PID (Process) Namespace mode for the container; + `"container:"`: joins another container's PID namespace + `"host"`: use the host's PID namespace inside the container - **PortBindings** - A map of exposed container ports and the host port they should map to. A JSON object in the form `{ /: [{ "HostPort": "" }] }` @@ -391,6 +395,7 @@ Return low-level information on the container `id` "MemorySwap": 0, "OomKillDisable": false, "NetworkMode": "bridge", + "PidMode": "", "PortBindings": {}, "Privileged": false, "ReadonlyRootfs": false, diff --git a/docs/reference/api/docker_remote_api_v1.21.md b/docs/reference/api/docker_remote_api_v1.21.md index 11c2d5981f..d55e4a174e 100644 --- a/docs/reference/api/docker_remote_api_v1.21.md +++ b/docs/reference/api/docker_remote_api_v1.21.md @@ -184,6 +184,7 @@ Create a container "BlkioWeight": 300, "MemorySwappiness": 60, "OomKillDisable": false, + "PidMode": "", "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, "PublishAllPorts": false, "Privileged": false, @@ -271,6 +272,9 @@ Json Parameters: - **BlkioWeight** - Block IO weight (relative weight) accepts a weight value between 10 and 1000. - **MemorySwappiness** - Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. - **OomKillDisable** - Boolean value, whether to disable OOM Killer for the container or not. + - **PidMode** - Set the PID (Process) Namespace mode for the container; + `"container:"`: joins another container's PID namespace + `"host"`: use the host's PID namespace inside the container - **PortBindings** - A map of exposed container ports and the host port they should map to. A JSON object in the form `{ /: [{ "HostPort": "" }] }` @@ -414,6 +418,7 @@ Return low-level information on the container `id` "KernelMemory": 0, "OomKillDisable": false, "NetworkMode": "bridge", + "PidMode": "", "PortBindings": {}, "Privileged": false, "ReadonlyRootfs": false, diff --git a/docs/reference/api/docker_remote_api_v1.22.md b/docs/reference/api/docker_remote_api_v1.22.md index a97e01db74..07fa423743 100644 --- a/docs/reference/api/docker_remote_api_v1.22.md +++ b/docs/reference/api/docker_remote_api_v1.22.md @@ -277,6 +277,7 @@ Create a container "MemorySwappiness": 60, "OomKillDisable": false, "OomScoreAdj": 500, + "PidMode": "", "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, "PublishAllPorts": false, "Privileged": false, @@ -382,6 +383,9 @@ Json Parameters: - **MemorySwappiness** - Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. - **OomKillDisable** - Boolean value, whether to disable OOM Killer for the container or not. - **OomScoreAdj** - An integer value containing the score given to the container in order to tune OOM killer preferences. + - **PidMode** - Set the PID (Process) Namespace mode for the container; + `"container:"`: joins another container's PID namespace + `"host"`: use the host's PID namespace inside the container - **PortBindings** - A map of exposed container ports and the host port they should map to. A JSON object in the form `{ /: [{ "HostPort": "" }] }` @@ -534,6 +538,7 @@ Return low-level information on the container `id` "OomKillDisable": false, "OomScoreAdj": 500, "NetworkMode": "bridge", + "PidMode": "", "PortBindings": {}, "Privileged": false, "ReadonlyRootfs": false, diff --git a/docs/reference/api/docker_remote_api_v1.23.md b/docs/reference/api/docker_remote_api_v1.23.md index 3e14d7f129..3e9ca61430 100644 --- a/docs/reference/api/docker_remote_api_v1.23.md +++ b/docs/reference/api/docker_remote_api_v1.23.md @@ -296,6 +296,7 @@ Create a container "MemorySwappiness": 60, "OomKillDisable": false, "OomScoreAdj": 500, + "PidMode": "", "PidsLimit": -1, "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, "PublishAllPorts": false, @@ -402,6 +403,9 @@ Json Parameters: - **MemorySwappiness** - Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. - **OomKillDisable** - Boolean value, whether to disable OOM Killer for the container or not. - **OomScoreAdj** - An integer value containing the score given to the container in order to tune OOM killer preferences. + - **PidMode** - Set the PID (Process) Namespace mode for the container; + `"container:"`: joins another container's PID namespace + `"host"`: use the host's PID namespace inside the container - **PidsLimit** - Tune a container's pids limit. Set -1 for unlimited. - **PortBindings** - A map of exposed container ports and the host port they should map to. A JSON object in the form @@ -557,6 +561,7 @@ Return low-level information on the container `id` "OomKillDisable": false, "OomScoreAdj": 500, "NetworkMode": "bridge", + "PidMode": "", "PortBindings": {}, "Privileged": false, "ReadonlyRootfs": false, diff --git a/docs/reference/api/docker_remote_api_v1.24.md b/docs/reference/api/docker_remote_api_v1.24.md index d745a021a6..af73b55277 100644 --- a/docs/reference/api/docker_remote_api_v1.24.md +++ b/docs/reference/api/docker_remote_api_v1.24.md @@ -310,6 +310,7 @@ Create a container "MemorySwappiness": 60, "OomKillDisable": false, "OomScoreAdj": 500, + "PidMode": "", "PidsLimit": -1, "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, "PublishAllPorts": false, @@ -361,7 +362,7 @@ Create a container **JSON parameters**: - **Hostname** - A string value containing the hostname to use for the - container. + container. This must be a valid RFC 1123 hostname. - **Domainname** - A string value containing the domain name to use for the container. - **User** - A string value specifying the user inside the container. @@ -421,6 +422,9 @@ Create a container - **MemorySwappiness** - Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. - **OomKillDisable** - Boolean value, whether to disable OOM Killer for the container or not. - **OomScoreAdj** - An integer value containing the score given to the container in order to tune OOM killer preferences. + - **PidMode** - Set the PID (Process) Namespace mode for the container; + `"container:"`: joins another container's PID namespace + `"host"`: use the host's PID namespace inside the container - **PidsLimit** - Tune a container's pids limit. Set -1 for unlimited. - **PortBindings** - A map of exposed container ports and the host port they should map to. A JSON object in the form @@ -583,6 +587,7 @@ Return low-level information on the container `id` "OomKillDisable": false, "OomScoreAdj": 500, "NetworkMode": "bridge", + "PidMode": "", "PortBindings": {}, "Privileged": false, "ReadonlyRootfs": false, @@ -2194,7 +2199,6 @@ Display system-wide information "DockerRootDir": "/var/lib/docker", "Driver": "btrfs", "DriverStatus": [[""]], - "ExecutionDriver": "native-0.1", "ExperimentalBuild": false, "HttpProxy": "http://test:test@localhost:8080", "HttpsProxy": "https://test:test@localhost:8080", @@ -3986,11 +3990,11 @@ JSON Parameters: - **Target** – Container path. - **Source** – Mount source (e.g. a volume name, a host path). - **Type** – The mount type (`bind`, or `volume`). - - **Writable** – A boolean indicating whether the mount should be writable. + - **ReadOnly** – A boolean indicating whether the mount should be read-only. - **BindOptions** - Optional configuration for the `bind` type. - **Propagation** – A propagation mode with the value `[r]private`, `[r]shared`, or `[r]slave`. - **VolumeOptions** – Optional configuration for the `volume` type. - - **Populate** – A boolean indicating if volume should be + - **NoCopy** – A boolean indicating if volume should be populated with the data from the target. (Default false) - **Labels** – User-defined name and labels for the volume. - **DriverConfig** – Map of driver-specific options. @@ -4008,7 +4012,7 @@ JSON Parameters: - **Memory** – Memory reservation - **RestartPolicy** – Specification for the restart policy which applies to containers created as part of this service. - - **Condition** – Condition for restart (`none`, `on_failure`, or `any`). + - **Condition** – Condition for restart (`none`, `on-failure`, or `any`). - **Delay** – Delay between restart attempts. - **Attempts** – Maximum attempts to restart a given container before giving up (default value is 0, which is ignored). @@ -4204,11 +4208,12 @@ Update the service `id`. - **Target** – Container path. - **Source** – Mount source (e.g. a volume name, a host path). - **Type** – The mount type (`bind`, or `volume`). - - **Writable** – A boolean indicating whether the mount should be writable. + - **ReadOnly** – A boolean indicating whether the mount should be read-only. - **BindOptions** - Optional configuration for the `bind` type - **Propagation** – A propagation mode with the value `[r]private`, `[r]shared`, or `[r]slave`. - **VolumeOptions** – Optional configuration for the `volume` type. - - **Populate** – A boolean indicating if volume should be populated with the data from the target. (Default false) + - **NoCopy** – A boolean indicating if volume should be + populated with the data from the target. (Default false) - **Labels** – User-defined name and labels for the volume. - **DriverConfig** – Map of driver-specific options. - **Name** - Name of the driver to use to create the volume @@ -4225,7 +4230,7 @@ Update the service `id`. - **Memory** – Memory reservation - **RestartPolicy** – Specification for the restart policy which applies to containers created as part of this service. - - **Condition** – Condition for restart (`none`, `on_failure`, or `any`). + - **Condition** – Condition for restart (`none`, `on-failure`, or `any`). - **Delay** – Delay between restart attempts. - **Attempts** – Maximum attempts to restart a given container before giving up (default value is 0, which is ignored). diff --git a/docs/reference/builder.md b/docs/reference/builder.md index 4c7e059c83..d677d63b8b 100644 --- a/docs/reference/builder.md +++ b/docs/reference/builder.md @@ -502,7 +502,7 @@ default is `/bin/sh -c` on Linux or `cmd /S /C` on Windows) - `RUN ["executable", "param1", "param2"]` (*exec* form) The `RUN` instruction will execute any commands in a new layer on top of the -current image and commit the results. The resulting committed image will be +current image and commit the results. The resulting comitted image will be used for the next step in the `Dockerfile`. Layering `RUN` instructions and generating commits conforms to the core @@ -544,7 +544,7 @@ RUN /bin/bash -c 'source $HOME/.bashrc ; echo $HOME' > > **Note**: > In the *JSON* form, it is necessary to escape backslashes. This is -> particularly relevant on Windows where the backslash is the path seperator. +> particularly relevant on Windows where the backslash is the path separator. > The following line would otherwise be treated as *shell* form due to not > being valid JSON, and fail in an unexpected way: > `RUN ["c:\windows\system32\tasklist.exe"]` @@ -572,7 +572,7 @@ The cache for `RUN` instructions can be invalidated by `ADD` instructions. See For systems that have recent aufs version (i.e., `dirperm1` mount option can be set), docker will attempt to fix the issue automatically by mounting the layers with `dirperm1` option. More details on `dirperm1` option can be - found at [`aufs` man page](http://aufs.sourceforge.net/aufs3/man.html) + found at [`aufs` man page](https://github.com/sfjro/aufs3-linux/tree/aufs3.18/Documentation/filesystems/aufs) If your system doesn't have support for `dirperm1`, the issue describes a workaround. @@ -1292,8 +1292,9 @@ subsequent line 3. The `USER` at line 4 evaluates to `what_user` as `user` is defined and the `what_user` value was passed on the command line. Prior to its definition by an `ARG` instruction, any use of a variable results in an empty string. -> **Note:** It is not recommended to use build-time variables for -> passing secrets like github keys, user credentials etc. +> **Warning:** It is not recommended to use build-time variables for +> passing secrets like github keys, user credentials etc. Build-time variable +> values are visible to any user of the image with the `docker history` command. You can use an `ARG` or an `ENV` instruction to specify variables that are available to the `RUN` instruction. Environment variables defined using the diff --git a/docs/reference/commandline/attach.md b/docs/reference/commandline/attach.md index b70c26f452..dd581ace9a 100644 --- a/docs/reference/commandline/attach.md +++ b/docs/reference/commandline/attach.md @@ -10,14 +10,17 @@ parent = "smn_cli" # attach - Usage: docker attach [OPTIONS] CONTAINER +```markdown +Usage: docker attach [OPTIONS] CONTAINER - Attach to a running container +Attach to a running container - --detach-keys="" Set up escape key sequence - --help Print usage - --no-stdin Do not attach STDIN - --sig-proxy=true Proxy all received signals to the process +Options: + --detach-keys string Override the key sequence for detaching a container + --help Print usage + --no-stdin Do not attach STDIN + --sig-proxy Proxy all received signals to the process (default true) +``` The `docker attach` command allows you to attach to a running container using the container's ID or name, either to view its ongoing output or to control it diff --git a/docs/reference/commandline/build.md b/docs/reference/commandline/build.md index 72426d659e..00fd85d61f 100644 --- a/docs/reference/commandline/build.md +++ b/docs/reference/commandline/build.md @@ -10,32 +10,38 @@ parent = "smn_cli" # build - Usage: docker build [OPTIONS] PATH | URL | - +```markdown +Usage: docker build [OPTIONS] PATH | URL | - - Build a new image from the source code at PATH +Build an image from a Dockerfile - --build-arg=[] Set build-time variables - --cpu-shares CPU Shares (relative weight) - --cgroup-parent="" Optional parent cgroup for the container - --cpu-period=0 Limit the CPU CFS (Completely Fair Scheduler) period - --cpu-quota=0 Limit the CPU CFS (Completely Fair Scheduler) quota - --cpuset-cpus="" CPUs in which to allow execution, e.g. `0-3`, `0,1` - --cpuset-mems="" MEMs in which to allow execution, e.g. `0-3`, `0,1` - --disable-content-trust=true Skip image verification - -f, --file="" Name of the Dockerfile (Default is 'PATH/Dockerfile') - --force-rm Always remove intermediate containers - --help Print usage - --isolation="" Container isolation technology - --label=[] Set metadata for an image - -m, --memory="" Memory limit for all build containers - --memory-swap="" A positive integer equal to memory plus swap. Specify -1 to enable unlimited swap. - --no-cache Do not use cache when building the image - --pull Always attempt to pull a newer version of the image - -q, --quiet Suppress the build output and print image ID on success - --rm=true Remove intermediate containers after a successful build - --shm-size=[] Size of `/dev/shm`. The format is ``. `number` must be greater than `0`. Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses `64m`. - -t, --tag=[] Name and optionally a tag in the 'name:tag' format - --ulimit=[] Ulimit options +Options: + --build-arg value Set build-time variables (default []) + --cgroup-parent string Optional parent cgroup for the container + --cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period + --cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota + -c, --cpu-shares int CPU shares (relative weight) + --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) + --cpuset-mems string MEMs in which to allow execution (0-3, 0,1) + --disable-content-trust Skip image verification (default true) + -f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile') + --force-rm Always remove intermediate containers + --help Print usage + --isolation string Container isolation technology + --label value Set metadata for an image (default []) + -m, --memory string Memory limit + --memory-swap string Swap limit equal to memory plus swap: '-1' to enable unlimited swap + --no-cache Do not use cache when building the image + --pull Always attempt to pull a newer version of the image + -q, --quiet Suppress the build output and print image ID on success + --rm Remove intermediate containers after a successful build (default true) + --shm-size string Size of /dev/shm, default value is 64MB. + The format is ``. `number` must be greater than `0`. + Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), + or `g` (gigabytes). If you omit the unit, the system uses bytes. + -t, --tag value Name and optionally a tag in the 'name:tag' format (default []) + --ulimit value Ulimit options (default []) +``` Builds Docker images from a Dockerfile and a "context". A build's context is the files located in the specified `PATH` or `URL`. The build process can refer diff --git a/docs/reference/commandline/cli.md b/docs/reference/commandline/cli.md index ac5f62d4bb..746b84b03a 100644 --- a/docs/reference/commandline/cli.md +++ b/docs/reference/commandline/cli.md @@ -14,16 +14,31 @@ weight = -2 To list available commands, either run `docker` with no parameters or execute `docker help`: - $ docker - Usage: docker [OPTIONS] COMMAND [arg...] - docker daemon [ --help | ... ] - docker [ --help | -v | --version ] +```bash +$ docker +Usage: docker [OPTIONS] COMMAND [arg...] + docker [ --help | -v | --version ] - -H, --host=[]: The socket(s) to talk to the Docker daemon in the format of tcp://host:port/path, unix:///path/to/socket, fd://* or fd://socketfd. +A self-sufficient runtime for containers. - A self-sufficient runtime for Linux containers. +Options: - ... + --config=~/.docker Location of client config files + -D, --debug Enable debug mode + -H, --host=[] Daemon socket(s) to connect to + -h, --help Print usage + -l, --log-level=info Set the logging level + --tls Use TLS; implied by --tlsverify + --tlscacert=~/.docker/ca.pem Trust certs signed only by this CA + --tlscert=~/.docker/cert.pem Path to TLS certificate file + --tlskey=~/.docker/key.pem Path to TLS key file + --tlsverify Use TLS and verify the remote + -v, --version Print version information and quit + +Commands: + attach Attach to a running container + # […] +``` Depending on your Docker system configuration, you may be required to preface each `docker` command with `sudo`. To avoid having to use `sudo` with the diff --git a/docs/reference/commandline/commit.md b/docs/reference/commandline/commit.md index ad25f64c84..acfb7c95be 100644 --- a/docs/reference/commandline/commit.md +++ b/docs/reference/commandline/commit.md @@ -10,15 +10,18 @@ parent = "smn_cli" # commit - Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] +```markdown +Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] - Create a new image from a container's changes +Create a new image from a container's changes - -a, --author="" Author (e.g., "John Hannibal Smith ") - -c, --change=[] Apply specified Dockerfile instructions while committing the image - --help Print usage - -m, --message="" Commit message - -p, --pause=true Pause container during commit +Options: + -a, --author string Author (e.g., "John Hannibal Smith ") + -c, --change value Apply Dockerfile instruction to the created image (default []) + --help Print usage + -m, --message string Commit message + -p, --pause Pause container during commit (default true) +``` It can be useful to commit a container's file changes or settings into a new image. This allows you debug a container by running an interactive shell, or to diff --git a/docs/reference/commandline/cp.md b/docs/reference/commandline/cp.md index 8afabc95bc..b3a0b78916 100644 --- a/docs/reference/commandline/cp.md +++ b/docs/reference/commandline/cp.md @@ -10,13 +10,21 @@ parent = "smn_cli" # cp - Usage: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH | - - docker cp [OPTIONS] SRC_PATH | - CONTAINER:DEST_PATH +```markdown +Usage: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- + docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH - Copy files/folders between a container and the local filesystem +Copy files/folders between a container and the local filesystem - -L, --follow-link Always follow symbol link in SRC_PATH - --help Print usage +Use '-' as the source to read a tar archive from stdin +and extract it to a directory destination in a container. +Use '-' as the destination to stream a tar archive of a +container source to stdout. + +Options: + -L, --follow-link Always follow symbol link in SRC_PATH + --help Print usage +``` The `docker cp` utility copies the contents of `SRC_PATH` to the `DEST_PATH`. You can copy from the container's file system to the local machine or the diff --git a/docs/reference/commandline/create.md b/docs/reference/commandline/create.md index fb84d38794..1d41c68665 100644 --- a/docs/reference/commandline/create.md +++ b/docs/reference/commandline/create.md @@ -12,95 +12,110 @@ parent = "smn_cli" Creates a new container. - Usage: docker create [OPTIONS] IMAGE [COMMAND] [ARG...] +```markdown +Usage: docker create [OPTIONS] IMAGE [COMMAND] [ARG...] - Create a new container +Create a new container - -a, --attach=[] Attach to STDIN, STDOUT or STDERR - --add-host=[] Add a custom host-to-IP mapping (host:ip) - --blkio-weight=0 Block IO weight (relative weight) - --blkio-weight-device=[] Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`) - --cpu-shares=0 CPU shares (relative weight) - --cap-add=[] Add Linux capabilities - --cap-drop=[] Drop Linux capabilities - --cgroup-parent="" Optional parent cgroup for the container - --cidfile="" Write the container ID to the file - --cpu-period=0 Limit CPU CFS (Completely Fair Scheduler) period - --cpu-quota=0 Limit CPU CFS (Completely Fair Scheduler) quota - --cpuset-cpus="" CPUs in which to allow execution (0-3, 0,1) - --cpuset-mems="" Memory nodes (MEMs) in which to allow execution (0-3, 0,1) - --device=[] Add a host device to the container - --device-read-bps=[] Limit read rate (bytes per second) from a device (e.g., --device-read-bps=/dev/sda:1mb) - --device-read-iops=[] Limit read rate (IO per second) from a device (e.g., --device-read-iops=/dev/sda:1000) - --device-write-bps=[] Limit write rate (bytes per second) to a device (e.g., --device-write-bps=/dev/sda:1mb) - --device-write-iops=[] Limit write rate (IO per second) to a device (e.g., --device-write-iops=/dev/sda:1000) - --disable-content-trust=true Skip image verification - --dns=[] Set custom DNS servers - --dns-opt=[] Set custom DNS options - --dns-search=[] Set custom DNS search domains - -e, --env=[] Set environment variables - --entrypoint="" Overwrite the default ENTRYPOINT of the image - --env-file=[] Read in a file of environment variables - --expose=[] Expose a port or a range of ports - --group-add=[] Add additional groups to join - -h, --hostname="" Container host name +Options: + --add-host value Add a custom host-to-IP mapping (host:ip) (default []) + -a, --attach value Attach to STDIN, STDOUT or STDERR (default []) + --blkio-weight value Block IO (relative weight), between 10 and 1000 + --blkio-weight-device value Block IO weight (relative device weight) (default []) + --cap-add value Add Linux capabilities (default []) + --cap-drop value Drop Linux capabilities (default []) + --cgroup-parent string Optional parent cgroup for the container + --cidfile string Write the container ID to the file + --cpu-percent int CPU percent (Windows only) + --cpu-period int Limit CPU CFS (Completely Fair Scheduler) period + --cpu-quota int Limit CPU CFS (Completely Fair Scheduler) quota + -c, --cpu-shares int CPU shares (relative weight) + --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) + --cpuset-mems string MEMs in which to allow execution (0-3, 0,1) + --device value Add a host device to the container (default []) + --device-read-bps value Limit read rate (bytes per second) from a device (default []) + --device-read-iops value Limit read rate (IO per second) from a device (default []) + --device-write-bps value Limit write rate (bytes per second) to a device (default []) + --device-write-iops value Limit write rate (IO per second) to a device (default []) + --disable-content-trust Skip image verification (default true) + --dns value Set custom DNS servers (default []) + --dns-opt value Set DNS options (default []) + --dns-search value Set custom DNS search domains (default []) + --entrypoint string Overwrite the default ENTRYPOINT of the image + -e, --env value Set environment variables (default []) + --env-file value Read in a file of environment variables (default []) + --expose value Expose a port or a range of ports (default []) + --group-add value Add additional groups to join (default []) + --health-cmd string Command to run to check health + --health-interval duration Time between running the check + --health-retries int Consecutive failures needed to report unhealthy + --health-timeout duration Maximum time to allow one check to run --help Print usage - -i, --interactive Keep STDIN open even if not attached - --ip="" Container IPv4 address (e.g. 172.30.100.104) - --ip6="" Container IPv6 address (e.g. 2001:db8::33) - --ipc="" IPC namespace to use - --isolation="" Container isolation technology - --kernel-memory="" Kernel memory limit - -l, --label=[] Set metadata on the container (e.g., --label=com.example.key=value) - --label-file=[] Read in a line delimited file of labels - --link=[] Add link to another container - --link-local-ip=[] Container IPv4/IPv6 link-local addresses (e.g. 169.254.0.77, fe80::77) - --log-driver="" Logging driver for container - --log-opt=[] Log driver specific options - -m, --memory="" Memory limit - --mac-address="" Container MAC address (e.g. 92:d0:c6:0a:29:33) - --memory-reservation="" Memory soft limit - --memory-swap="" A positive integer equal to memory plus swap. Specify -1 to enable unlimited swap. - --memory-swappiness="" Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. - --name="" Assign a name to the container - --net="bridge" Connect a container to a network + -h, --hostname string Container host name + -i, --interactive Keep STDIN open even if not attached + --io-maxbandwidth string Maximum IO bandwidth limit for the system drive (Windows only) + --io-maxiops uint Maximum IOps limit for the system drive (Windows only) + --ip string Container IPv4 address (e.g. 172.30.100.104) + --ip6 string Container IPv6 address (e.g. 2001:db8::33) + --ipc string IPC namespace to use + --isolation string Container isolation technology + --kernel-memory string Kernel memory limit + -l, --label value Set meta data on a container (default []) + --label-file value Read in a line delimited file of labels (default []) + --link value Add link to another container (default []) + --link-local-ip value Container IPv4/IPv6 link-local addresses (default []) + --log-driver string Logging driver for container + --log-opt value Log driver options (default []) + --mac-address string Container MAC address (e.g. 92:d0:c6:0a:29:33) + -m, --memory string Memory limit + --memory-reservation string Memory soft limit + --memory-swap string Swap limit equal to memory plus swap: '-1' to enable unlimited swap + --memory-swappiness int Tune container memory swappiness (0 to 100) (default -1) + --name string Assign a name to the container + --network-alias value Add network-scoped alias for the container (default []) + --network string Connect a container to a network (default "default") 'bridge': create a network stack on the default Docker bridge 'none': no networking 'container:': reuse another container's network stack 'host': use the Docker host network stack '|': connect to a user-defined network - --net-alias=[] Add network-scoped alias for the container - --oom-kill-disable Whether to disable OOM Killer for the container or not - --oom-score-adj=0 Tune the host's OOM preferences for containers (accepts -1000 to 1000) - -P, --publish-all Publish all exposed ports to random ports - -p, --publish=[] Publish a container's port(s) to the host - --pid="" PID namespace to use - --pids-limit=-1 Tune container pids limit (set -1 for unlimited), kernel >= 4.3 + --no-healthcheck Disable any container-specified HEALTHCHECK + --oom-kill-disable Disable OOM Killer + --oom-score-adj int Tune host's OOM preferences (-1000 to 1000) + --pid string PID namespace to use + --pids-limit int Tune container pids limit (set -1 for unlimited), kernel >= 4.3 --privileged Give extended privileges to this container + -p, --publish value Publish a container's port(s) to the host (default []) + -P, --publish-all Publish all exposed ports to random ports --read-only Mount the container's root filesystem as read only - --restart="no" Restart policy (no, on-failure[:max-retry], always, unless-stopped) - --runtime="" Name of the runtime to be used for that container - --security-opt=[] Security options - --stop-signal="SIGTERM" Signal to stop a container - --shm-size=[] Size of `/dev/shm`. The format is ``. `number` must be greater than `0`. Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses `64m`. - --storage-opt=[] Set storage driver options per container - --sysctl[=*[]*]] Configure namespaced kernel parameters at runtime - -t, --tty Allocate a pseudo-TTY - -u, --user="" Username or UID - --userns="" Container user namespace + --restart string Restart policy to apply when a container exits (default "no") + Possible values are: no, on-failure[:max-retry], always, unless-stopped + --runtime string Runtime to use for this container + --security-opt value Security Options (default []) + --shm-size string Size of /dev/shm, default value is 64MB. + The format is ``. `number` must be greater than `0`. + Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), + or `g` (gigabytes). If you omit the unit, the system uses bytes. + --stop-signal string Signal to stop a container, SIGTERM by default (default "SIGTERM") + --storage-opt value Set storage driver options per container (default []) + --sysctl value Sysctl options (default map[]) + --tmpfs value Mount a tmpfs directory (default []) + -t, --tty Allocate a pseudo-TTY + --ulimit value Ulimit options (default []) + -u, --user string Username or UID (format: [:]) + --userns string User namespace to use 'host': Use the Docker host user namespace '': Use the Docker daemon user namespace specified by `--userns-remap` option. - --ulimit=[] Ulimit options - --uts="" UTS namespace to use - -v, --volume=[host-src:]container-dest[:] - Bind mount a volume. The comma-delimited + --uts string UTS namespace to use + -v, --volume value Bind mount a volume (default []). The comma-delimited `options` are [rw|ro], [z|Z], [[r]shared|[r]slave|[r]private], and [nocopy]. The 'host-src' is an absolute path or a name value. - --volume-driver="" Container's volume driver - --volumes-from=[] Mount volumes from the specified container(s) - -w, --workdir="" Working directory inside the container + --volume-driver string Optional volume driver for the container + --volumes-from value Mount volumes from the specified container(s) (default []) + -w, --workdir string Working directory inside the container +``` The `docker create` command creates a writeable container layer over the specified image and prepares it for running the specified command. The diff --git a/docs/reference/commandline/diff.md b/docs/reference/commandline/diff.md index bda74eadad..8c01b8cdf2 100644 --- a/docs/reference/commandline/diff.md +++ b/docs/reference/commandline/diff.md @@ -10,11 +10,14 @@ parent = "smn_cli" # diff - Usage: docker diff [OPTIONS] CONTAINER +```markdown +Usage: docker diff CONTAINER - Inspect changes on a container's filesystem +Inspect changes on a container's filesystem - --help Print usage +Options: + --help Print usage +``` List the changed files and directories in a container᾿s filesystem There are 3 events that are listed in the `diff`: diff --git a/docs/reference/commandline/dockerd.md b/docs/reference/commandline/dockerd.md index ec44c0ab90..3a9c69c1d9 100644 --- a/docs/reference/commandline/dockerd.md +++ b/docs/reference/commandline/dockerd.md @@ -17,6 +17,7 @@ weight = -1 A self-sufficient runtime for linux containers. Options: + --add-runtime=[] Register an additional OCI compatible runtime --api-cors-header="" Set CORS headers in the remote API --authorization-plugin=[] Set authorization plugins to load -b, --bridge="" Attach containers to a network bridge @@ -60,7 +61,6 @@ weight = -1 -p, --pidfile="/var/run/docker.pid" Path to use for daemon PID file --raw-logs Full timestamps without ANSI coloring --registry-mirror=[] Preferred Docker registry mirror - --add-runtime=[] Register an additional OCI compatible runtime -s, --storage-driver="" Storage driver to use --selinux-enabled Enable selinux support --storage-opt=[] Set storage driver options @@ -566,6 +566,17 @@ options for `zfs` start with `zfs` and options for `btrfs` start with `btrfs`. Example use: $ docker daemon -s btrfs --storage-opt btrfs.min_space=10G +#### Overlay2 options + +* `overlay2.override_kernel_check` + + Overrides the Linux kernel version check allowing overlay2. Support for + specifying multiple lower directories needed by overlay2 was added to the + Linux kernel in 4.0.0. However some older kernel versions may be patched + to add multiple lower directory support for OverlayFS. This option should + only be used after verifying this support exists in the kernel. Applying + this option on a kernel without this support will cause failures on mount. + ## Docker runtime execution options The Docker daemon relies on a @@ -910,8 +921,8 @@ This option will completely disable user namespace mapping for the container's u The following standard Docker features are currently incompatible when running a Docker daemon with user namespaces enabled: - - sharing PID or NET namespaces with the host (`--pid=host` or `--net=host`) - - A `--readonly` container filesystem (this is a Linux kernel restriction against remounting with modified flags of a currently mounted filesystem when inside a user namespace) + - sharing PID or NET namespaces with the host (`--pid=host` or `--network=host`) + - A `--read-only` container filesystem (this is a Linux kernel restriction against remounting with modified flags of a currently mounted filesystem when inside a user namespace) - external (volume or graph) drivers which are unaware/incapable of using daemon user mappings - Using `--privileged` mode flag on `docker run` (unless also specifying `--userns=host`) @@ -1108,6 +1119,7 @@ The following daemon options must be configured for each daemon: -g, --graph=/var/lib/docker Root of the Docker runtime -p, --pidfile=/var/run/docker.pid Path to use for daemon PID file -H, --host=[] Daemon socket(s) to connect to +--iptables=true Enable addition of iptables rules --config-file=/etc/docker/daemon.json Daemon configuration file --tlscacert="~/.docker/ca.pem" Trust certs signed only by this CA --tlscert="~/.docker/cert.pem" Path to TLS certificate file @@ -1126,6 +1138,10 @@ set this parameter separately for each daemon. - `-p, --pidfile=/var/run/docker.pid` is the path where the process ID of the daemon is stored. Specify the path for your pid file here. - `--host=[]` specifies where the Docker daemon will listen for client connections. If unspecified, it defaults to `/var/run/docker.sock`. +- `--iptables=false` prevents the Docker daemon from adding iptables rules. If + multiple daemons manage iptables rules, they may overwrite rules set by + another daemon. Be aware that disabling this option requires you to manually + add iptables rules to expose container ports. - `--config-file=/etc/docker/daemon.json` is the path where configuration file is stored. You can use it instead of daemon flags. Specify the path for each daemon. - `--tls*` Docker daemon supports `--tlsverify` mode that enforces encrypted and authenticated remote connections. diff --git a/docs/reference/commandline/events.md b/docs/reference/commandline/events.md index 688c05a907..c966289d59 100644 --- a/docs/reference/commandline/events.md +++ b/docs/reference/commandline/events.md @@ -10,14 +10,17 @@ parent = "smn_cli" # events - Usage: docker events [OPTIONS] +```markdown +Usage: docker events [OPTIONS] - Get real time events from the server +Get real time events from the server - -f, --filter=[] Filter output based on conditions provided - --help Print usage - --since="" Show all events created since timestamp - --until="" Stream events until this timestamp +Options: + -f, --filter value Filter output based on conditions provided (default []) + --help Print usage + --since string Show all events created since timestamp + --until string Stream events until this timestamp +``` Docker containers report the following events: diff --git a/docs/reference/commandline/exec.md b/docs/reference/commandline/exec.md index 80796a59c9..a5e1d3c9c5 100644 --- a/docs/reference/commandline/exec.md +++ b/docs/reference/commandline/exec.md @@ -10,17 +10,19 @@ parent = "smn_cli" # exec - Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...] +```markdown +Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...] - Run a command in a running container +Run a command in a running container - -d, --detach Detached mode: run command in the background - --detach-keys Specify the escape key sequence used to detach a container - --help Print usage - -i, --interactive Keep STDIN open even if not attached - --privileged Give extended Linux capabilities to the command - -t, --tty Allocate a pseudo-TTY - -u, --user= Username or UID (format: [:]) + -d, --detach Detached mode: run command in the background + --detach-keys Override the key sequence for detaching a container + --help Print usage + -i, --interactive Keep STDIN open even if not attached + --privileged Give extended privileges to the command + -t, --tty Allocate a pseudo-TTY + -u, --user Username or UID (format: [:]) +``` The `docker exec` command runs a new command in a running container. diff --git a/docs/reference/commandline/export.md b/docs/reference/commandline/export.md index 90ffec62be..54e6e01a6e 100644 --- a/docs/reference/commandline/export.md +++ b/docs/reference/commandline/export.md @@ -10,12 +10,15 @@ parent = "smn_cli" # export - Usage: docker export [OPTIONS] CONTAINER +```markdown +Usage: docker export [OPTIONS] CONTAINER - Export the contents of a container's filesystem as a tar archive +Export a container's filesystem as a tar archive - --help Print usage - -o, --output="" Write to a file, instead of STDOUT +Options: + --help Print usage + -o, --output string Write to a file, instead of STDOUT +``` The `docker export` command does not export the contents of volumes associated with the container. If a volume is mounted on top of an existing directory in diff --git a/docs/reference/commandline/history.md b/docs/reference/commandline/history.md index d8750d83c0..895fd55ea9 100644 --- a/docs/reference/commandline/history.md +++ b/docs/reference/commandline/history.md @@ -10,14 +10,17 @@ parent = "smn_cli" # history - Usage: docker history [OPTIONS] IMAGE +```markdown +Usage: docker history [OPTIONS] IMAGE - Show the history of an image +Show the history of an image - -H, --human=true Print sizes and dates in human readable format - --help Print usage - --no-trunc Don't truncate output - -q, --quiet Only show numeric IDs +Options: + --help Print usage + -H, --human Print sizes and dates in human readable format (default true) + --no-trunc Don't truncate output + -q, --quiet Only show numeric IDs +``` To see how the `docker:latest` image was built: diff --git a/docs/reference/commandline/images.md b/docs/reference/commandline/images.md index b9f80980b0..af21a8197d 100644 --- a/docs/reference/commandline/images.md +++ b/docs/reference/commandline/images.md @@ -10,20 +10,24 @@ parent = "smn_cli" # images - Usage: docker images [OPTIONS] [REPOSITORY[:TAG]] +```markdown +Usage: docker images [OPTIONS] [REPOSITORY[:TAG]] - List images +List images - -a, --all Show all images (default hides intermediate images) - --digests Show digests - -f, --filter=[] Filter output based on these conditions: - - dangling=(true|false) - - label= or label== - - before=([:tag]||) - - since=([:tag]||) - --help Print usage - --no-trunc Don't truncate output - -q, --quiet Only show numeric IDs +Options: + -a, --all Show all images (default hides intermediate images) + --digests Show digests + -f, --filter value Filter output based on conditions provided (default []) + - dangling=(true|false) + - label= or label== + - before=([:tag]||) + - since=([:tag]||) + --format string Pretty-print images using a Go template + --help Print usage + --no-trunc Don't truncate output + -q, --quiet Only show numeric IDs +``` The default `docker images` will show all top level images, their repository and tags, and their size. diff --git a/docs/reference/commandline/import.md b/docs/reference/commandline/import.md index d4ca8d5775..2d2c88b4e8 100644 --- a/docs/reference/commandline/import.md +++ b/docs/reference/commandline/import.md @@ -10,15 +10,16 @@ parent = "smn_cli" # import - Usage: docker import file|URL|- [REPOSITORY[:TAG]] +```markdown +Usage: docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]] - Create an empty filesystem image and import the contents of the - tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) into it, then - optionally tag it. +Import the contents from a tarball to create a filesystem image - -c, --change=[] Apply specified Dockerfile instructions while importing the image - --help Print usage - -m, --message= Set commit message for imported image +Options: + -c, --change value Apply Dockerfile instruction to the created image (default []) + --help Print usage + -m, --message string Set commit message for imported image +``` You can specify a `URL` or `-` (dash) to take data directly from `STDIN`. The `URL` can point to an archive (.tar, .tar.gz, .tgz, .bzip, .tar.xz, or .txz) diff --git a/docs/reference/commandline/index.md b/docs/reference/commandline/index.md index 3643cdb810..75acb1c7fa 100644 --- a/docs/reference/commandline/index.md +++ b/docs/reference/commandline/index.md @@ -1,11 +1,11 @@ @@ -14,103 +14,129 @@ weight=-70 # The Docker commands -This section contains reference information on using Docker's command line client. Each command has a reference page along with samples. If you are unfamiliar with the command line, you should start by reading about how to [Use the Docker command line](cli.md). +This section contains reference information on using Docker's command line +client. Each command has a reference page along with samples. If you are +unfamiliar with the command line, you should start by reading about how to [Use +the Docker command line](cli.md). -You start the Docker daemon with the command line. How you start the daemon affects your Docker containers. For that reason you should also make sure to read the [`dockerd`](dockerd.md) reference page. +You start the Docker daemon with the command line. How you start the daemon +affects your Docker containers. For that reason you should also make sure to +read the [`dockerd`](dockerd.md) reference page. ### Docker management commands -* [dockerd](dockerd.md) -* [info](info.md) -* [inspect](inspect.md) -* [version](version.md) +| Command | Description | +|:--------|:-------------------------------------------------------------------| +| [dockerd](dockerd.md) | Launch the Docker daemon | +| [info](info.md) | Display system-wide information | +| [inspect](inspect.md)| Return low-level information on a container or image | +| [version](version.md) | Show the Docker version information | + ### Image commands -* [build](build.md) -* [commit](commit.md) -* [export](export.md) -* [history](history.md) -* [images](images.md) -* [import](import.md) -* [load](load.md) -* [rmi](rmi.md) -* [save](save.md) -* [tag](tag.md) +| Command | Description | +|:--------|:-------------------------------------------------------------------| +| [build](build.md) | Build an image from a Dockerfile | +| [commit](commit.md) | Create a new image from a container's changes | +| [export](export.md) | Export a container's filesystem as a tar archive | +| [history](history.md) | Show the history of an image | +| [images](images.md) | List images | +| [import](import.md) | Import the contents from a tarball to create a filesystem image | +| [load](load.md) | Load an image from a tar archive or STDIN | +| [rmi](rmi.md) | Remove one or more images | +| [save](save.md) | Save images to a tar archive | +| [tag](tag.md) | Tag an image into a repository | ### Container commands -* [attach](attach.md) -* [cp](cp.md) -* [create](create.md) -* [diff](diff.md) -* [events](events.md) -* [exec](exec.md) -* [kill](kill.md) -* [logs](logs.md) -* [pause](pause.md) -* [port](port.md) -* [ps](ps.md) -* [rename](rename.md) -* [restart](restart.md) -* [rm](rm.md) -* [run](run.md) -* [start](start.md) -* [stats](stats.md) -* [stop](stop.md) -* [top](top.md) -* [unpause](unpause.md) -* [update](update.md) -* [wait](wait.md) +| Command | Description | +|:--------|:-------------------------------------------------------------------| +| [attach](attach.md) | Attach to a running container | +| [cp](cp.md) | Copy files/folders from a container to a HOSTDIR or to STDOUT | +| [create](create.md) | Create a new container | +| [diff](diff.md) | Inspect changes on a container's filesystem | +| [events](events.md) | Get real time events from the server | +| [exec](exec.md) | Run a command in a running container | +| [kill](kill.md) | Kill a running container | +| [logs](logs.md) | Fetch the logs of a container | +| [pause](pause.md) | Pause all processes within a container | +| [port](port.md) | List port mappings or a specific mapping for the container | +| [ps](ps.md) | List containers | +| [rename](rename.md) | Rename a container | +| [restart](restart.md) | Restart a running container | +| [rm](rm.md) | Remove one or more containers | +| [run](run.md) | Run a command in a new container | +| [start](start.md) | Start one or more stopped containers | +| [stats](stats.md) | Display a live stream of container(s) resource usage statistics | +| [stop](stop.md) | Stop a running container | +| [top](top.md) | Display the running processes of a container | +| [unpause](unpause.md) | Unpause all processes within a container | +| [update](update.md) | Update configuration of one or more containers | +| [wait](wait.md) | Block until a container stops, then print its exit code | ### Hub and registry commands -* [login](login.md) -* [logout](logout.md) -* [pull](pull.md) -* [push](push.md) -* [search](search.md) +| Command | Description | +|:--------|:-------------------------------------------------------------------| +| [login](login.md) | Register or log in to a Docker registry | +| [logout](logout.md) | Log out from a Docker registry | +| [pull](pull.md) | Pull an image or a repository from a Docker registry | +| [push](push.md) | Push an image or a repository to a Docker registry | +| [search](search.md) | Search the Docker Hub for images | ### Network and connectivity commands -* [network_connect](network_connect.md) -* [network_create](network_create.md) -* [network_disconnect](network_disconnect.md) -* [network_inspect](network_inspect.md) -* [network_ls](network_ls.md) -* [network_rm](network_rm.md) +| Command | Description | +|:--------|:-------------------------------------------------------------------| +| [network connect](network_connect.md) | Connect a container to a network | +| [network create](network_create.md) | Create a new network | +| [network disconnect](network_disconnect.md) | Disconnect a container from a network | +| [network inspect](network_inspect.md) | Display information about a network | +| [network ls](network_ls.md) | Lists all the networks the Engine `daemon` knows about | +| [network rm](network_rm.md) | Removes one or more networks | + ### Shared data volume commands -* [volume_create](volume_create.md) -* [volume_inspect](volume_inspect.md) -* [volume_ls](volume_ls.md) -* [volume_rm](volume_rm.md) +| Command | Description | +|:--------|:-------------------------------------------------------------------| +| [volume create](volume_create.md) | Creates a new volume where containers can consume and store data | +| [volume inspect](volume_inspect.md) | Display information about a volume | +| [volume ls](volume_ls.md) | Lists all the volumes Docker knows about | +| [volume rm](volume_rm.md) | Remove one or more volumes | + ### Swarm node commands -* [node_accept](node_accept.md) -* [node_promote](node_promote.md) -* [node_demote](node_demote.md) -* [node_inspect](node_inspect.md) -* [node_update](node_update.md) -* [node_tasks](node_tasks.md) -* [node_ls](node_ls.md) -* [node_rm](node_rm.md) +| Command | Description | +|:--------|:-------------------------------------------------------------------| +| [node accept](node_accept.md) | Accept a node into the swarm | +| [node promote](node_promote.md) | Promote a node that is pending a promotion to manager | +| [node demote](node_demote.md) | Demotes an existing manager so that it is no longer a manager | +| [node inspect](node_inspect.md) | Inspect a node in the swarm | +| [node update](node_update.md) | Update attributes for a node | +| [node tasks](node_tasks.md) | List tasks running on a node | +| [node ls](node_ls.md) | List nodes in the swarm | +| [node rm](node_rm.md) | Remove a node from the swarm | ### Swarm swarm commands -* [swarm init](swarm_init.md) -* [swarm join](swarm_join.md) -* [swarm leave](swarm_leave.md) -* [swarm update](swarm_update.md) +| Command | Description | +|:--------|:-------------------------------------------------------------------| +| [swarm init](swarm_init.md) | Initialize a Swarm | +| [swarm join](swarm_join.md) | Join a Swarm as a manager node or worker node | +| [swarm leave](swarm_leave.md) | Remove the current node from the swarm | +| [swarm update](swarm_update.md) | Update attributes of a swarm | ### Swarm service commands -* [service create](service_create.md) -* [service inspect](service_inspect.md) -* [service ls](service_ls.md) -* [service rm](service_rm.md) -* [service scale](service_scale.md) -* [service tasks](service_tasks.md) -* [service update](service_update.md) +| Command | Description | +|:--------|:-------------------------------------------------------------------| +| [service create](service_create.md) | Create a new service | +| [service inspect](service_inspect.md) | Inspect a service | +| [service ls](service_ls.md) | List services in the swarm | +| [service rm](service_rm.md) | Reemove a swervice from the swarm | +| [service scale](service_scale.md) | Set the number of replicas for the desired state of the service | +| [service tasks](service_tasks.md) | List the tasks of a service | +| [service update](service_update.md) | Update the attributes of a service | diff --git a/docs/reference/commandline/info.md b/docs/reference/commandline/info.md index 21f483c282..88514d1606 100644 --- a/docs/reference/commandline/info.md +++ b/docs/reference/commandline/info.md @@ -10,13 +10,14 @@ parent = "smn_cli" # info +```markdown +Usage: docker info - Usage: docker info [OPTIONS] - - Display system-wide information - - --help Print usage +Display system-wide information +Options: + --help Print usage +``` This command displays system wide information regarding the Docker installation. Information displayed includes the kernel version, number of containers and images. diff --git a/docs/reference/commandline/inspect.md b/docs/reference/commandline/inspect.md index 34b60fbd46..7ccc7f7392 100644 --- a/docs/reference/commandline/inspect.md +++ b/docs/reference/commandline/inspect.md @@ -10,15 +10,17 @@ parent = "smn_cli" # inspect - Usage: docker inspect [OPTIONS] CONTAINER|IMAGE|TASK [CONTAINER|IMAGE|TASK...] +```markdown +Usage: docker inspect [OPTIONS] CONTAINER|IMAGE|TASK [CONTAINER|IMAGE|TASK...] - Return low-level information on a container or image or task +Return low-level information on a container, image or task - -f, --format="" Format the output using the given go template - --help Print usage - --type=container|image|task Return JSON for specified type, permissible - values are "image" or "container" or "task" - -s, --size Display total file sizes if the type is container + -f, --format Format the output using the given go template + --help Print usage + -s, --size Display total file sizes if the type is container + values are "image" or "container" or "task + --type Return JSON for specified type, (e.g image, container or task) +``` By default, this will render all results in a JSON array. If the container and image have the same name, this will return container JSON for unspecified type. diff --git a/docs/reference/commandline/kill.md b/docs/reference/commandline/kill.md index 6f20258707..e85ba61657 100644 --- a/docs/reference/commandline/kill.md +++ b/docs/reference/commandline/kill.md @@ -10,12 +10,15 @@ parent = "smn_cli" # kill - Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...] +```markdown +Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...] - Kill a running container using SIGKILL or a specified signal +Kill one or more running container - --help Print usage - -s, --signal="KILL" Signal to send to the container +Options: + --help Print usage + -s, --signal string Signal to send to the container (default "KILL") +``` The main process inside the container will be sent `SIGKILL`, or any signal specified with option `--signal`. diff --git a/docs/reference/commandline/load.md b/docs/reference/commandline/load.md index 60f4076c77..be8ed05cf2 100644 --- a/docs/reference/commandline/load.md +++ b/docs/reference/commandline/load.md @@ -10,14 +10,17 @@ parent = "smn_cli" # load - Usage: docker load [OPTIONS] +```markdown +Usage: docker load [OPTIONS] - Load an image from a tar archive or STDIN and shows image names or - IDs imported. +Load an image from a tar archive or STDIN - --help Print usage - -i, --input="" Read from a tar archive file, instead of STDIN. The tarball may be compressed with gzip, bzip, or xz - -q, --quiet Suppress the load progress bar but still outputs the imported images +Options: + --help Print usage + -i, --input string Read from tar archive file, instead of STDIN. + The tarball may be compressed with gzip, bzip, or xz + -q, --quiet Suppress the load output but still outputs the imported images +``` Loads a tarred repository from a file or the standard input stream. Restores both images and tags. diff --git a/docs/reference/commandline/login.md b/docs/reference/commandline/login.md index baff45f8c7..4c5670ea53 100644 --- a/docs/reference/commandline/login.md +++ b/docs/reference/commandline/login.md @@ -10,14 +10,17 @@ parent = "smn_cli" # login - Usage: docker login [OPTIONS] [SERVER] +```markdown +Usage: docker login [OPTIONS] [SERVER] - Log in to a Docker registry server, if no server is - specified "https://index.docker.io/v1/" is the default. +Log in to a Docker registry. +If no server is specified, the default is defined by the daemon. - --help Print usage - -p, --password="" Password - -u, --username="" Username +Options: + --help Print usage + -p, --password string Password + -u, --username string Username +``` If you want to login to a self-hosted registry you can specify this by adding the server name. diff --git a/docs/reference/commandline/logout.md b/docs/reference/commandline/logout.md index a3bb40c657..a073b34f88 100644 --- a/docs/reference/commandline/logout.md +++ b/docs/reference/commandline/logout.md @@ -10,12 +10,15 @@ parent = "smn_cli" # logout - Usage: docker logout [SERVER] +```markdown +Usage: docker logout [SERVER] - Log out from a Docker registry, if no server is - specified "https://index.docker.io/v1/" is the default. +Log out from a Docker registry. +If no server is specified, the default is defined by the daemon. - --help Print usage +Options: + --help Print usage +``` For example: diff --git a/docs/reference/commandline/logs.md b/docs/reference/commandline/logs.md index dd90c4dcc0..9074311405 100644 --- a/docs/reference/commandline/logs.md +++ b/docs/reference/commandline/logs.md @@ -10,16 +10,19 @@ parent = "smn_cli" # logs - Usage: docker logs [OPTIONS] CONTAINER +```markdown +Usage: docker logs [OPTIONS] CONTAINER - Fetch the logs of a container +Fetch the logs of a container - --details Show extra details provided to logs - -f, --follow Follow log output - --help Print usage - --since="" Show logs since timestamp - -t, --timestamps Show timestamps - --tail="all" Number of lines to show from the end of the logs +Options: + --details Show extra details provided to logs + -f, --follow Follow log output + --help Print usage + --since string Show logs since timestamp + --tail string Number of lines to show from the end of the logs (default "all") + -t, --timestamps Show timestamps +``` > **Note**: this command is available only for containers with `json-file` and > `journald` logging drivers. diff --git a/docs/reference/commandline/menu.md b/docs/reference/commandline/menu.md new file mode 100644 index 0000000000..9ade86d26a --- /dev/null +++ b/docs/reference/commandline/menu.md @@ -0,0 +1,26 @@ + + + + +# The Docker commands + +This section contains reference information on using Docker's command line +client. Each command has a reference page along with samples. If you are +unfamiliar with the command line, you should start by reading about how to +[Use the Docker command line](cli.md). + +You start the Docker daemon with the command line. How you start the daemon +affects your Docker containers. For that reason you should also make sure to +read the [`dockerd`](dockerd.md) reference page. + +For a list of Docker commands see [Command line reference guide](index.md). diff --git a/docs/reference/commandline/network_connect.md b/docs/reference/commandline/network_connect.md index c6a33ed15e..60accc763c 100644 --- a/docs/reference/commandline/network_connect.md +++ b/docs/reference/commandline/network_connect.md @@ -10,16 +10,19 @@ parent = "smn_cli" # network connect - Usage: docker network connect [OPTIONS] NETWORK CONTAINER +```markdown +Usage: docker network connect [OPTIONS] NETWORK CONTAINER - Connect a container to a network +Connect a container to a network - --alias=[] Add network-scoped alias for the container - --help Print usage - --ip IPv4 Address - --ip6 IPv6 Address - --link=[] Add a link to another container - --link-local-ip=[] IPv4/IPv6 link-local addresses +Options: + --alias value Add network-scoped alias for the container (default []) + --help Print usage + --ip string IP Address + --ip6 string IPv6 Address + --link value Add link to another container (default []) + --link-local-ip value Add a link-local address for the container (default []) +``` Connects a container to a network. You can connect a container by name or by ID. Once connected, the container can communicate with other containers in @@ -29,10 +32,10 @@ the same network. $ docker network connect multi-host-network container1 ``` -You can also use the `docker run --net=` option to start a container and immediately connect it to a network. +You can also use the `docker run --network=` option to start a container and immediately connect it to a network. ```bash -$ docker run -itd --net=multi-host-network busybox +$ docker run -itd --network=multi-host-network busybox ``` You can specify the IP address you want to be assigned to the container's interface. diff --git a/docs/reference/commandline/network_create.md b/docs/reference/commandline/network_create.md index 4d5e17bda6..bb08c07652 100644 --- a/docs/reference/commandline/network_create.md +++ b/docs/reference/commandline/network_create.md @@ -38,8 +38,8 @@ network driver you can specify that `DRIVER` here also. If you don't specify the `--driver` option, the command automatically creates a `bridge` network for you. When you install Docker Engine it creates a `bridge` network automatically. This network corresponds to the `docker0` bridge that Engine has traditionally relied -on. When launch a new container with `docker run` it automatically connects to -this bridge network. You cannot remove this default bridge network but you can +on. When you launch a new container with `docker run` it automatically connects to +this bridge network. You cannot remove this default bridge network, but you can create new ones using the `network create` command. ```bash @@ -48,7 +48,7 @@ $ docker network create -d bridge my-bridge-network Bridge networks are isolated networks on a single Engine installation. If you want to create a network that spans multiple Docker hosts each running an -Engine, you must create an `overlay` network. Unlike `bridge` networks overlay +Engine, you must create an `overlay` network. Unlike `bridge` networks, overlay networks require some pre-existing conditions before you can create one. These conditions are: @@ -65,9 +65,9 @@ The `dockerd` options that support the `overlay` network are: To read more about these options and how to configure them, see ["*Get started with multi-host network*"](../../userguide/networking/get-started-overlay.md). -It is also a good idea, though not required, that you install Docker Swarm on to +While not required, it is a good idea to install Docker Swarm to manage the cluster that makes up your network. Swarm provides sophisticated -discovery and server management that can assist your implementation. +discovery and server management tools that can assist your implementation. Once you have prepared the `overlay` network prerequisites you simply choose a Docker host in the cluster and issue the following to create the network: @@ -82,15 +82,15 @@ name conflicts. ## Connect containers -When you start a container use the `--net` flag to connect it to a network. -This adds the `busybox` container to the `mynet` network. +When you start a container, use the `--network` flag to connect it to a network. +This example adds the `busybox` container to the `mynet` network: ```bash -$ docker run -itd --net=mynet busybox +$ docker run -itd --network=mynet busybox ``` If you want to add a container to a network after the container is already -running use the `docker network connect` subcommand. +running, use the `docker network connect` subcommand. You can connect multiple containers to the same network. Once connected, the containers can communicate using only another container's IP address or name. diff --git a/docs/reference/commandline/network_disconnect.md b/docs/reference/commandline/network_disconnect.md index 10c4f16ea2..9d0c31580d 100644 --- a/docs/reference/commandline/network_disconnect.md +++ b/docs/reference/commandline/network_disconnect.md @@ -10,13 +10,15 @@ parent = "smn_cli" # network disconnect - Usage: docker network disconnect [OPTIONS] NETWORK CONTAINER +```markdown +Usage: docker network disconnect [OPTIONS] NETWORK CONTAINER +Disconnect a container from a network - Disconnects a container from a network - - -f, --force Force the container to disconnect from a network - --help Print usage +Options: + -f, --force Force the container to disconnect from a network + --help Print usage +``` Disconnects a container from a network. The container must be running to disconnect it from the network. diff --git a/docs/reference/commandline/network_inspect.md b/docs/reference/commandline/network_inspect.md index 251407e596..e72a5c793f 100644 --- a/docs/reference/commandline/network_inspect.md +++ b/docs/reference/commandline/network_inspect.md @@ -10,12 +10,15 @@ parent = "smn_cli" # network inspect - Usage: docker network inspect [OPTIONS] NETWORK [NETWORK..] +```markdown +Usage: docker network inspect [OPTIONS] NETWORK [NETWORK...] - Displays detailed information on a network +Display detailed information on one or more networks - -f, --format= Format the output using the given go template. - --help Print usage +Options: + -f, --format string Format the output using the given go template + --help Print usage +``` Returns information about one or more networks. By default, this command renders all results in a JSON object. For example, if you connect two containers to the default `bridge` network: diff --git a/docs/reference/commandline/network_ls.md b/docs/reference/commandline/network_ls.md index 6542b12ca7..49614bdaf4 100644 --- a/docs/reference/commandline/network_ls.md +++ b/docs/reference/commandline/network_ls.md @@ -10,13 +10,20 @@ parent = "smn_cli" # docker network ls - Usage: docker network ls [OPTIONS] +```markdown +Usage: docker network ls [OPTIONS] - Lists all the networks created by the user - -f, --filter=[] Filter output based on conditions provided - --help Print usage - --no-trunc Do not truncate the output - -q, --quiet Only display numeric IDs +List networks + +Aliases: + ls, list + +Options: + -f, --filter value Provide filter values (i.e. 'dangling=true') (default []) + --help Print usage + --no-trunc Do not truncate the output + -q, --quiet Only display volume names +``` Lists all the networks the Engine `daemon` knows about. This includes the networks that span across multiple hosts in a cluster, for example: @@ -35,10 +42,10 @@ Use the `--no-trunc` option to display the full network id: ```bash docker network ls --no-trunc NETWORK ID NAME DRIVER -18a2866682b85619a026c81b98a5e375bd33e1b0936a26cc497c283d27bae9b3 none null -c288470c46f6c8949c5f7e5099b5b7947b07eabe8d9a27d79a9cbf111adcbf47 host host -7b369448dccbf865d397c8d2be0cda7cf7edc6b0945f77d2529912ae917a0185 bridge bridge -95e74588f40db048e86320c6526440c504650a1ff3e9f7d60a497c4d2163e5bd foo bridge +18a2866682b85619a026c81b98a5e375bd33e1b0936a26cc497c283d27bae9b3 none null +c288470c46f6c8949c5f7e5099b5b7947b07eabe8d9a27d79a9cbf111adcbf47 host host +7b369448dccbf865d397c8d2be0cda7cf7edc6b0945f77d2529912ae917a0185 bridge bridge +95e74588f40db048e86320c6526440c504650a1ff3e9f7d60a497c4d2163e5bd foo bridge 63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161 dev bridge ``` @@ -46,7 +53,7 @@ c288470c46f6c8949c5f7e5099b5b7947b07eabe8d9a27d79a9cbf111adcbf47 host The filtering flag (`-f` or `--filter`) format is a `key=value` pair. If there is more than one filter, then pass multiple flags (e.g. `--filter "foo=bar" --filter "bif=baz"`). -Multiple filter flags are combined as an `OR` filter. For example, +Multiple filter flags are combined as an `OR` filter. For example, `-f type=custom -f type=builtin` returns both `custom` and `builtin` networks. The currently supported filters are: @@ -105,7 +112,7 @@ The following filter matches networks with the `usage` label regardless of its v ```bash $ docker network ls -f "label=usage" NETWORK ID NAME DRIVER -db9db329f835 test1 bridge +db9db329f835 test1 bridge f6e212da9dfd test2 bridge ``` diff --git a/docs/reference/commandline/network_rm.md b/docs/reference/commandline/network_rm.md index 0653458f9d..ce213b47fe 100644 --- a/docs/reference/commandline/network_rm.md +++ b/docs/reference/commandline/network_rm.md @@ -10,11 +10,17 @@ parent = "smn_cli" # network rm - Usage: docker network rm [OPTIONS] NETWORK [NETWORK...] +```markdown +Usage: docker network rm NETWORK [NETWORK]... - Deletes one or more networks +Remove a network - --help Print usage +Aliases: + rm, remove + +Options: + --help Print usage +``` Removes one or more networks by name or identifier. To remove a network, you must first disconnect any containers connected to it. diff --git a/docs/reference/commandline/node_accept.md b/docs/reference/commandline/node_accept.md index 21cb15fc36..73676c086c 100644 --- a/docs/reference/commandline/node_accept.md +++ b/docs/reference/commandline/node_accept.md @@ -10,9 +10,14 @@ parent = "smn_cli" # node accept - Usage: docker node accept NODE [NODE...] +```markdown +Usage: docker node accept NODE [NODE...] - Accept a node in the swarm +Accept a node in the swarm + +Options: + --help Print usage +``` Accept a node into the swarm. This command targets a docker engine that is a manager in the swarm cluster. diff --git a/docs/reference/commandline/node_demote.md b/docs/reference/commandline/node_demote.md index 97c779c71e..5d765adfaf 100644 --- a/docs/reference/commandline/node_demote.md +++ b/docs/reference/commandline/node_demote.md @@ -10,11 +10,17 @@ parent = "smn_cli" # node demote - Usage: docker node demote NODE [NODE...] +```markdown +Usage: docker node demote NODE [NODE...] - Demote a node as manager in the swarm +Demote a node from manager in the swarm -Demotes an existing Manager so that it is no longer a manager. This command targets a docker engine that is a manager in the swarm cluster. +Options: + --help Print usage + +``` + +Demotes an existing manager so that it is no longer a manager. This command targets a docker engine that is a manager in the swarm cluster. ```bash diff --git a/docs/reference/commandline/node_inspect.md b/docs/reference/commandline/node_inspect.md index 6c2836348a..ae13168da8 100644 --- a/docs/reference/commandline/node_inspect.md +++ b/docs/reference/commandline/node_inspect.md @@ -12,13 +12,16 @@ parent = "smn_cli" # node inspect - Usage: docker node inspect [OPTIONS] self|NODE [NODE...] +```markdown +Usage: docker node inspect [OPTIONS] self|NODE [NODE...] - Display detailed information on one or more nodes +Display detailed information on one or more nodes - -f, --format= Format the output using the given go template. - --help Print usage - -p, --pretty Print the information in a human friendly format. +Options: + -f, --format string Format the output using the given go template + --help Print usage + -p, --pretty Print the information in a human friendly format. +``` Returns information about a node. By default, this command renders all results in a JSON array. You can specify an alternate format to execute a diff --git a/docs/reference/commandline/node_ls.md b/docs/reference/commandline/node_ls.md index d2f9ec074c..bf5f70df27 100644 --- a/docs/reference/commandline/node_ls.md +++ b/docs/reference/commandline/node_ls.md @@ -12,24 +12,26 @@ parent = "smn_cli" # node ls - Usage: docker node ls [OPTIONS] +```markdown +Usage: docker node ls [OPTIONS] - List nodes in the swarm +List nodes in the swarm - Aliases: - ls, list +Aliases: + ls, list - Options: - -f, --filter value Filter output based on conditions provided - --help Print usage - -q, --quiet Only display IDs +Options: + -f, --filter value Filter output based on conditions provided + --help Print usage + -q, --quiet Only display IDs +``` Lists all the nodes that the Docker Swarm manager knows about. You can filter using the `-f` or `--filter` flag. Refer to the [filtering](#filtering) section for more information about available filter options. Example output: $ docker node ls - ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER + ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER 1bcef6utixb0l0ca7gxuivsj0 swarm-worker2 Accepted Ready Active 38ciaotwjuritcdtn9npbnkuz swarm-worker1 Accepted Ready Active e216jshn25ckzbvmwlnh5jr3g * swarm-manager1 Accepted Ready Active Reachable Yes @@ -53,7 +55,7 @@ The `name` filter matches on all or part of a node name. The following filter matches the node with a name equal to `swarm-master` string. $ docker node ls -f name=swarm-manager1 - ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER + ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER e216jshn25ckzbvmwlnh5jr3g * swarm-manager1 Accepted Ready Active Reachable Yes ### id @@ -61,7 +63,7 @@ The following filter matches the node with a name equal to `swarm-master` string The `id` filter matches all or part of a node's id. $ docker node ls -f id=1 - ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER + ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER 1bcef6utixb0l0ca7gxuivsj0 swarm-worker2 Accepted Ready Active @@ -74,7 +76,7 @@ The following filter matches nodes with the `usage` label regardless of its valu ```bash $ docker node ls -f "label=foo" -ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER +ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER 1bcef6utixb0l0ca7gxuivsj0 swarm-worker2 Accepted Ready Active ``` diff --git a/docs/reference/commandline/node_promote.md b/docs/reference/commandline/node_promote.md index 06c76c2a90..884fee8fc9 100644 --- a/docs/reference/commandline/node_promote.md +++ b/docs/reference/commandline/node_promote.md @@ -10,9 +10,14 @@ parent = "smn_cli" # node promote - Usage: docker node promote NODE [NODE...] +```markdown +Usage: docker node promote NODE [NODE...] - Promote a node as manager in the swarm +Promote a node to a manager in the swarm + +Options: + --help Print usage +``` Promotes a node that is pending a promotion to manager. This command targets a docker engine that is a manager in the swarm cluster. diff --git a/docs/reference/commandline/node_rm.md b/docs/reference/commandline/node_rm.md index 6eb9a873cf..613cf4fbd1 100644 --- a/docs/reference/commandline/node_rm.md +++ b/docs/reference/commandline/node_rm.md @@ -12,17 +12,21 @@ parent = "smn_cli" # node rm - Usage: docker node rm NODE [NODE...] +```markdown +Usage: docker node rm NODE [NODE...] - Remove a node from the swarm +Remove a node from the swarm - Aliases: - rm, remove +Aliases: + rm, remove - Options: - --help Print usage +Options: + --help Print usage +``` + +Removes specified nodes from a swarm. Rejects nodes with `Pending` +membership from the swarm. -Removes nodes that are specified. Example output: diff --git a/docs/reference/commandline/node_tasks.md b/docs/reference/commandline/node_tasks.md index 4cfa4cd23e..de84335e57 100644 --- a/docs/reference/commandline/node_tasks.md +++ b/docs/reference/commandline/node_tasks.md @@ -12,15 +12,17 @@ parent = "smn_cli" # node tasks - Usage: docker node tasks [OPTIONS] NODE +```markdown +Usage: docker node tasks [OPTIONS] self|NODE - List tasks running on a node +List tasks running on a node - Options: - -a, --all Display all instances - -f, --filter value Filter output based on conditions provided +Options: + -a, --all Display all instances + -f, --filter value Filter output based on conditions provided --help Print usage - -n, --no-resolve Do not map IDs to Names + -n, --no-resolve Do not map IDs to Names +``` Lists all the tasks on a Node that Docker knows about. You can filter using the `-f` or `--filter` flag. Refer to the [filtering](#filtering) section for more information about available filter options. @@ -45,7 +47,7 @@ The currently supported filters are: * [name](#name) * [id](#id) * [label](#label) -* [desired_state](#desired_state) +* [desired-state](#desired-state) #### name @@ -86,9 +88,9 @@ bg8c07zzg87di2mufeq51a2qp redis.7 redis redis:3.0.6 Running 9 minutes Ru ``` -#### desired_state +#### desired-state -The `desired_state` filter can take the values `running` and `accepted`. +The `desired-state` filter can take the values `running` and `accepted`. ## Related information diff --git a/docs/reference/commandline/node_update.md b/docs/reference/commandline/node_update.md index 8f005430a3..068958f6f0 100644 --- a/docs/reference/commandline/node_update.md +++ b/docs/reference/commandline/node_update.md @@ -12,16 +12,17 @@ parent = "smn_cli" ## update - Usage: docker node update [OPTIONS] Node +```markdown +Usage: docker node update [OPTIONS] NODE - Update a node +Update a node - Options: +Options: --availability string Availability of the node (active/pause/drain) --help Print usage --membership string Membership of the node (accepted/rejected) --role string Role of the node (worker/manager) - +``` ## Related information diff --git a/docs/reference/commandline/pause.md b/docs/reference/commandline/pause.md index 73d3c94935..629c6ed091 100644 --- a/docs/reference/commandline/pause.md +++ b/docs/reference/commandline/pause.md @@ -10,11 +10,14 @@ parent = "smn_cli" # pause - Usage: docker pause [OPTIONS] CONTAINER [CONTAINER...] +```markdown +Usage: docker pause CONTAINER [CONTAINER...] - Pause all processes within a container +Pause all processes within one or more containers - --help Print usage +Options: + --help Print usage +``` The `docker pause` command uses the cgroups freezer to suspend all processes in a container. Traditionally, when suspending a process the `SIGSTOP` signal is diff --git a/docs/reference/commandline/plugin_disable.md b/docs/reference/commandline/plugin_disable.md index dd5998e89f..2ddba071b4 100644 --- a/docs/reference/commandline/plugin_disable.md +++ b/docs/reference/commandline/plugin_disable.md @@ -11,11 +11,14 @@ parent = "smn_cli" # plugin disable (experimental) - Usage: docker plugin disable PLUGIN +```markdown +Usage: docker plugin disable PLUGIN - Disable a plugin +Disable a plugin - --help Print usage +Options: + --help Print usage +``` Disables a plugin. The plugin must be installed before it can be disabled, see [`docker plugin install`](plugin_install.md). diff --git a/docs/reference/commandline/plugin_enable.md b/docs/reference/commandline/plugin_enable.md index 323882325a..c7370e1818 100644 --- a/docs/reference/commandline/plugin_enable.md +++ b/docs/reference/commandline/plugin_enable.md @@ -11,11 +11,14 @@ parent = "smn_cli" # plugin enable (experimental) - Usage: docker plugin enable PLUGIN +```markdown +Usage: docker plugin enable PLUGIN - Enable a plugin +Enable a plugin - --help Print usage +Options: + --help Print usage +``` Enables a plugin. The plugin must be installed before it can be enabled, see [`docker plugin install`](plugin_install.md). diff --git a/docs/reference/commandline/plugin_inspect.md b/docs/reference/commandline/plugin_inspect.md index 67d63c236b..8131441a12 100644 --- a/docs/reference/commandline/plugin_inspect.md +++ b/docs/reference/commandline/plugin_inspect.md @@ -11,12 +11,14 @@ parent = "smn_cli" # plugin inspect (experimental) - Usage: docker plugin inspect PLUGIN +```markdown +Usage: docker plugin inspect PLUGIN - Return low-level information about a plugin - - --help Print usage +Inspect a plugin +Options: + --help Print usage +``` Returns information about a plugin. By default, this command renders all results in a JSON array. diff --git a/docs/reference/commandline/plugin_install.md b/docs/reference/commandline/plugin_install.md index 03d089584f..52f222c44c 100644 --- a/docs/reference/commandline/plugin_install.md +++ b/docs/reference/commandline/plugin_install.md @@ -11,11 +11,16 @@ parent = "smn_cli" # plugin install (experimental) - Usage: docker plugin install PLUGIN +```markdown +Usage: docker plugin install PLUGIN [OPTIONS] - Install a plugin +Install a plugin - --help Print usage +Options: + --disable do not enable the plugin on install + --grant-all-permissions grant all permissions necessary to run the plugin + --help Print usage +``` Installs and enables a plugin. Docker looks first for the plugin on your Docker host. If the plugin does not exist locally, then the plugin is pulled from diff --git a/docs/reference/commandline/plugin_ls.md b/docs/reference/commandline/plugin_ls.md index 624807aaad..31ccdb96c0 100644 --- a/docs/reference/commandline/plugin_ls.md +++ b/docs/reference/commandline/plugin_ls.md @@ -11,14 +11,17 @@ parent = "smn_cli" # plugin ls (experimental) - Usage: docker plugin ls +```markdown +Usage: docker plugin ls - List plugins +List plugins +Aliases: + ls, list + +Options: --help Print usage - - Aliases: - ls, list +``` Lists all the plugins that are currently installed. You can install plugins using the [`docker plugin install`](plugin_install.md) command. diff --git a/docs/reference/commandline/plugin_rm.md b/docs/reference/commandline/plugin_rm.md index 5f73b00fee..04dbc674cc 100644 --- a/docs/reference/commandline/plugin_rm.md +++ b/docs/reference/commandline/plugin_rm.md @@ -11,14 +11,17 @@ parent = "smn_cli" # plugin rm (experimental) - Usage: docker plugin rm PLUGIN +```markdown +Usage: docker plugin rm PLUGIN - Remove a plugin +Remove a plugin - --help Print usage +Aliases: + rm, remove - Aliases: - rm, remove +Options: + --help Print usage +``` Removes a plugin. You cannot remove a plugin if it is active, you must disable a plugin using the [`docker plugin disable`](plugin_disable.md) before removing diff --git a/docs/reference/commandline/port.md b/docs/reference/commandline/port.md index dbfae61039..e8da943c36 100644 --- a/docs/reference/commandline/port.md +++ b/docs/reference/commandline/port.md @@ -10,12 +10,14 @@ parent = "smn_cli" # port - Usage: docker port [OPTIONS] CONTAINER [PRIVATE_PORT[/PROTO]] +```markdown +Usage: docker port CONTAINER [PRIVATE_PORT[/PROTO]] - List port mappings for the CONTAINER, or lookup the public-facing port that is - NAT-ed to the PRIVATE_PORT +List port mappings or a specific mapping for the container - --help Print usage +Options: + --help Print usage +``` You can find out all the ports mapped by not specifying a `PRIVATE_PORT`, or just a specific mapping: diff --git a/docs/reference/commandline/ps.md b/docs/reference/commandline/ps.md index c661c653dc..63aaa56985 100644 --- a/docs/reference/commandline/ps.md +++ b/docs/reference/commandline/ps.md @@ -10,28 +10,31 @@ parent = "smn_cli" # ps - Usage: docker ps [OPTIONS] +```markdown +Usage: docker ps [OPTIONS] - List containers +List containers - -a, --all Show all containers (default shows just running) - -f, --filter=[] Filter output based on these conditions: - - exited= an exit code of - - label= or label== - - status=(created|restarting|running|paused|exited) - - name= a container's name - - id= a container's ID - - before=(|) - - since=(|) - - ancestor=([:tag]||) - containers created from an image or a descendant. - - volume=(|) - --format=[] Pretty-print containers using a Go template - --help Print usage - -l, --latest Show the latest created container (includes all states) - -n=-1 Show n last created containers (includes all states) - --no-trunc Don't truncate output - -q, --quiet Only display numeric IDs - -s, --size Display total file sizes +Options: + -a, --all Show all containers (default shows just running) + -f, --filter value Filter output based on conditions provided (default []) + - exited= an exit code of + - label= or label== + - status=(created|restarting|running|paused|exited) + - name= a container's name + - id= a container's ID + - before=(|) + - since=(|) + - ancestor=([:tag]||) + containers created from an image or a descendant. + --format string Pretty-print containers using a Go template + --help Print usage + -n, --last int Show n last created containers (includes all states) (default -1) + -l, --latest Show the latest created container (includes all states) + --no-trunc Don't truncate output + -q, --quiet Only display numeric IDs + -s, --size Display total file sizes +``` Running `docker ps --no-trunc` showing 2 linked containers. diff --git a/docs/reference/commandline/pull.md b/docs/reference/commandline/pull.md index 01abc9590c..f10c134863 100644 --- a/docs/reference/commandline/pull.md +++ b/docs/reference/commandline/pull.md @@ -10,13 +10,16 @@ parent = "smn_cli" # pull - Usage: docker pull [OPTIONS] NAME[:TAG] | [REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG] +```markdown +Usage: docker pull [OPTIONS] NAME[:TAG|@DIGEST] - Pull an image or a repository from the registry +Pull an image or a repository from a registry - -a, --all-tags Download all tagged images in the repository - --disable-content-trust=true Skip image verification - --help Print usage +Options: + -a, --all-tags Download all tagged images in the repository + --disable-content-trust Skip image verification (default true) + --help Print usage +``` Most of your images will be created on top of a base image from the [Docker Hub](https://hub.docker.com) registry. diff --git a/docs/reference/commandline/push.md b/docs/reference/commandline/push.md index 1e617865df..42601ed1bb 100644 --- a/docs/reference/commandline/push.md +++ b/docs/reference/commandline/push.md @@ -10,12 +10,15 @@ parent = "smn_cli" # push - Usage: docker push [OPTIONS] NAME[:TAG] +```markdown +Usage: docker push [OPTIONS] NAME[:TAG] - Push an image or a repository to the registry +Push an image or a repository to a registry - --disable-content-trust=true Skip image signing - --help Print usage +Options: + --disable-content-trust Skip image verification (default true) + --help Print usage +``` Use `docker push` to share your images to the [Docker Hub](https://hub.docker.com) registry or to a self-hosted one. diff --git a/docs/reference/commandline/rename.md b/docs/reference/commandline/rename.md index 3e2b370387..11bf5d0a14 100644 --- a/docs/reference/commandline/rename.md +++ b/docs/reference/commandline/rename.md @@ -10,10 +10,13 @@ parent = "smn_cli" # rename - Usage: docker rename [OPTIONS] OLD_NAME NEW_NAME +```markdown +Usage: docker rename OLD_NAME NEW_NAME - Rename a container +Rename a container - --help Print usage +Options: + --help Print usage +``` The `docker rename` command allows the container to be renamed to a different name. diff --git a/docs/reference/commandline/restart.md b/docs/reference/commandline/restart.md index 5e6633c8cf..661e16d4de 100644 --- a/docs/reference/commandline/restart.md +++ b/docs/reference/commandline/restart.md @@ -10,9 +10,12 @@ parent = "smn_cli" # restart - Usage: docker restart [OPTIONS] CONTAINER [CONTAINER...] +```markdown +Usage: docker restart [OPTIONS] CONTAINER [CONTAINER...] - Restart a container +Restart a container - --help Print usage - -t, --time=10 Seconds to wait for stop before killing the container +Options: + --help Print usage + -t, --time int Seconds to wait for stop before killing the container (default 10) +``` diff --git a/docs/reference/commandline/rm.md b/docs/reference/commandline/rm.md index bf615b55b8..319ef4dbbc 100644 --- a/docs/reference/commandline/rm.md +++ b/docs/reference/commandline/rm.md @@ -10,14 +10,17 @@ parent = "smn_cli" # rm - Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...] +```markdown +Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...] - Remove one or more containers +Remove one or more containers - -f, --force Force the removal of a running container (uses SIGKILL) - --help Print usage - -l, --link Remove the specified link - -v, --volumes Remove the volumes associated with the container +Options: + -f, --force Force the removal of a running container (uses SIGKILL) + --help Print usage + -l, --link Remove the specified link + -v, --volumes Remove the volumes associated with the container +``` ## Examples diff --git a/docs/reference/commandline/rmi.md b/docs/reference/commandline/rmi.md index f02734e8b4..328d9fe140 100644 --- a/docs/reference/commandline/rmi.md +++ b/docs/reference/commandline/rmi.md @@ -10,13 +10,16 @@ parent = "smn_cli" # rmi - Usage: docker rmi [OPTIONS] IMAGE [IMAGE...] +```markdown +Usage: docker rmi [OPTIONS] IMAGE [IMAGE...] - Remove one or more images +Remove one or more images - -f, --force Force removal of the image - --help Print usage - --no-prune Do not delete untagged parents +Options: + -f, --force Force removal of the image + --help Print usage + --no-prune Do not delete untagged parents +``` You can remove an image using its short or long ID, its tag, or its digest. If an image has one or more tag referencing it, you must remove all of them before diff --git a/docs/reference/commandline/run.md b/docs/reference/commandline/run.md index ad009aa872..841b63572e 100644 --- a/docs/reference/commandline/run.md +++ b/docs/reference/commandline/run.md @@ -10,109 +10,120 @@ parent = "smn_cli" # run - Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] +```markdown +Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] - Run a command in a new container +Run a command in a new container - -a, --attach=[] Attach to STDIN, STDOUT or STDERR - --add-host=[] Add a custom host-to-IP mapping (host:ip) - --blkio-weight=0 Block IO weight (relative weight) - --blkio-weight-device=[] Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`) - --cpu-shares=0 CPU shares (relative weight) - --cap-add=[] Add Linux capabilities - --cap-drop=[] Drop Linux capabilities - --cgroup-parent="" Optional parent cgroup for the container - --cidfile="" Write the container ID to the file - --cpu-percent=0 Limit percentage of CPU available for execution by the container. Windows daemon only. - --cpu-period=0 Limit CPU CFS (Completely Fair Scheduler) period - --cpu-quota=0 Limit CPU CFS (Completely Fair Scheduler) quota - --cpuset-cpus="" CPUs in which to allow execution (0-3, 0,1) - --cpuset-mems="" Memory nodes (MEMs) in which to allow execution (0-3, 0,1) - -d, --detach Run container in background and print container ID - --detach-keys Specify the escape key sequence used to detach a container - --device=[] Add a host device to the container - --device-read-bps=[] Limit read rate (bytes per second) from a device (e.g., --device-read-bps=/dev/sda:1mb) - --device-read-iops=[] Limit read rate (IO per second) from a device (e.g., --device-read-iops=/dev/sda:1000) - --device-write-bps=[] Limit write rate (bytes per second) to a device (e.g., --device-write-bps=/dev/sda:1mb) - --device-write-iops=[] Limit write rate (IO per second) to a device (e.g., --device-write-bps=/dev/sda:1000) - --disable-content-trust=true Skip image verification - --dns=[] Set custom DNS servers - --dns-opt=[] Set custom DNS options - --dns-search=[] Set custom DNS search domains - -e, --env=[] Set environment variables - --entrypoint="" Overwrite the default ENTRYPOINT of the image - --env-file=[] Read in a file of environment variables - --expose=[] Expose a port or a range of ports - --group-add=[] Add additional groups to run as - -h, --hostname="" Container host name +Options: + --add-host value Add a custom host-to-IP mapping (host:ip) (default []) + -a, --attach value Attach to STDIN, STDOUT or STDERR (default []) + --blkio-weight value Block IO (relative weight), between 10 and 1000 + --blkio-weight-device value Block IO weight (relative device weight) (default []) + --cap-add value Add Linux capabilities (default []) + --cap-drop value Drop Linux capabilities (default []) + --cgroup-parent string Optional parent cgroup for the container + --cidfile string Write the container ID to the file + --cpu-percent int CPU percent (Windows only) + --cpu-period int Limit CPU CFS (Completely Fair Scheduler) period + --cpu-quota int Limit CPU CFS (Completely Fair Scheduler) quota + -c, --cpu-shares int CPU shares (relative weight) + --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) + --cpuset-mems string MEMs in which to allow execution (0-3, 0,1) + -d, --detach Run container in background and print container ID + --detach-keys string Override the key sequence for detaching a container + --device value Add a host device to the container (default []) + --device-read-bps value Limit read rate (bytes per second) from a device (default []) + --device-read-iops value Limit read rate (IO per second) from a device (default []) + --device-write-bps value Limit write rate (bytes per second) to a device (default []) + --device-write-iops value Limit write rate (IO per second) to a device (default []) + --disable-content-trust Skip image verification (default true) + --dns value Set custom DNS servers (default []) + --dns-opt value Set DNS options (default []) + --dns-search value Set custom DNS search domains (default []) + --entrypoint string Overwrite the default ENTRYPOINT of the image + -e, --env value Set environment variables (default []) + --env-file value Read in a file of environment variables (default []) + --expose value Expose a port or a range of ports (default []) + --group-add value Add additional groups to join (default []) + --health-cmd string Command to run to check health + --health-interval duration Time between running the check + --health-retries int Consecutive failures needed to report unhealthy + --health-timeout duration Maximum time to allow one check to run --help Print usage - -i, --interactive Keep STDIN open even if not attached - --ip="" Container IPv4 address (e.g. 172.30.100.104) - --ip6="" Container IPv6 address (e.g. 2001:db8::33) - --ipc="" IPC namespace to use - --isolation="" Container isolation technology - --kernel-memory="" Kernel memory limit - -l, --label=[] Set metadata on the container (e.g., --label=com.example.key=value) - --label-file=[] Read in a file of labels (EOL delimited) - --link=[] Add link to another container - --link-local-ip=[] Container IPv4/IPv6 link-local addresses (e.g. 169.254.0.77, fe80::77) - --log-driver="" Logging driver for container - --log-opt=[] Log driver specific options - -m, --memory="" Memory limit - --mac-address="" Container MAC address (e.g. 92:d0:c6:0a:29:33) - --io-maxbandwidth="" Maximum IO bandwidth limit for the system drive + -h, --hostname string Container host name + -i, --interactive Keep STDIN open even if not attached + --io-maxbandwidth string Maximum IO bandwidth limit for the system drive (Windows only) (Windows only). The format is ``. Unit is optional and can be `b` (bytes per second), `k` (kilobytes per second), `m` (megabytes per second), or `g` (gigabytes per second). If you omit the unit, the system uses bytes per second. --io-maxbandwidth and --io-maxiops are mutually exclusive options. - --io-maxiops=0 Maximum IO per second limit for the system drive (Windows only). - --io-maxbandwidth and --io-maxiops are mutually exclusive options. - --memory-reservation="" Memory soft limit - --memory-swap="" A positive integer equal to memory plus swap. Specify -1 to enable unlimited swap. - --memory-swappiness="" Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. - --name="" Assign a name to the container - --net="bridge" Connect a container to a network + --io-maxiops uint Maximum IOps limit for the system drive (Windows only) + --ip string Container IPv4 address (e.g. 172.30.100.104) + --ip6 string Container IPv6 address (e.g. 2001:db8::33) + --ipc string IPC namespace to use + --isolation string Container isolation technology + --kernel-memory string Kernel memory limit + -l, --label value Set meta data on a container (default []) + --label-file value Read in a line delimited file of labels (default []) + --link value Add link to another container (default []) + --link-local-ip value Container IPv4/IPv6 link-local addresses (default []) + --log-driver string Logging driver for container + --log-opt value Log driver options (default []) + --mac-address string Container MAC address (e.g. 92:d0:c6:0a:29:33) + -m, --memory string Memory limit + --memory-reservation string Memory soft limit + --memory-swap string Swap limit equal to memory plus swap: '-1' to enable unlimited swap + --memory-swappiness int Tune container memory swappiness (0 to 100) (default -1). + --name string Assign a name to the container + --network-alias value Add network-scoped alias for the container (default []) + --network string Connect a container to a network 'bridge': create a network stack on the default Docker bridge 'none': no networking 'container:': reuse another container's network stack 'host': use the Docker host network stack '|': connect to a user-defined network - --net-alias=[] Add network-scoped alias for the container - --oom-kill-disable Whether to disable OOM Killer for the container or not - --oom-score-adj=0 Tune the host's OOM preferences for containers (accepts -1000 to 1000) - -P, --publish-all Publish all exposed ports to random ports - -p, --publish=[] Publish a container's port(s) to the host - --pid="" PID namespace to use - --pids-limit=-1 Tune container pids limit (set -1 for unlimited), kernel >= 4.3 + --no-healthcheck Disable any container-specified HEALTHCHECK + --oom-kill-disable Disable OOM Killer + --oom-score-adj int Tune host's OOM preferences (-1000 to 1000) + --pid string PID namespace to use + --pids-limit int Tune container pids limit (set -1 for unlimited) --privileged Give extended privileges to this container + -p, --publish value Publish a container's port(s) to the host (default []) + -P, --publish-all Publish all exposed ports to random ports --read-only Mount the container's root filesystem as read only - --restart="no" Restart policy (no, on-failure[:max-retry], always, unless-stopped) + --restart string Restart policy to apply when a container exits (default "no") + Possible values are : no, on-failuer[:max-retry], always, unless-stopped --rm Automatically remove the container when it exits - --runtime="" Name of the runtime to be used for that container - --shm-size=[] Size of `/dev/shm`. The format is ``. `number` must be greater than `0`. Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses `64m`. - --security-opt=[] Security Options - --sig-proxy=true Proxy received signals to the process - --stop-signal="SIGTERM" Signal to stop a container - --storage-opt=[] Set storage driver options per container - --sysctl[=*[]*]] Configure namespaced kernel parameters at runtime - -t, --tty Allocate a pseudo-TTY - -u, --user="" Username or UID (format: [:]) - --userns="" Container user namespace + --runtime string Runtime to use for this container + --security-opt value Security Options (default []) + --shm-size string Size of /dev/shm, default value is 64MB. + The format is ``. `number` must be greater than `0`. + Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), + or `g` (gigabytes). If you omit the unit, the system uses bytes. + --sig-proxy Proxy received signals to the process (default true) + --stop-signal string Signal to stop a container, SIGTERM by default (default "SIGTERM") + --storage-opt value Set storage driver options per container (default []) + --sysctl value Sysctl options (default map[]) + --tmpfs value Mount a tmpfs directory (default []) + -t, --tty Allocate a pseudo-TTY + --ulimit value Ulimit options (default []) + -u, --user string Username or UID (format: [:]) + --userns string User namespace to use 'host': Use the Docker host user namespace '': Use the Docker daemon user namespace specified by `--userns-remap` option. - --ulimit=[] Ulimit options - --uts="" UTS namespace to use - -v, --volume=[host-src:]container-dest[:] - Bind mount a volume. The comma-delimited + --uts string UTS namespace to use + -v, --volume value Bind mount a volume (default []). The comma-delimited `options` are [rw|ro], [z|Z], [[r]shared|[r]slave|[r]private], and [nocopy]. The 'host-src' is an absolute path or a name value. - --volume-driver="" Container's volume driver - --volumes-from=[] Mount volumes from the specified container(s) - -w, --workdir="" Working directory inside the container + --volume-driver string Optional volume driver for the container + --volumes-from value Mount volumes from the specified container(s) (default []) + -w, --workdir string Working directory inside the container +``` The `docker run` command first `creates` a writeable container layer over the specified image, and then `starts` it using the specified command. That is, @@ -179,7 +190,7 @@ flag exists to allow special use-cases, like running Docker within Docker. $ docker run -w /path/to/dir/ -i -t ubuntu pwd The `-w` lets the command being executed inside directory given, here -`/path/to/dir/`. If the path does not exists it is created inside the container. +`/path/to/dir/`. If the path does not exist it is created inside the container. ### Set storage driver options per container @@ -349,20 +360,20 @@ For additional information on working with labels, see [*Labels - custom metadata in Docker*](../../userguide/labels-custom-metadata.md) in the Docker User Guide. -### Connect a container to a network (--net) +### Connect a container to a network (--network) -When you start a container use the `--net` flag to connect it to a network. +When you start a container use the `--network` flag to connect it to a network. This adds the `busybox` container to the `my-net` network. ```bash -$ docker run -itd --net=my-net busybox +$ docker run -itd --network=my-net busybox ``` You can also choose the IP addresses for the container with `--ip` and `--ip6` flags when you start the container on a user-defined network. ```bash -$ docker run -itd --net=my-net --ip=10.10.9.75 busybox +$ docker run -itd --network=my-net --ip=10.10.9.75 busybox ``` If you want to add a running container to a network use the `docker network connect` subcommand. @@ -662,4 +673,4 @@ network namespace, run this command: `Network Namespace`: Sysctls beginning with net.* - If you use the `--net=host` option using these sysctls will not be allowed. + If you use the `--network=host` option using these sysctls will not be allowed. diff --git a/docs/reference/commandline/save.md b/docs/reference/commandline/save.md index 23fc671210..f7d1fdedcb 100644 --- a/docs/reference/commandline/save.md +++ b/docs/reference/commandline/save.md @@ -10,12 +10,15 @@ parent = "smn_cli" # save - Usage: docker save [OPTIONS] IMAGE [IMAGE...] +```markdown +Usage: docker save [OPTIONS] IMAGE [IMAGE...] - Save one or more images to a tar archive (streamed to STDOUT by default) +Save one or more images to a tar archive (streamed to STDOUT by default) - --help Print usage - -o, --output="" Write to a file, instead of STDOUT +Options: + --help Print usage + -o, --output string Write to a file, instead of STDOUT +``` Produces a tarred repository to the standard output stream. Contains all parent layers, and all tags + versions, or specified `repo:tag`, for diff --git a/docs/reference/commandline/search.md b/docs/reference/commandline/search.md index fff426d38d..988db8bf1f 100644 --- a/docs/reference/commandline/search.md +++ b/docs/reference/commandline/search.md @@ -10,17 +10,20 @@ parent = "smn_cli" # search - Usage: docker search [OPTIONS] TERM +```markdown +Usage: docker search [OPTIONS] TERM - Search the Docker Hub for images +Search the Docker Hub for images - --filter=[] Filter output based on these conditions: - - is-automated=(true|false) - - is-official=(true|false) - - stars= - image has at least 'number' stars - --help Print usage - --limit=25 Maximum returned search results - --no-trunc Don't truncate output +Options: + -f, --filter value Filter output based on conditions provided (default []) + - is-automated=(true|false) + - is-official=(true|false) + - stars= - image has at least 'number' stars + --help Print usage + --limit int Max number of search results (default 25) + --no-trunc Don't truncate output +``` Search [Docker Hub](https://hub.docker.com) for images @@ -49,7 +52,7 @@ This example displays images with a name containing 'busybox': ofayau/busybox-libc32 Busybox with 32 bits (and 64 bits) libs 1 [OK] peelsky/zulu-openjdk-busybox 1 [OK] skomma/busybox-data Docker image suitable for data volume cont... 1 [OK] - elektritter/busybox-teamspeak Leightweight teamspeak3 container based on... 1 [OK] + elektritter/busybox-teamspeak Lightweight teamspeak3 container based on... 1 [OK] socketplane/busybox 1 [OK] oveits/docker-nginx-busybox This is a tiny NginX docker image based on... 0 [OK] ggtools/busybox-ubuntu Busybox ubuntu version with extra goodies 0 [OK] diff --git a/docs/reference/commandline/service_create.md b/docs/reference/commandline/service_create.md index 34e2a7a7e1..b21f299a0c 100644 --- a/docs/reference/commandline/service_create.md +++ b/docs/reference/commandline/service_create.md @@ -14,13 +14,13 @@ parent = "smn_cli" # service create ```Markdown -Usage: docker service create [OPTIONS] IMAGE [COMMAND] [ARG...] +Usage: docker service create [OPTIONS] IMAGE [COMMAND] [ARG...] Create a new service Options: --constraint value Placement constraints (default []) - --endpoint-mode string Endpoint mode(Valid values: VIP, DNSRR) + --endpoint-mode string Endpoint mode (vip or dnsrr) -e, --env value Set environment variables (default []) --help Print usage -l, --label value Service labels (default []) @@ -31,10 +31,11 @@ Options: --name string Service name --network value Network attachments (default []) -p, --publish value Publish a port as a node port (default []) + --registry-auth Send registry authentication details to Swarm agents --replicas value Number of tasks (default none) --reserve-cpu value Reserve CPUs (default 0.000) --reserve-memory value Reserve Memory (default 0 B) - --restart-condition string Restart when condition is met (none, on_failure, or any) + --restart-condition string Restart when condition is met (none, on-failure, or any) --restart-delay value Delay between restart attempts (default none) --restart-max-attempts value Maximum number of restarts before giving up (default none) --restart-window value Window used to evaluate the restart policy (default none) @@ -95,7 +96,7 @@ ID NAME REPLICAS IMAGE COMMAND ``` -### Create a service with a rolling update constraints +### Create a service with a rolling update policy ```bash @@ -134,7 +135,7 @@ $ docker service create \ For more information about labels, refer to [apply custom metadata](../../userguide/labels-custom-metadata.md) -### Service mode +### Set service mode Is this a replicated service or a global service. A replicated service runs as many tasks as specified, while a global service runs on each active node in the @@ -146,6 +147,33 @@ The following command creates a "global" service: $ docker service create --name redis_2 --mode global redis:3.0.6 ``` +### Specify service constraints + +You can limit the set of nodes where a task can be scheduled by defining +constraint expressions. Multiple constraints find nodes that satisfy every +expression (AND match). Constraints can match node or Docker Engine labels as +follows: + +| node attribute | matches | example | +|:------------- |:-------------| :---------------------------------------------| +| node.id | node ID | `node.id == 2ivku8v2gvtg4` | +| node.hostname | node hostname | `node.hostname != node-2` | +| node.role | node role: manager | `node.role == manager` | +| node.labels | user defined node labels | `node.labels.security == high` | +| engine.labels | Docker Engine's labels | `engine.labels.operatingsystem == ubuntu 14.04`| + +`engine.labels` apply to Docker Engine labels like operating system, +drivers, etc. Swarm administrators add `node.labels` for operational purposes by +using the `docker node update` command. + +For example, the following limits tasks for the redis service to nodes where the +node type label equals queue: + +```bash +$ docker service create \ + --name redis_2 \ + --constraint node.labels.type == queue +``` ## Related information diff --git a/docs/reference/commandline/service_inspect.md b/docs/reference/commandline/service_inspect.md index 13116d83de..5f4b09d28d 100644 --- a/docs/reference/commandline/service_inspect.md +++ b/docs/reference/commandline/service_inspect.md @@ -13,7 +13,7 @@ parent = "smn_cli" # service inspect ```Markdown -Usage: docker service inspect [OPTIONS] SERVICE [SERVICE...] +Usage: docker service inspect [OPTIONS] SERVICE [SERVICE...] Display detailed information on one or more services diff --git a/docs/reference/commandline/service_ls.md b/docs/reference/commandline/service_ls.md index 543c1d6e71..14cf2b43e4 100644 --- a/docs/reference/commandline/service_ls.md +++ b/docs/reference/commandline/service_ls.md @@ -13,8 +13,6 @@ parent = "smn_cli" # service ls ```Markdown -docker service ls --help - Usage: docker service ls [OPTIONS] List services diff --git a/docs/reference/commandline/service_scale.md b/docs/reference/commandline/service_scale.md index 272dcc849a..9a6721b016 100644 --- a/docs/reference/commandline/service_scale.md +++ b/docs/reference/commandline/service_scale.md @@ -12,13 +12,14 @@ parent = "smn_cli" # service scale - Usage: docker service scale SERVICE=REPLICAS [SERVICE=REPLICAS...] +```markdown +Usage: docker service scale SERVICE=REPLICAS [SERVICE=REPLICAS...] - Scale one or multiple services - - Options: - --help Print usage +Scale one or multiple services +Options: + --help Print usage +``` ## Examples diff --git a/docs/reference/commandline/service_tasks.md b/docs/reference/commandline/service_tasks.md index e6cbcf935e..cceec92039 100644 --- a/docs/reference/commandline/service_tasks.md +++ b/docs/reference/commandline/service_tasks.md @@ -54,14 +54,14 @@ bk658fpbex0d57cqcwoe3jthu redis.2 redis redis:3.0.6 Running 9 seconds Ru The filtering flag (`-f` or `--filter`) format is a `key=value` pair. If there is more than one filter, then pass multiple flags (e.g. `--filter "foo=bar" --filter "bif=baz"`). -Multiple filter flags are combined as an `OR` filter. For example, -`-f type=custom -f type=builtin` returns both `custom` and `builtin` networks. +Multiple filter flags are combined as an `OR` filter. For example, +`-f name=redis.1 -f name=redis.7` returns both `redis.1` and `redis.7` tasks. The currently supported filters are: * [id](#id) * [name](#name) -* [desired_state](#desired_state) +* [desired-state](#desired-state) #### ID @@ -86,9 +86,9 @@ ID NAME SERVICE IMAGE DESIRED STATE LAST S ``` -#### desired_state +#### desired-state -The `desired_state` filter can take the values `running` and `accepted`. +The `desired-state` filter can take the values `running` and `accepted`. ## Related information diff --git a/docs/reference/commandline/service_update.md b/docs/reference/commandline/service_update.md index afff2041c4..131b37b96e 100644 --- a/docs/reference/commandline/service_update.md +++ b/docs/reference/commandline/service_update.md @@ -13,7 +13,7 @@ parent = "smn_cli" # service update ```Markdown -Usage: docker service update [OPTIONS] SERVICE +Usage: docker service update [OPTIONS] SERVICE Update a service @@ -21,22 +21,22 @@ Options: --arg value Service command args (default []) --command value Service command (default []) --constraint value Placement constraints (default []) - --endpoint-mode string Endpoint mode(Valid values: VIP, DNSRR) + --endpoint-mode string Endpoint mode (vip or dnsrr) -e, --env value Set environment variables (default []) --help Print usage --image string Service image tag -l, --label value Service labels (default []) --limit-cpu value Limit CPUs (default 0.000) --limit-memory value Limit Memory (default 0 B) - --mode string Service mode (replicated or global) (default "replicated") -m, --mount value Attach a mount to the service --name string Service name --network value Network attachments (default []) -p, --publish value Publish a port as a node port (default []) + --registry-auth Send registry authentication details to Swarm agents --replicas value Number of tasks (default none) --reserve-cpu value Reserve CPUs (default 0.000) --reserve-memory value Reserve Memory (default 0 B) - --restart-condition string Restart when condition is met (none, on_failure, or any) + --restart-condition string Restart when condition is met (none, on-failure, or any) --restart-delay value Delay between restart attempts (default none) --restart-max-attempts value Maximum number of restarts before giving up (default none) --restart-window value Window used to evaluate the restart policy (default none) diff --git a/docs/reference/commandline/start.md b/docs/reference/commandline/start.md index 156a2aae08..72ff7e1002 100644 --- a/docs/reference/commandline/start.md +++ b/docs/reference/commandline/start.md @@ -10,11 +10,14 @@ parent = "smn_cli" # start - Usage: docker start [OPTIONS] CONTAINER [CONTAINER...] +```markdown +Usage: docker start [OPTIONS] CONTAINER [CONTAINER...] - Start one or more containers +Start one or more stopped containers - -a, --attach Attach STDOUT/STDERR and forward signals - --detach-keys Specify the escape key sequence used to detach a container - --help Print usage - -i, --interactive Attach container's STDIN +Options: + -a, --attach Attach STDOUT/STDERR and forward signals + --detach-keys string Override the key sequence for detaching a container + --help Print usage + -i, --interactive Attach container's STDIN +``` diff --git a/docs/reference/commandline/stats.md b/docs/reference/commandline/stats.md index d46a94e3a2..3e1a5c4ccc 100644 --- a/docs/reference/commandline/stats.md +++ b/docs/reference/commandline/stats.md @@ -10,13 +10,16 @@ parent = "smn_cli" # stats - Usage: docker stats [OPTIONS] [CONTAINER...] +```markdown +Usage: docker stats [OPTIONS] [CONTAINER...] - Display a live stream of one or more containers' resource usage statistics +Display a live stream of container(s) resource usage statistics - -a, --all Show all containers (default shows just running) - --help Print usage - --no-stream Disable streaming stats and only pull the first result +Options: + -a, --all Show all containers (default shows just running) + --help Print usage + --no-stream Disable streaming stats and only pull the first result +``` The `docker stats` command returns a live data stream for running containers. To limit data to one or more specific containers, specify a list of container names or ids separated by a space. You can specify a stopped container but stopped containers do not return any data. diff --git a/docs/reference/commandline/stop.md b/docs/reference/commandline/stop.md index 1fb376eaf7..662255846f 100644 --- a/docs/reference/commandline/stop.md +++ b/docs/reference/commandline/stop.md @@ -10,13 +10,15 @@ parent = "smn_cli" # stop - Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...] +```markdown +Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...] - Stop a container by sending SIGTERM and then SIGKILL after a - grace period +Stop one or more running containers - --help Print usage - -t, --time=10 Seconds to wait for stop before killing it +Options: + --help Print usage + -t, --time int Seconds to wait for stop before killing it (default 10) +``` The main process inside the container will receive `SIGTERM`, and after a grace period, `SIGKILL`. diff --git a/docs/reference/commandline/swarm_init.md b/docs/reference/commandline/swarm_init.md index 040c44207b..5c255247be 100644 --- a/docs/reference/commandline/swarm_init.md +++ b/docs/reference/commandline/swarm_init.md @@ -12,17 +12,22 @@ parent = "smn_cli" # swarm init - Usage: docker swarm init [OPTIONS] +```markdown +Usage: docker swarm init [OPTIONS] - Initialize a Swarm. +Initialize a Swarm - Options: - --auto-accept value Acceptance policy (default [worker,manager]) - --external-ca value Specifications of one or more certificate signing endpoints - --force-new-cluster Force create a new cluster from current state. - --help Print usage - --listen-addr value Listen address (default 0.0.0.0:2377) - --secret string Set secret value needed to accept nodes into cluster +Options: + --auto-accept value Auto acceptance policy (default worker) + --cert-expiry duration Validity period for node certificates (default 2160h0m0s) + --dispatcher-heartbeat duration Dispatcher heartbeat period (default 5s) + --external-ca value Specifications of one or more certificate signing endpoints + --force-new-cluster Force create a new cluster from current state. + --help Print usage + --listen-addr value Listen address (default 0.0.0.0:2377) + --secret string Set secret value needed to accept nodes into cluster + --task-history-limit int Task history retention limit (default 10) +``` Initialize a Swarm cluster. The docker engine targeted by this command becomes a manager in the newly created one node Swarm cluster. @@ -30,16 +35,28 @@ in the newly created one node Swarm cluster. ```bash $ docker swarm init --listen-addr 192.168.99.121:2377 +No --secret provided. Generated random secret: + 4ao565v9jsuogtq5t8s379ulb + Swarm initialized: current node (1ujecd0j9n3ro9i6628smdmth) is now a manager. + +To add a worker to this swarm, run the following command: + docker swarm join --secret 4ao565v9jsuogtq5t8s379ulb \ + --ca-hash sha256:07ce22bd1a7619f2adc0d63bd110479a170e7c4e69df05b67a1aa2705c88ef09 \ + 192.168.99.121:2377 $ docker node ls -ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER +ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER 1ujecd0j9n3ro9i6628smdmth * manager1 Accepted Ready Active Reachable Yes ``` +If a secret for joining new nodes is not provided with `--secret`, `docker swarm init` will +generate a random one and print it to the terminal (as seen in the example above). To initialize +a swarm with no secret, use `--secret ""`. + ### `--auto-accept value` -This flag controls node acceptance into the cluster. By default, both `worker` and `manager` -nodes are auto accepted by the cluster. This can be changed by specifing what kinds of nodes +This flag controls node acceptance into the cluster. By default, `worker` nodes are +automatically accepted by the cluster. This can be changed by specifying what kinds of nodes can be auto-accepted into the cluster. If auto-accept is not turned on, then [node accept](node_accept.md) can be used to explicitly accept a node into the cluster. @@ -48,9 +65,34 @@ For example, the following initializes a cluster with auto-acceptance of workers ```bash $ docker swarm init --listen-addr 192.168.99.121:2377 --auto-accept worker -Swarm initialized: current node (1m8cdsylxbf3lk8qriqt07hx1) is now a manager. ``` +It is possible to pass a comma-separated list of node types. The following initializes a cluster +with auto-acceptance of both `worker` and `manager` nodes + +```bash +$ docker swarm init --listen-addr 192.168.99.121:2377 --auto-accept worker,manager +``` + +To disable auto acceptance, use the `none` option. Note that this option cannot +be combined with other values. When disabling auto acceptance, nodes must be +manually accepted or rejected using `docker node accept` or `docker node rm`. + +The following example enables swarm mode with auto acceptance disabled: + +```bash +$ docker swarm init --listen-addr 192.168.99.121:2377 --auto-accept none +``` + +### `--cert-expiry` + +This flag sets the validity period for node certificates. + +### `--dispatcher-heartbeat` + +This flags sets the frequency with which nodes are told to use as a +period to report their health. + ### `--external-ca value` This flag sets up the swarm to use an external CA to issue node certificates. The value takes @@ -70,8 +112,14 @@ The node listens for inbound Swarm manager traffic on this IP:PORT Secret value needed to accept nodes into the Swarm +### `--task-history-limit` + +This flag sets up task history retention limit. + ## Related information * [swarm join](swarm_join.md) * [swarm leave](swarm_leave.md) * [swarm update](swarm_update.md) +* [node accept](node_accept.md) +* [node rm](node_rm.md) diff --git a/docs/reference/commandline/swarm_join.md b/docs/reference/commandline/swarm_join.md index 6c0d137b8e..6d99a406e7 100644 --- a/docs/reference/commandline/swarm_join.md +++ b/docs/reference/commandline/swarm_join.md @@ -12,15 +12,18 @@ parent = "smn_cli" # swarm join - Usage: docker swarm join [OPTIONS] HOST:PORT +```markdown +Usage: docker swarm join [OPTIONS] HOST:PORT - Join a Swarm as a node and/or manager. +Join a Swarm as a node and/or manager - Options: - --help Print usage - --listen-addr value Listen address (default 0.0.0.0:2377) - --manager Try joining as a manager. - --secret string Secret for node acceptance +Options: + --ca-hash string Hash of the Root Certificate Authority certificate used for trusted join + --help Print usage + --listen-addr value Listen address (default 0.0.0.0:2377) + --manager Try joining as a manager. + --secret string Secret for node acceptance +``` Join a node to a Swarm cluster. If the `--manager` flag is specified, the docker engine targeted by this command becomes a `manager`. If it is not specified, it becomes a `worker`. @@ -28,10 +31,10 @@ targeted by this command becomes a `manager`. If it is not specified, it becomes ### Join a node to swarm as a manager ```bash -$ docker swarm join --manager --listen-addr 192.168.99.122:2377 192.168.99.121:2377 +$ docker swarm join --secret 4ao565v9jsuogtq5t8s379ulb --manager --listen-addr 192.168.99.122:2377 192.168.99.121:2377 This node joined a Swarm as a manager. $ docker node ls -ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER +ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER dkp8vy1dq1kxleu9g4u78tlag * manager2 Accepted Ready Active Reachable dvfxp4zseq4s0rih1selh0d20 manager1 Accepted Ready Active Reachable Yes ``` @@ -39,23 +42,27 @@ dvfxp4zseq4s0rih1selh0d20 manager1 Accepted Ready Active Reachab ### Join a node to swarm as a worker ```bash -$ docker swarm join --listen-addr 192.168.99.123:2377 192.168.99.121:2377 +$ docker swarm join --secret 4ao565v9jsuogtq5t8s379ulb --listen-addr 192.168.99.123:2377 192.168.99.121:2377 This node joined a Swarm as a worker. $ docker node ls -ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER +ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER 7ln70fl22uw2dvjn2ft53m3q5 worker2 Accepted Ready Active dkp8vy1dq1kxleu9g4u78tlag worker1 Accepted Ready Active Reachable dvfxp4zseq4s0rih1selh0d20 * manager1 Accepted Ready Active Reachable Yes ``` -### `--manager` +### `--ca-hash` -Joins the node as a manager +Hash of the Root Certificate Authority certificate used for trusted join. ### `--listen-addr value` The node listens for inbound Swarm manager traffic on this IP:PORT +### `--manager` + +Joins the node as a manager + ### `--secret string` Secret value required for nodes to join the swarm diff --git a/docs/reference/commandline/swarm_leave.md b/docs/reference/commandline/swarm_leave.md index 3eab7eb0f6..1fdbc38fc5 100644 --- a/docs/reference/commandline/swarm_leave.md +++ b/docs/reference/commandline/swarm_leave.md @@ -12,19 +12,22 @@ parent = "smn_cli" # swarm leave - Usage: docker swarm leave +```markdown +Usage: docker swarm leave [OPTIONS] - Leave a Swarm swarm. +Leave a Swarm - Options: - --help Print usage +Options: + --force Force leave ignoring warnings. + --help Print usage +``` This command causes the node to leave the swarm. On a manager node: ```bash $ docker node ls -ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER +ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER 7ln70fl22uw2dvjn2ft53m3q5 worker2 Accepted Ready Active dkp8vy1dq1kxleu9g4u78tlag worker1 Accepted Ready Active Reachable dvfxp4zseq4s0rih1selh0d20 * manager1 Accepted Ready Active Reachable Yes @@ -39,7 +42,7 @@ Node left the default swarm. On a manager node: ```bash $ docker node ls -ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER +ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER 7ln70fl22uw2dvjn2ft53m3q5 worker2 Accepted Down Active dkp8vy1dq1kxleu9g4u78tlag worker1 Accepted Ready Active Reachable dvfxp4zseq4s0rih1selh0d20 * manager1 Accepted Ready Active Reachable Yes diff --git a/docs/reference/commandline/swarm_update.md b/docs/reference/commandline/swarm_update.md index fc89249fe5..6173923be3 100644 --- a/docs/reference/commandline/swarm_update.md +++ b/docs/reference/commandline/swarm_update.md @@ -12,17 +12,20 @@ parent = "smn_cli" # swarm update - Usage: docker swarm update [OPTIONS] +```markdown +Usage: docker swarm update [OPTIONS] - update the Swarm. +Update the Swarm - Options: - --auto-accept value Auto acceptance policy (worker, manager or none) - --external-ca value Specifications of one or more certificate signing endpoints - --dispatcher-heartbeat duration Dispatcher heartbeat period (default 5s) - --help Print usage - --secret string Set secret value needed to accept nodes into cluster - --task-history-limit int Task history retention limit (default 10) +Options: + --auto-accept value Auto acceptance policy (worker, manager or none) + --cert-expiry duration Validity period for node certificates (default 2160h0m0s) + --dispatcher-heartbeat duration Dispatcher heartbeat period (default 5s) + --external-ca value Specifications of one or more certificate signing endpoints + --help Print usage + --secret string Set secret value needed to accept nodes into cluster + --task-history-limit int Task history retention limit (default 10) +``` Updates a Swarm cluster with new parameter values. This command must target a manager node. diff --git a/docs/reference/commandline/tag.md b/docs/reference/commandline/tag.md index 47cc58c4e5..60692958f1 100644 --- a/docs/reference/commandline/tag.md +++ b/docs/reference/commandline/tag.md @@ -10,11 +10,14 @@ parent = "smn_cli" # tag - Usage: docker tag [OPTIONS] NAME[:TAG] NAME[:TAG] +```markdown +Usage: docker tag IMAGE[:TAG] IMAGE[:TAG] - Tag an image into a repository +Tag an image into a repository - --help Print usage +Options: + --help Print usage +``` An image name is made up of slash-separated name components, optionally prefixed by a registry hostname. The hostname must comply with standard DNS rules, but diff --git a/docs/reference/commandline/top.md b/docs/reference/commandline/top.md index 2bff2fdb47..291f96ce09 100644 --- a/docs/reference/commandline/top.md +++ b/docs/reference/commandline/top.md @@ -10,8 +10,11 @@ parent = "smn_cli" # top - Usage: docker top [OPTIONS] CONTAINER [ps OPTIONS] +```markdown +Usage: docker top CONTAINER [ps OPTIONS] - Display the running processes of a container +Display the running processes of a container - --help Print usage +Options: + --help Print usage +``` diff --git a/docs/reference/commandline/unpause.md b/docs/reference/commandline/unpause.md index c5920f435c..e5c9d506e0 100644 --- a/docs/reference/commandline/unpause.md +++ b/docs/reference/commandline/unpause.md @@ -10,11 +10,14 @@ parent = "smn_cli" # unpause - Usage: docker unpause [OPTIONS] CONTAINER [CONTAINER...] +```markdown +Usage: docker unpause CONTAINER [CONTAINER...] - Unpause all processes within a container +Unpause all processes within one or more containers - --help Print usage +Options: + --help Print usage +``` The `docker unpause` command uses the cgroups freezer to un-suspend all processes in a container. diff --git a/docs/reference/commandline/update.md b/docs/reference/commandline/update.md index 24fb1f290d..4ad4dc9e62 100644 --- a/docs/reference/commandline/update.md +++ b/docs/reference/commandline/update.md @@ -10,22 +10,25 @@ parent = "smn_cli" ## update - Usage: docker update [OPTIONS] CONTAINER [CONTAINER...] +```markdown +Usage: docker update [OPTIONS] CONTAINER [CONTAINER...] - Update configuration of one or more containers +Update configuration of one or more containers - --help=false Print usage - --blkio-weight=0 Block IO (relative weight), between 10 and 1000 - --cpu-shares=0 CPU shares (relative weight) - --cpu-period=0 Limit the CPU CFS (Completely Fair Scheduler) period - --cpu-quota=0 Limit the CPU CFS (Completely Fair Scheduler) quota - --cpuset-cpus="" CPUs in which to allow execution (0-3, 0,1) - --cpuset-mems="" Memory nodes (MEMs) in which to allow execution (0-3, 0,1) - -m, --memory="" Memory limit - --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 +Options: + --blkio-weight value Block IO (relative weight), between 10 and 1000 + --cpu-period int Limit CPU CFS (Completely Fair Scheduler) period + --cpu-quota int Limit CPU CFS (Completely Fair Scheduler) quota + -c, --cpu-shares int CPU shares (relative weight) + --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) + --cpuset-mems string MEMs in which to allow execution (0-3, 0,1) + --help Print usage + --kernel-memory string Kernel memory limit + -m, --memory string Memory limit + --memory-reservation string Memory soft limit + --memory-swap string Swap limit equal to memory plus swap: '-1' to enable unlimited swap + --restart string Restart policy to apply when a container exits +``` The `docker update` command dynamically updates container configuration. You can use this command to prevent containers from consuming too many resources diff --git a/docs/reference/commandline/version.md b/docs/reference/commandline/version.md index 14fac17e29..e650e41a2d 100644 --- a/docs/reference/commandline/version.md +++ b/docs/reference/commandline/version.md @@ -10,12 +10,15 @@ parent = "smn_cli" # version - Usage: docker version [OPTIONS] +```markdown +Usage: docker version [OPTIONS] - Show the Docker version information. +Show the Docker version information - -f, --format="" Format the output using the given go template - --help Print usage +Options: + -f, --format string Format the output using the given go template + --help Print usage +``` By default, this will render all version information in an easy to read layout. If a format is specified, the given template will be executed instead. diff --git a/docs/reference/commandline/volume_create.md b/docs/reference/commandline/volume_create.md index 3e69b79864..56c8a5fcc0 100644 --- a/docs/reference/commandline/volume_create.md +++ b/docs/reference/commandline/volume_create.md @@ -10,15 +10,18 @@ parent = "smn_cli" # volume create - Usage: docker volume create [OPTIONS] +```markdown +Usage: docker volume create [OPTIONS] - Create a volume +Create a volume - -d, --driver=local Specify volume driver name - --help Print usage - --label=[] Set metadata for a volume - --name= Specify volume name - -o, --opt=map[] Set driver specific options +Options: + -d, --driver string Specify volume driver name (default "local") + --help Print usage + --label value Set metadata for a volume (default []) + --name string Specify volume name + -o, --opt value Set driver specific options (default map[]) +``` Creates a new volume that containers can consume and store data in. If a name is not specified, Docker generates a random name. You create a volume and then configure the container to use it, for example: @@ -54,17 +57,24 @@ different volume drivers may do different things (or nothing at all). The built-in `local` driver on Windows does not support any options. -The built-in `local` driver on Linux accepts options similar to the linux `mount` -command: +The built-in `local` driver on Linux accepts options similar to the linux `mount` command. You can provide multiple options by passing the `--opt` flag multiple times. Some `mount` options (such as the `o` option) can take a comma-separated list of options. Complete list of available mount options can be found [here](http://man7.org/linux/man-pages/man8/mount.8.html). + +For example, the following creates a `tmpfs` volume called `foo` with a size of 100 megabyte and `uid` of 1000. ```bash -$ docker volume create --driver local --opt type=tmpfs --opt device=tmpfs --opt o=size=100m,uid=1000 +$ docker volume create --driver local --opt type=tmpfs --opt device=tmpfs --opt o=size=100m,uid=1000 --name foo ``` -Another example: +Another example that uses `btrfs`: ```bash -$ docker volume create --driver local --opt type=btrfs --opt device=/dev/sda2 +$ docker volume create --driver local --opt type=btrfs --opt device=/dev/sda2 --name foo +``` + +Another example that uses `nfs` to mount the `/path/to/dir` in `rw` mode from `192.168.1.1`: + +```bash +$ docker volume create --driver local --opt type=nfs --opt o=addr=192.168.1.1,rw --opt device=:/path/to/dir --name foo ``` diff --git a/docs/reference/commandline/volume_inspect.md b/docs/reference/commandline/volume_inspect.md index d8b7702360..fac9438e3d 100644 --- a/docs/reference/commandline/volume_inspect.md +++ b/docs/reference/commandline/volume_inspect.md @@ -10,12 +10,15 @@ parent = "smn_cli" # volume inspect - Usage: docker volume inspect [OPTIONS] VOLUME [VOLUME...] +```markdown +Usage: docker volume inspect [OPTIONS] VOLUME [VOLUME...] - Display detailed information on one or more volumes +Display detailed information on one or more volumes - -f, --format= Format the output using the given go template. - --help Print usage +Options: + -f, --format string Format the output using the given go template + --help Print usage +``` Returns information about a volume. By default, this command renders all results in a JSON array. You can specify an alternate format to execute a diff --git a/docs/reference/commandline/volume_ls.md b/docs/reference/commandline/volume_ls.md index 12ed40c401..cdeea42e8c 100644 --- a/docs/reference/commandline/volume_ls.md +++ b/docs/reference/commandline/volume_ls.md @@ -10,16 +10,22 @@ parent = "smn_cli" # volume ls - Usage: docker volume ls [OPTIONS] +```markdown +Usage: docker volume ls [OPTIONS] - List volumes +List volumes - -f, --filter=[] Filter output based on these conditions: - - dangling= a volume if referenced or not - - driver= a volume's driver name - - name= a volume's name - --help Print usage - -q, --quiet Only display volume names +Aliases: + ls, list + +Options: + -f, --filter value Provide filter values (i.e. 'dangling=true') (default []) + - dangling= a volume if referenced or not + - driver= a volume's driver name + - name= a volume's name + --help Print usage + -q, --quiet Only display volume names +``` Lists all the volumes Docker knows about. You can filter using the `-f` or `--filter` flag. Refer to the [filtering](#filtering) section for more information about available filter options. diff --git a/docs/reference/commandline/volume_rm.md b/docs/reference/commandline/volume_rm.md index c163ddf680..1760a5d905 100644 --- a/docs/reference/commandline/volume_rm.md +++ b/docs/reference/commandline/volume_rm.md @@ -10,11 +10,17 @@ parent = "smn_cli" # volume rm - Usage: docker volume rm [OPTIONS] VOLUME [VOLUME...] +```markdown +Usage: docker volume rm VOLUME [VOLUME]... - Remove a volume +Remove a volume - --help Print usage +Aliases: + rm, remove + +Options: + --help Print usage +``` Removes one or more volumes. You cannot remove a volume that is in use by a container. diff --git a/docs/reference/commandline/wait.md b/docs/reference/commandline/wait.md index 5cd9a7b9f6..b10f6a1a21 100644 --- a/docs/reference/commandline/wait.md +++ b/docs/reference/commandline/wait.md @@ -10,8 +10,11 @@ parent = "smn_cli" # wait - Usage: docker wait [OPTIONS] CONTAINER [CONTAINER...] +```markdown +Usage: docker wait CONTAINER [CONTAINER...] - Block until a container stops, then print its exit code. +Block until a container stops, then print its exit code - --help Print usage +Options: + --help Print usage +``` diff --git a/docs/reference/run.md b/docs/reference/run.md index db0e86b6e9..ab5ed29f84 100644 --- a/docs/reference/run.md +++ b/docs/reference/run.md @@ -259,7 +259,7 @@ $ strace -p 1 The UTS namespace is for setting the hostname and the domain that is visible to running processes in that namespace. By default, all containers, including -those with `--net=host`, have their own UTS namespace. The `host` setting will +those with `--network=host`, have their own UTS namespace. The `host` setting will result in the container using the same UTS namespace as the host. Note that `--hostname` is invalid in `host` UTS mode. @@ -289,13 +289,13 @@ of the containers. ## Network settings --dns=[] : Set custom dns servers for the container - --net="bridge" : Connect a container to a network + --network="bridge" : Connect a container to a network 'bridge': create a network stack on the default Docker bridge 'none': no networking 'container:': reuse another container's network stack 'host': use the Docker host network stack '|': connect to a user-defined network - --net-alias=[] : Add network-scoped alias for the container + --network-alias=[] : Add network-scoped alias for the container --add-host="" : Add a line to /etc/hosts (host:IP) --mac-address="" : Sets the container's Ethernet device's MAC address --ip="" : Sets the container's Ethernet device's IPv4 address @@ -304,7 +304,7 @@ of the containers. By default, all containers have networking enabled and they can make any outgoing connections. The operator can completely disable networking -with `docker run --net none` which disables all incoming and outgoing +with `docker run --network none` which disables all incoming and outgoing networking. In cases like this, you would perform I/O through files or `STDIN` and `STDOUT` only. @@ -404,14 +404,14 @@ docker daemon. It is recommended to run containers in this mode when their networking performance is critical, for example, a production Load Balancer or a High Performance Web Server. -> **Note**: `--net="host"` gives the container full access to local system +> **Note**: `--network="host"` gives the container full access to local system > services such as D-bus and is therefore considered insecure. #### Network: container With the network set to `container` a container will share the network stack of another container. The other container's name must be -provided in the format of `--net container:`. Note that `--add-host` +provided in the format of `--network container:`. Note that `--add-host` `--hostname` `--dns` `--dns-search` `--dns-opt` and `--mac-address` are invalid in `container` netmode, and `--publish` `--publish-all` `--expose` are also invalid in `container` netmode. @@ -422,7 +422,7 @@ running the `redis-cli` command and connecting to the Redis server over the $ docker run -d --name redis example/redis --bind 127.0.0.1 $ # use the redis container's network stack to access localhost - $ docker run --rm -it --net container:redis example/redis-cli -h 127.0.0.1 + $ docker run --rm -it --network container:redis example/redis-cli -h 127.0.0.1 #### User-defined network @@ -440,7 +440,7 @@ driver and running a container in the created network ``` $ docker network create -d bridge my-net -$ docker run --net=my-net -itd --name=container3 busybox +$ docker run --network=my-net -itd --name=container3 busybox ``` ### Managing /etc/hosts diff --git a/docs/security/security.md b/docs/security/security.md index 39a47e06b2..17810eecc9 100644 --- a/docs/security/security.md +++ b/docs/security/security.md @@ -51,7 +51,7 @@ common Ethernet switch; no more, no less. How mature is the code providing kernel namespaces and private networking? Kernel namespaces were introduced [between kernel version 2.6.15 and -2.6.26](http://lxc.sourceforge.net/index.php/about/kernel-namespaces/). +2.6.26](http://man7.org/linux/man-pages/man7/namespaces.7.html). This means that since July 2008 (date of the 2.6.26 release ), namespace code has been exercised and scrutinized on a large number of production systems. And there is more: the design and diff --git a/docs/security/trust/content_trust.md b/docs/security/trust/content_trust.md index a475dd306b..4ae8687db7 100644 --- a/docs/security/trust/content_trust.md +++ b/docs/security/trust/content_trust.md @@ -130,7 +130,14 @@ read how to [manage keys for content trust](trust_key_mng.md). ## Survey of typical content trust operations This section surveys the typical trusted operations users perform with Docker -images. +images. Specifically, we will be going through the following steps to help us exercise +these various trusted operations: + +* Build and push an unsigned image +* Pull an unsigned image +* Build and push a signed image +* Pull the signed image pushed above +* Pull unsigned image pushed above ### Enable and disable content trust per-shell or per-invocation @@ -152,14 +159,36 @@ In an environment where `DOCKER_CONTENT_TRUST` is set, you can use the `--disable-content-trust` flag to run individual operations on tagged images without content trust on an as-needed basis. -```bash -$ docker pull --disable-content-trust docker/trusttest:untrusted +Consider the following Dockerfile that uses an untrusted base image: + +``` +$ cat Dockerfile +FROM docker/trusttest:latest +RUN echo +``` + +In order to build a container successfully using this Dockerfile, one can do: + +``` +$ docker build --disable-content-trust -t /nottrusttest:latest . +Sending build context to Docker daemon 42.84 MB +... +Successfully built f21b872447dc +``` + +The same is true for all the other commands, such as `pull` and `push`: + +``` +$ docker pull --disable-content-trust docker/trusttest:latest +... +$ docker push --disable-content-trust /nottrusttest:latest +... ``` To invoke a command with content trust enabled regardless of whether or how the `DOCKER_CONTENT_TRUST` variable is set: ```bash -$ docker build --disable-content-trust=false -t docker/trusttest:testing . +$ docker build --disable-content-trust=false -t /trusttest:testing . ``` All of the trusted operations support the `--disable-content-trust` flag. @@ -172,8 +201,8 @@ and push a tagged image. If this is the first time you have pushed an image using content trust on your system, the session looks like this: ```bash -$ docker push docker/trusttest:latest -The push refers to a repository [docker.io/docker/trusttest] (len: 1) +$ docker push /trusttest:testing +The push refers to a repository [docker.io//trusttest] (len: 1) 9a61b6b1315e: Image already exists 902b87aaaec9: Image already exists latest: digest: sha256:d02adacee0ac7a5be140adb94fa1dae64f4e71a68696e7f8e7cbf9db8dd49418 size: 3220 @@ -186,9 +215,9 @@ password manager to generate the passphrase and keep it safe. There will be no way to recover this key. You can find the key in your config directory. Enter passphrase for new root key with id a1d96fb: Repeat passphrase for new root key with id a1d96fb: -Enter passphrase for new repository key with id docker.io/docker/trusttest (3a932f1): -Repeat passphrase for new repository key with id docker.io/docker/trusttest (3a932f1): -Finished initializing "docker.io/docker/trusttest" +Enter passphrase for new repository key with id docker.io//trusttest (3a932f1): +Repeat passphrase for new repository key with id docker.io//trusttest (3a932f1): +Finished initializing "docker.io//trusttest" ``` When you push your first tagged image with content trust enabled, the `docker` client recognizes this is your first push and: @@ -202,12 +231,12 @@ client recognizes this is your first push and: The passphrase you chose for both the root key and your repository key-pair should be randomly generated and stored in a *password manager*. -> **NOTE**: If you omit the `latest` tag, content trust is skipped. This is true +> **NOTE**: If you omit the `testing` tag, content trust is skipped. This is true even if content trust is enabled and even if this is your first push. ```bash -$ docker push docker/trusttest -The push refers to a repository [docker.io/docker/trusttest] (len: 1) +$ docker push /trusttest +The push refers to a repository [docker.io//trusttest] (len: 1) 9a61b6b1315e: Image successfully pushed 902b87aaaec9: Image successfully pushed latest: digest: sha256:a9a9c4402604b703bed1c847f6d85faac97686e48c579bd9c3b0fa6694a398fc size: 3220 @@ -221,16 +250,16 @@ Once you have a root key on your system, subsequent images repositories you create can use that same root key: ```bash -$ docker push docker.io/docker/seaside:latest -The push refers to a repository [docker.io/docker/seaside] (len: 1) +$ docker push docker.io//otherimage:latest +The push refers to a repository [docker.io//otherimage] (len: 1) a9539b34a6ab: Image successfully pushed b3dbab3810fc: Image successfully pushed latest: digest: sha256:d2ba1e603661a59940bfad7072eba698b79a8b20ccbb4e3bfb6f9e367ea43939 size: 3346 Signing and pushing trust metadata Enter key passphrase for root key with id a1d96fb: -Enter passphrase for new repository key with id docker.io/docker/seaside (bb045e3): -Repeat passphrase for new repository key with id docker.io/docker/seaside (bb045e3): -Finished initializing "docker.io/docker/seaside" +Enter passphrase for new repository key with id docker.io//otherimage (bb045e3): +Repeat passphrase for new repository key with id docker.io//otherimage (bb045e3): +Finished initializing "docker.io//otherimage" ``` The new image has its own repository key and timestamp key. The `latest` tag is signed with both of @@ -240,54 +269,27 @@ these. ### Pull image content A common way to consume an image is to `pull` it. With content trust enabled, the Docker -client only allows `docker pull` to retrieve signed images. +client only allows `docker pull` to retrieve signed images. Let's try to pull the image +you signed and pushed earlier: ``` -$ docker pull docker/seaside +$ docker pull /trusttest:testing Using default tag: latest -Pull (1 of 1): docker/trusttest:latest@sha256:d149ab53f871 +Pull (1 of 1): /trusttest:testing@sha256:d149ab53f871 ... -Tagging docker/trusttest@sha256:d149ab53f871 as docker/trusttest:latest +Tagging /trusttest@sha256:d149ab53f871 as docker/trusttest:testing ``` -The `seaside:latest` image is signed. In the following example, the command does not specify a tag, so the system uses -the `latest` tag by default again and the `docker/cliffs:latest` tag is not signed. +In the following example, the command does not specify a tag, so the system uses +the `latest` tag by default again and the `docker/trusttest:latest` tag is not signed. ```bash -$ docker pull docker/cliffs +$ docker pull docker/trusttest Using default tag: latest no trust data available ``` -Because the tag `docker/cliffs:latest` is not trusted, the `pull` fails. - - -### Disable content trust for specific operations - -A user who wants to disable content trust for a particular operation can use the -`--disable-content-trust` flag. **Warning: this flag disables content trust for -this operation**. With this flag, Docker will ignore content-trust and allow all -operations to be done without verifying any signatures. If we wanted the -previous untrusted build to succeed we could do: - -``` -$ cat Dockerfile -FROM docker/trusttest:notrust -RUN echo -$ docker build --disable-content-trust -t docker/trusttest:testing . -Sending build context to Docker daemon 42.84 MB -... -Successfully built f21b872447dc -``` - -The same is true for all the other commands, such as `pull` and `push`: - -``` -$ docker pull --disable-content-trust docker/trusttest:untrusted -... -$ docker push --disable-content-trust docker/trusttest:untrusted -... -``` +Because the tag `docker/trusttest:latest` is not trusted, the `pull` fails. ## Related information diff --git a/docs/swarm/swarm-tutorial/add-nodes.md b/docs/swarm/swarm-tutorial/add-nodes.md index 8b9b69f557..dee1d9db09 100644 --- a/docs/swarm/swarm-tutorial/add-nodes.md +++ b/docs/swarm/swarm-tutorial/add-nodes.md @@ -23,16 +23,17 @@ This tutorial uses the name `worker1`. the existing swarm: ``` - docker swarm join : + docker swarm join --secret : ``` - Replace `` with the address of the manager node and `` - with the port where the manager listens. + Replace `` with the secret that was printed by `docker swarm init` in the + previous step. Replace `` with the address of the manager node + and `` with the port where the manager listens. In the tutorial, the following command joins `worker1` to the swarm on `manager1`: ``` - $ docker swarm join 192.168.99.100:2377 + $ docker swarm join --secret 4ao565v9jsuogtq5t8s379ulb 192.168.99.100:2377 This node joined a Swarm as a worker. ``` @@ -40,17 +41,18 @@ the existing swarm: 3. Open a terminal and ssh into the machine where you want to run a second worker node. This tutorial uses the name `worker2`. -4. Run `docker swarm join :` to create a worker node joined to +4. Run `docker swarm join --secret :` to create a worker node joined to the existing Swarm. - Replace `` with the address of the manager node and `` - with the port where the manager listens. + Replace `` with the secret that was printed by `docker swarm init` in the + previous step. Replace `` with the address of the manager node + and `` with the port where the manager listens. 5. Open a terminal and ssh into the machine where the manager node runs and run the `docker node ls` command to see the worker nodes: ```bash - ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER + ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER 03g1y59jwfg7cf99w4lt0f662 worker2 Accepted Ready Active 9j68exjopxe7wfl6yuxml7a7j worker1 Accepted Ready Active dxn1zf6l61qsb1josjja83ngz * manager1 Accepted Ready Active Reachable Yes diff --git a/docs/swarm/swarm-tutorial/create-swarm.md b/docs/swarm/swarm-tutorial/create-swarm.md index bd851e19d9..d48aba43d5 100644 --- a/docs/swarm/swarm-tutorial/create-swarm.md +++ b/docs/swarm/swarm-tutorial/create-swarm.md @@ -30,8 +30,15 @@ node. For example, the tutorial uses a machine named `manager1`. ``` $ docker swarm init --listen-addr 192.168.99.100:2377 + No --secret provided. Generated random secret: + 4ao565v9jsuogtq5t8s379ulb Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) is now a manager. + + To add a worker to this swarm, run the following command: + docker swarm join --secret 4ao565v9jsuogtq5t8s379ulb \ + --ca-hash sha256:07ce22bd1a7619f2adc0d63bd110479a170e7c4e69df05b67a1aa2705c88ef09 \ + 192.168.99.100:2377 ``` The `--listen-addr` flag configures the manager node to listen on port @@ -62,7 +69,7 @@ node. For example, the tutorial uses a machine named `manager1`. ``` $ docker node ls - ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER + ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER dxn1zf6l61qsb1josjja83ngz * manager1 Accepted Ready Active Reachable Yes ``` diff --git a/docs/swarm/swarm-tutorial/delete-service.md b/docs/swarm/swarm-tutorial/delete-service.md index b98a3ec4f3..d0364be42b 100644 --- a/docs/swarm/swarm-tutorial/delete-service.md +++ b/docs/swarm/swarm-tutorial/delete-service.md @@ -39,5 +39,5 @@ removed the service. The CLI returns a message that the service is not found: ## What's next? -In the next step of the tutorial, you set up a new service and and apply a +In the next step of the tutorial, you set up a new service and apply a [rolling update](rolling-update.md). diff --git a/docs/swarm/swarm-tutorial/drain-node.md b/docs/swarm/swarm-tutorial/drain-node.md index 8dac987abd..fc001f7a3c 100644 --- a/docs/swarm/swarm-tutorial/drain-node.md +++ b/docs/swarm/swarm-tutorial/drain-node.md @@ -31,7 +31,7 @@ run your manager node. For example, the tutorial uses a machine named ```bash $ docker node ls - ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER + ID HOSTNAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER 1bcef6utixb0l0ca7gxuivsj0 worker2 Accepted Ready Active 38ciaotwjuritcdtn9npbnkuz worker1 Accepted Ready Active e216jshn25ckzbvmwlnh5jr3g * manager1 Accepted Ready Active Reachable Yes diff --git a/docs/swarm/swarm-tutorial/index.md b/docs/swarm/swarm-tutorial/index.md index c0a6c2e5ce..88081be1ed 100644 --- a/docs/swarm/swarm-tutorial/index.md +++ b/docs/swarm/swarm-tutorial/index.md @@ -84,9 +84,6 @@ The tutorial uses `manager1` : `192.168.99.100`. * **TCP** and **UDP port 7946** for communication among nodes * **TCP** and **UDP port 4789** for overlay network traffic ->**Tip**: Docker recommends that every node in the cluster be on the same layer -3 (IP) subnet with all traffic permitted between nodes. - ## What's next? After you have set up your environment, you're ready to [create a swarm](create-swarm.md). diff --git a/docs/tutorials/dockerimages.md b/docs/tutorials/dockerimages.md index a904eef76a..619ac14898 100644 --- a/docs/tutorials/dockerimages.md +++ b/docs/tutorials/dockerimages.md @@ -37,6 +37,7 @@ Let's start with listing the images you have locally on our host. You can do this using the `docker images` command like so: $ docker images + REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 14.04 1d073211c498 3 days ago 187.9 MB busybox latest 2c5ac3f849df 5 days ago 1.113 MB @@ -87,6 +88,7 @@ can download it using the `docker pull` command. Suppose you'd like to download the `centos` image. $ docker pull centos + Pulling repository centos b7de3133ff98: Pulling dependent layers 5cc9e91966f7: Pulling fs layer @@ -101,6 +103,7 @@ can run a container from this image and you won't have to wait to download the image. $ docker run -t -i centos /bin/bash + bash-4.1# ## Finding images @@ -158,6 +161,7 @@ You've identified a suitable image, `training/sinatra`, and now you can download The team can now use this image by running their own containers. $ docker run -t -i training/sinatra /bin/bash + root@a8cb6ce02d85:/# ## Creating our own images @@ -176,6 +180,7 @@ To update an image you first need to create a container from the image you'd like to update. $ docker run -t -i training/sinatra /bin/bash + root@0b2616b0e5a8:/# > **Note:** @@ -195,6 +200,7 @@ command. $ docker commit -m "Added json gem" -a "Kate Smith" \ 0b2616b0e5a8 ouruser/sinatra:v2 + 4f177bd27a9ff0f6dc2a830403925b5360bfe0b93d476f7fc3231110e7f71b1c Here you've used the `docker commit` command. You've specified two flags: `-m` @@ -217,6 +223,7 @@ You can then look at our new `ouruser/sinatra` image using the `docker images` command. $ docker images + REPOSITORY TAG IMAGE ID CREATED SIZE training/sinatra latest 5bc342fa0b91 10 hours ago 446.7 MB ouruser/sinatra v2 3c59e02ddd1a 10 hours ago 446.7 MB @@ -225,6 +232,7 @@ command. To use our new image to create a container you can then: $ docker run -t -i ouruser/sinatra:v2 /bin/bash + root@78e82f680994:/# ### Building an image from a `Dockerfile` @@ -240,7 +248,9 @@ tell Docker how to build our image. First, create a directory and a `Dockerfile`. $ mkdir sinatra + $ cd sinatra + $ touch Dockerfile If you are using Docker Machine on Windows, you may access your host @@ -275,6 +285,7 @@ Sinatra gem. Now let's take our `Dockerfile` and use the `docker build` command to build an image. $ docker build -t ouruser/sinatra:v2 . + Sending build context to Docker daemon 2.048 kB Sending build context to Docker daemon Step 1 : FROM ubuntu:14.04 @@ -469,6 +480,7 @@ containers will get removed to clean things up. You can then create a container from our new image. $ docker run -t -i ouruser/sinatra:v2 /bin/bash + root@8196968dac35:/# > **Note:** @@ -495,6 +507,7 @@ user name, the repository name and the new tag. Now, see your new tag using the `docker images` command. $ docker images ouruser/sinatra + REPOSITORY TAG IMAGE ID CREATED SIZE ouruser/sinatra latest 5db5f8471261 11 hours ago 446.7 MB ouruser/sinatra devel 5db5f8471261 11 hours ago 446.7 MB @@ -508,6 +521,7 @@ unchanged, the digest value is predictable. To list image digest values, use the `--digests` flag: $ docker images --digests | head + REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE ouruser/sinatra latest sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf 5db5f8471261 11 hours ago 446.7 MB @@ -527,6 +541,7 @@ allows you to share it with others, either publicly, or push it into [a private repository](https://hub.docker.com/account/billing-plans/). $ docker push ouruser/sinatra + The push refers to a repository [ouruser/sinatra] (len: 1) Sending image list Pushing repository ouruser/sinatra (3 tags) @@ -540,6 +555,7 @@ containers](usingdocker.md) using the `docker rmi` command. Delete the `training/sinatra` image as you don't need it anymore. $ docker rmi training/sinatra + Untagged: training/sinatra:latest Deleted: 5bc342fa0b91cabf65246837015197eecfa24b2213ed6a51a8974ae250fedd8d Deleted: ed0fffdcdae5eb2c3a55549857a8be7fc8bc4241fb19ad714364cbfd7a56b22f diff --git a/docs/tutorials/dockerizing.md b/docs/tutorials/dockerizing.md index 0414beb4a2..6295319d93 100644 --- a/docs/tutorials/dockerizing.md +++ b/docs/tutorials/dockerizing.md @@ -30,6 +30,7 @@ Running an application inside a container takes a single command: `docker run`. Let's run a hello world container. $ docker run ubuntu /bin/echo 'Hello world' + Hello world You just launched your first container! @@ -59,6 +60,7 @@ the container stops once the command is executed. Let's specify a new command to run in the container. $ docker run -t -i ubuntu /bin/bash + root@af8bae53bdd3:/# In this example: @@ -78,8 +80,11 @@ command prompt inside it: Let's try running some commands inside the container: root@af8bae53bdd3:/# pwd + / + root@af8bae53bdd3:/# ls + bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var In this example: @@ -100,6 +105,7 @@ finished, the container stops. Let's create a container that runs as a daemon. $ docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done" + 1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147 In this example: @@ -132,6 +138,7 @@ The `docker ps` command queries the Docker daemon for information about all the about. $ docker ps + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1e5535038e28 ubuntu /bin/sh -c 'while tr 2 minutes ago Up 1 minute insane_babbage @@ -154,6 +161,7 @@ command. Let's use the container name `insane_babbage`. $ docker logs insane_babbage + hello world hello world hello world @@ -169,6 +177,7 @@ Dockerized application! Next, run the `docker stop` command to stop our detached container. $ docker stop insane_babbage + insane_babbage The `docker stop` command tells Docker to politely stop the running @@ -177,6 +186,7 @@ container and returns the name of the container it stopped. Let's check it worked with the `docker ps` command. $ docker ps + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES Excellent. Our container is stopped. diff --git a/docs/tutorials/dockerrepos.md b/docs/tutorials/dockerrepos.md index fdb3fa37b3..b1d76b326d 100644 --- a/docs/tutorials/dockerrepos.md +++ b/docs/tutorials/dockerrepos.md @@ -57,6 +57,7 @@ interface or by using the command line interface. Searching can find images by i name, user name, or description: $ docker search centos + NAME DESCRIPTION STARS OFFICIAL AUTOMATED centos The official build of CentOS 1223 [OK] tianon/centos CentOS 5 and 6, created using rinse instea... 33 @@ -72,6 +73,7 @@ a user's repository from the image name. Once you've found the image you want, you can download it with `docker pull `: $ docker pull centos + Using default tag: latest latest: Pulling from library/centos f1b10cd84249: Pull complete diff --git a/docs/tutorials/dockervolumes.md b/docs/tutorials/dockervolumes.md index 957e09fd66..778f61add2 100644 --- a/docs/tutorials/dockervolumes.md +++ b/docs/tutorials/dockervolumes.md @@ -97,7 +97,7 @@ if the volume is read/write. ### Mount a host directory as a data volume In addition to creating a volume using the `-v` flag you can also mount a -directory from your Engine daemon's host into a container. +directory from your Docker engine's host into a container. ```bash $ docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py @@ -119,10 +119,10 @@ followed by `a-z0-9`, `_` (underscore), `.` (period) or `-` (hyphen). An absolute path starts with a `/` (forward slash). For example, you can specify either `/foo` or `foo` for a `host-dir` value. -If you supply the `/foo` value, Engine creates a bind-mount. If you supply -the `foo` specification, Engine creates a named volume. +If you supply the `/foo` value, the Docker Engine creates a bind-mount. If you supply +the `foo` specification, the Docker Engine creates a named volume. -If you are using Docker Machine on Mac or Windows, your Engine daemon has only +If you are using Docker Machine on Mac or Windows, your Docker Engine daemon has only limited access to your OS X or Windows filesystem. Docker Machine tries to auto-share your `/Users` (OS X) or `C:\Users` (Windows) directory. So, you can mount files or directories on OS X using. @@ -146,8 +146,8 @@ Docker `-v` flag. Mounting a host directory can be useful for testing. For example, you can mount source code inside a container. Then, change the source code and see its effect on the application in real time. The directory on the host must be specified as -an absolute path and if the directory doesn't exist the Engine daemon automatically -creates it for you. +an absolute path and if the directory doesn't exist the Docker Engine daemon +automatically creates it for you. Docker volumes default to mount in read-write mode, but you can also set it to be mounted read-only. @@ -204,6 +204,7 @@ using the `docker volume create` command. ```bash $ docker volume create -d flocker --name my-named-volume -o size=20GB + $ docker run -d -P \ -v my-named-volume:/opt/webapp \ --name web training/webapp python app.py @@ -344,7 +345,7 @@ restore testing using your preferred tools. A Docker data volume persists after a container is deleted. You can create named or anonymous volumes. Named volumes have a specific source form outside the container, for example `awesome:/bar`. Anonymous volumes have no specific -source. When the container is deleted, you should instruction the Engine daemon +source. When the container is deleted, you should instruct the Docker Engine daemon to clean up anonymous volumes. To do this, use the `--rm` option, for example: ```bash @@ -352,7 +353,7 @@ $ docker run --rm -v /foo -v awesome:/bar busybox top ``` This command creates an anonymous `/foo` volume. When the container is removed, -Engine removes the `/foo` volume but not the `awesome` volume. +the Docker Engine removes the `/foo` volume but not the `awesome` volume. ## Important tips on using shared volumes diff --git a/docs/tutorials/networkingcontainers.md b/docs/tutorials/networkingcontainers.md index 144dce44bb..591c90098d 100644 --- a/docs/tutorials/networkingcontainers.md +++ b/docs/tutorials/networkingcontainers.md @@ -41,26 +41,28 @@ You name your container by using the `--name` flag, for example launch a new con Use the `docker ps` command to check the name: $ docker ps -l + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES aed84ee21bde training/webapp:latest python app.py 12 hours ago Up 2 seconds 0.0.0.0:49154->5000/tcp web You can also use `docker inspect` with the container's name. $ docker inspect web + [ - { - "Id": "3ce51710b34f5d6da95e0a340d32aa2e6cf64857fb8cdb2a6c38f7c56f448143", - "Created": "2015-10-25T22:44:17.854367116Z", - "Path": "python", - "Args": [ - "app.py" - ], - "State": { - "Status": "running", - "Running": true, - "Paused": false, - "Restarting": false, - "OOMKilled": false, + { + "Id": "3ce51710b34f5d6da95e0a340d32aa2e6cf64857fb8cdb2a6c38f7c56f448143", + "Created": "2015-10-25T22:44:17.854367116Z", + "Path": "python", + "Args": [ + "app.py" + ], + "State": { + "Status": "running", + "Running": true, + "Paused": false, + "Restarting": false, + "OOMKilled": false, ... Container names must be unique. That means you can only call one container @@ -68,8 +70,11 @@ Container names must be unique. That means you can only call one container (with `docker rm`) before you can reuse the name with a new container. Go ahead and stop and remove your old `web` container. $ docker stop web + web + $ docker rm web + web @@ -83,6 +88,7 @@ that you can create your own drivers but that is an advanced task. Every installation of the Docker Engine automatically includes three default networks. You can list them: $ docker network ls + NETWORK ID NAME DRIVER 18a2866682b8 none null c288470c46f6 host host @@ -91,12 +97,14 @@ Every installation of the Docker Engine automatically includes three default net The network named `bridge` is a special network. Unless you tell it otherwise, Docker always launches your containers in this network. Try this now: $ docker run -itd --name=networktest ubuntu + 74695c9cea6d9810718fddadc01a727a5dd3ce6a69d09752239736c030599741 Inspecting the network is an easy way to find out the container's IP address. ```bash $ docker network inspect bridge + [ { "Name": "bridge", @@ -153,6 +161,7 @@ Docker Engine natively supports both bridge networks and overlay networks. A bri The `-d` flag tells Docker to use the `bridge` driver for the new network. You could have left this flag off as `bridge` is the default value for this flag. Go ahead and list the networks on your machine: $ docker network ls + NETWORK ID NAME DRIVER 7b369448dccb bridge bridge 615d565d498c my-bridge-network bridge @@ -162,6 +171,7 @@ The `-d` flag tells Docker to use the `bridge` driver for the new network. You c If you inspect the network, you'll find that it has nothing in it. $ docker network inspect my-bridge-network + [ { "Name": "my-bridge-network", @@ -188,14 +198,15 @@ To build web applications that act in concert but do so securely, create a network. Networks, by definition, provide complete isolation for containers. You can add containers to a network when you first run a container. -Launch a container running a PostgreSQL database and pass it the `--net=my-bridge-network` flag to connect it to your new network: +Launch a container running a PostgreSQL database and pass it the `--network=my-bridge-network` flag to connect it to your new network: - $ docker run -d --net=my-bridge-network --name db training/postgres + $ docker run -d --network=my-bridge-network --name db training/postgres If you inspect your `my-bridge-network` you'll see it has a container attached. You can also inspect your container to see where it is connected: $ docker inspect --format='{{json .NetworkSettings.Networks}}' db + {"my-bridge-network":{"NetworkID":"7d86d31b1478e7cca9ebed7e73aa0fdeec46c5ca29497431d3007d2d9e15ed99", "EndpointID":"508b170d56b2ac9e4ef86694b0a76a22dd3df1983404f7321da5649645bf7043","Gateway":"172.18.0.1","IPAddress":"172.18.0.2","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:11:00:02"}} @@ -206,17 +217,20 @@ Now, go ahead and start your by now familiar web application. This time leave of Which network is your `web` application running under? Inspect the application and you'll find it is running in the default `bridge` network. $ docker inspect --format='{{json .NetworkSettings.Networks}}' web + {"bridge":{"NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812", "EndpointID":"508b170d56b2ac9e4ef86694b0a76a22dd3df1983404f7321da5649645bf7043","Gateway":"172.17.0.1","IPAddress":"172.17.0.2","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:11:00:02"}} Then, get the IP address of your `web` $ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web + 172.17.0.2 Now, open a shell to your running `db` container: $ docker exec -it db bash + root@a205f0dd33b2:/# ping 172.17.0.2 ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. @@ -233,6 +247,7 @@ Docker networking allows you to attach a container to as many networks as you li Open a shell into the `db` application again and try the ping command. This time just use the container name `web` rather than the IP Address. $ docker exec -it db bash + root@a205f0dd33b2:/# ping web PING web (172.18.0.3) 56(84) bytes of data. 64 bytes from web (172.18.0.3): icmp_seq=1 ttl=64 time=0.095 ms diff --git a/docs/tutorials/usingdocker.md b/docs/tutorials/usingdocker.md index 0aca5b6c37..fa7daa79e9 100644 --- a/docs/tutorials/usingdocker.md +++ b/docs/tutorials/usingdocker.md @@ -115,6 +115,7 @@ Lastly, you've specified a command for our container to run: `python app.py`. Th Now you can see your running container using the `docker ps` command. $ docker ps -l + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bc533791f3f5 training/webapp:latest python app.py 5 seconds ago Up 2 seconds 0.0.0.0:49155->5000/tcp nostalgic_morse @@ -186,6 +187,7 @@ specify the ID or name of our container and then the port for which we need the corresponding public-facing port. $ docker port nostalgic_morse 5000 + 0.0.0.0:49155 In this case you've looked up what port is mapped externally to port 5000 inside @@ -197,6 +199,7 @@ You can also find out a bit more about what's happening with our application and use another of the commands you've learned, `docker logs`. $ docker logs -f nostalgic_morse + * Running on http://0.0.0.0:5000/ 10.0.2.2 - - [23/May/2014 20:16:31] "GET / HTTP/1.1" 200 - 10.0.2.2 - - [23/May/2014 20:16:31] "GET /favicon.ico HTTP/1.1" 404 - @@ -212,6 +215,7 @@ In addition to the container's logs we can also examine the processes running inside it using the `docker top` command. $ docker top nostalgic_morse + PID USER COMMAND 854 root python app.py @@ -245,6 +249,7 @@ We can also narrow down the information we want to return by requesting a specific element, for example to return the container's IP address we would: $ docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nostalgic_morse + 172.17.0.5 ## Stopping our web application container @@ -253,6 +258,7 @@ Okay you've seen web application working. Now you can stop it using the `docker stop` command and the name of our container: `nostalgic_morse`. $ docker stop nostalgic_morse + nostalgic_morse We can now use the `docker ps` command to check if the container has @@ -268,6 +274,7 @@ can create a new container or restart the old one. Look at starting your previous container back up. $ docker start nostalgic_morse + nostalgic_morse Now quickly run `docker ps -l` again to see the running container is @@ -284,6 +291,7 @@ Your colleague has let you know that they've now finished with the container and won't need it again. Now, you can remove it using the `docker rm` command. $ docker rm nostalgic_morse + Error: Impossible to remove a running container, please stop it first or use -f 2014/05/24 08:12:56 Error: failed to remove one or more containers @@ -292,8 +300,11 @@ you from accidentally removing a running container you might need. You can try this again by stopping the container first. $ docker stop nostalgic_morse + nostalgic_morse + $ docker rm nostalgic_morse + nostalgic_morse And now our container is stopped and deleted. diff --git a/docs/userguide/eng-image/baseimages.md b/docs/userguide/eng-image/baseimages.md index 172d65a9c2..86be42e689 100644 --- a/docs/userguide/eng-image/baseimages.md +++ b/docs/userguide/eng-image/baseimages.md @@ -29,8 +29,11 @@ It can be as simple as this to create an Ubuntu base image: $ sudo debootstrap raring raring > /dev/null $ sudo tar -C raring -c . | docker import - raring + a29c15f1bf7a + $ docker run raring cat /etc/lsb-release + DISTRIB_ID=Ubuntu DISTRIB_RELEASE=13.04 DISTRIB_CODENAME=raring diff --git a/docs/userguide/labels-custom-metadata.md b/docs/userguide/labels-custom-metadata.md index c4b6d27a6a..74df2b88f3 100644 --- a/docs/userguide/labels-custom-metadata.md +++ b/docs/userguide/labels-custom-metadata.md @@ -192,6 +192,7 @@ on how to query labels set on a container. These labels appear as part of the `docker info` output for the daemon: $ docker -D info + Containers: 12 Running: 5 Paused: 2 diff --git a/docs/userguide/networking/configure-dns.md b/docs/userguide/networking/configure-dns.md index d248f4294f..434688d636 100644 --- a/docs/userguide/networking/configure-dns.md +++ b/docs/userguide/networking/configure-dns.md @@ -48,13 +48,13 @@ Various container options that affect container domain name services.

- --net-alias=ALIAS + --network-alias=ALIAS

In addition to --name as described above, a container is discovered by one or more - of its configured --net-alias (or --alias in docker network connect command) + of its configured --network-alias (or --alias in docker network connect command) within the user-defined network. The embedded DNS server maintains the mapping between all of the container aliases and its IP address on a specific user-defined network. A container can have different aliases in different networks by using the --alias diff --git a/docs/userguide/networking/default_network/binding.md b/docs/userguide/networking/default_network/binding.md index d8799f4fbd..0ec495a173 100644 --- a/docs/userguide/networking/default_network/binding.md +++ b/docs/userguide/networking/default_network/binding.md @@ -23,6 +23,7 @@ when it starts: ``` $ sudo iptables -t nat -L -n + ... Chain POSTROUTING (policy ACCEPT) target prot opt source destination @@ -56,6 +57,7 @@ network stack by examining your NAT tables. # is finished setting up a -P forward: $ iptables -t nat -L -n + ... Chain DOCKER (2 references) target prot opt source destination diff --git a/docs/userguide/networking/default_network/build-bridges.md b/docs/userguide/networking/default_network/build-bridges.md index 73f35e357e..0cd70215df 100644 --- a/docs/userguide/networking/default_network/build-bridges.md +++ b/docs/userguide/networking/default_network/build-bridges.md @@ -27,8 +27,11 @@ stopping the service and removing the interface: # Stopping Docker and removing docker0 $ sudo service docker stop + $ sudo ip link set dev docker0 down + $ sudo brctl delbr docker0 + $ sudo iptables -t nat -F POSTROUTING ``` @@ -41,12 +44,15 @@ customize `docker0`, but it will be enough to illustrate the technique. # Create our own bridge $ sudo brctl addbr bridge0 + $ sudo ip addr add 192.168.5.1/24 dev bridge0 + $ sudo ip link set dev bridge0 up # Confirming that our bridge is up and running $ ip addr show bridge0 + 4: bridge0: mtu 1500 qdisc noop state UP group default link/ether 66:38:d0:0d:76:18 brd ff:ff:ff:ff:ff:ff inet 192.168.5.1/24 scope global bridge0 @@ -55,11 +61,13 @@ $ ip addr show bridge0 # Tell Docker about it and restart (on Ubuntu) $ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker + $ sudo service docker start # Confirming new outgoing NAT masquerade is set up $ sudo iptables -t nat -L -n + ... Chain POSTROUTING (policy ACCEPT) target prot opt source destination diff --git a/docs/userguide/networking/default_network/configure-dns.md b/docs/userguide/networking/default_network/configure-dns.md index 2703aca1d0..71f189e141 100644 --- a/docs/userguide/networking/default_network/configure-dns.md +++ b/docs/userguide/networking/default_network/configure-dns.md @@ -20,6 +20,7 @@ How can Docker supply each container with a hostname and DNS configuration, with ``` $$ mount + ... /dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ... /dev/disk/by-uuid/1fec...ebdf on /etc/hosts type ext4 ... diff --git a/docs/userguide/networking/default_network/container-communication.md b/docs/userguide/networking/default_network/container-communication.md index 0ca1976333..8e2110af6e 100644 --- a/docs/userguide/networking/default_network/container-communication.md +++ b/docs/userguide/networking/default_network/container-communication.md @@ -31,14 +31,18 @@ set `--ip-forward=false` and your system's kernel has it enabled, the or to turn it on manually: ``` $ sysctl net.ipv4.conf.all.forwarding + net.ipv4.conf.all.forwarding = 0 + $ sysctl net.ipv4.conf.all.forwarding=1 + $ sysctl net.ipv4.conf.all.forwarding + net.ipv4.conf.all.forwarding = 1 ``` > **Note**: this setting does not affect containers that use the host -> network stack (`--net=host`). +> network stack (`--network=host`). Many using Docker will want `ip_forward` to be on, to at least make communication _possible_ between containers and the wider world. May also be @@ -98,6 +102,7 @@ You can run the `iptables` command on your Docker host to see whether the `FORWA # When --icc=false, you should see a DROP rule: $ sudo iptables -L -n + ... Chain FORWARD (policy ACCEPT) target prot opt source destination @@ -110,6 +115,7 @@ DROP all -- 0.0.0.0/0 0.0.0.0/0 # the subsequent DROP policy for all other packets: $ sudo iptables -L -n + ... Chain FORWARD (policy ACCEPT) target prot opt source destination diff --git a/docs/userguide/networking/default_network/custom-docker0.md b/docs/userguide/networking/default_network/custom-docker0.md index 6178b06ab5..f4a3f90c1c 100644 --- a/docs/userguide/networking/default_network/custom-docker0.md +++ b/docs/userguide/networking/default_network/custom-docker0.md @@ -30,6 +30,7 @@ Once you have one or more containers up and running, you can confirm that Docker # Display bridge info $ sudo brctl show + bridge name bridge id STP enabled interfaces docker0 8000.3a1d7362b4ee no veth65f9 vethdda6 @@ -45,6 +46,7 @@ Finally, the `docker0` Ethernet bridge settings are used every time you create a $ docker run -i -t --rm base /bin/bash $$ ip addr show eth0 + 24: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 32:6f:e0:35:57:91 brd ff:ff:ff:ff:ff:ff inet 172.17.0.3/16 scope global eth0 @@ -53,6 +55,7 @@ $$ ip addr show eth0 valid_lft forever preferred_lft forever $$ ip route + default via 172.17.42.1 dev eth0 172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.3 diff --git a/docs/userguide/networking/default_network/dockerlinks.md b/docs/userguide/networking/default_network/dockerlinks.md index 66299002e7..95f32cb4c1 100644 --- a/docs/userguide/networking/default_network/dockerlinks.md +++ b/docs/userguide/networking/default_network/dockerlinks.md @@ -43,6 +43,7 @@ range* on your Docker host. Next, when `docker ps` was run, you saw that port 5000 in the container was bound to port 49155 on the host. $ docker ps nostalgic_morse + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bc533791f3f5 training/webapp:latest python app.py 5 seconds ago Up 2 seconds 0.0.0.0:49155->5000/tcp nostalgic_morse @@ -88,6 +89,7 @@ configurations. For example, if you've bound the container port to the `localhost` on the host machine, then the `docker port` output will reflect that. $ docker port nostalgic_morse 5000 + 127.0.0.1:49155 > **Note:** @@ -132,6 +134,7 @@ name the container `web`. You can see the container's name using the `docker ps` command. $ docker ps -l + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES aed84ee21bde training/webapp:latest python app.py 12 hours ago Up 2 seconds 0.0.0.0:49154->5000/tcp web @@ -187,6 +190,7 @@ example as: Next, inspect your linked containers with `docker inspect`: $ docker inspect -f "{{ .HostConfig.Links }}" web + [/db:/web/db] You can see that the `web` container is now linked to the `db` container @@ -273,6 +277,7 @@ command to list the specified container's environment variables. ``` $ docker run --rm --name web2 --link db:db training/webapp env + . . . DB_NAME=/web2/db DB_PORT=tcp://172.17.0.5:5432 @@ -310,7 +315,9 @@ source container to the `/etc/hosts` file. Here's an entry for the `web` container: $ docker run -t -i --rm --link db:webdb training/webapp /bin/bash + root@aed84ee21bde:/opt/webapp# cat /etc/hosts + 172.17.0.7 aed84ee21bde . . . 172.17.0.5 webdb 6e5cdeb2d300 db @@ -324,7 +331,9 @@ also be added in `/etc/hosts` for the linked container's IP address. You can pin that host now via any of these entries: root@aed84ee21bde:/opt/webapp# apt-get install -yqq inetutils-ping + root@aed84ee21bde:/opt/webapp# ping webdb + PING webdb (172.17.0.5): 48 data bytes 56 bytes from 172.17.0.5: icmp_seq=0 ttl=64 time=0.267 ms 56 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.250 ms @@ -348,9 +357,13 @@ will be automatically updated with the source container's new IP address, allowing linked communication to continue. $ docker restart db + db + $ docker run -t -i --rm --link db:db training/webapp /bin/bash + root@aed84ee21bde:/opt/webapp# cat /etc/hosts + 172.17.0.7 aed84ee21bde . . . 172.17.0.9 db diff --git a/docs/userguide/networking/default_network/ipv6.md b/docs/userguide/networking/default_network/ipv6.md index fc6c968a50..64a1b7e55b 100644 --- a/docs/userguide/networking/default_network/ipv6.md +++ b/docs/userguide/networking/default_network/ipv6.md @@ -48,7 +48,9 @@ starting dockerd with `--ip-forward=false`): ``` $ ip -6 route add 2001:db8:1::/64 dev docker0 + $ sysctl net.ipv6.conf.default.forwarding=1 + $ sysctl net.ipv6.conf.all.forwarding=1 ``` @@ -113,6 +115,7 @@ configure the IPv6 addresses `2001:db8::c000` to `2001:db8::c00f`: ``` $ ip -6 addr show + 1: lo: mtu 65536 inet6 ::1/128 scope host valid_lft forever preferred_lft forever @@ -165,6 +168,7 @@ device to the container network: ``` $ ip -6 route show + 2001:db8::c008/125 dev docker0 metric 1 2001:db8::/64 dev eth0 proto kernel metric 256 ``` diff --git a/docs/userguide/networking/dockernetworks.md b/docs/userguide/networking/dockernetworks.md index 2bab1b41c3..7a70e066d2 100644 --- a/docs/userguide/networking/dockernetworks.md +++ b/docs/userguide/networking/dockernetworks.md @@ -29,6 +29,7 @@ these networks using the `docker network ls` command: ``` $ docker network ls + NETWORK ID NAME DRIVER 7fca4eb8c647 bridge bridge 9f904ee27bf5 none null @@ -36,17 +37,18 @@ cf03ee007fb4 host host ``` Historically, these three networks are part of Docker's implementation. When -you run a container you can use the `--net` flag to specify which network you +you run a container you can use the `--network` flag to specify which network you want to run a container on. These three networks are still available to you. The `bridge` network represents the `docker0` network present in all Docker installations. Unless you specify otherwise with the `docker run ---net=` option, the Docker daemon connects containers to this network +--network=` option, the Docker daemon connects containers to this network by default. You can see this bridge as part of a host's network stack by using the `ifconfig` command on the host. ``` $ ifconfig + docker0 Link encap:Ethernet HWaddr 02:42:47:bc:3a:eb inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:47ff:febc:3aeb/64 Scope:Link @@ -100,6 +102,7 @@ command returns information about a network: ``` $ docker network inspect bridge + [ { "Name": "bridge", @@ -132,9 +135,11 @@ The `docker run` command automatically adds new containers to this network. ``` $ docker run -itd --name=container1 busybox + 3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c $ docker run -itd --name=container2 busybox + 94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c ``` @@ -142,6 +147,7 @@ Inspecting the `bridge` network again after starting two containers shows both n ``` $ docker network inspect bridge + {[ { "Name": "bridge", @@ -215,6 +221,7 @@ Then use `ping` for about 3 seconds to test the connectivity of the containers o ``` root@0cb243cd1293:/# ping -w3 172.17.0.3 + PING 172.17.0.3 (172.17.0.3): 56 data bytes 64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.096 ms 64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.080 ms @@ -229,6 +236,7 @@ Finally, use the `cat` command to check the `container1` network configuration: ``` root@0cb243cd1293:/# cat /etc/hosts + 172.17.0.2 3386a527aa08 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback @@ -243,6 +251,7 @@ To detach from a `container1` and leave it running use `CTRL-p CTRL-q`.Then, att $ docker attach container2 root@0cb243cd1293:/# ifconfig + eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03 inet addr:172.17.0.3 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link @@ -262,6 +271,7 @@ lo Link encap:Local Loopback RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) root@0cb243cd1293:/# ping -w3 172.17.0.2 + PING 172.17.0.2 (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.067 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.075 ms @@ -311,6 +321,7 @@ $ docker network create --driver bridge isolated_nw 1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b $ docker network inspect isolated_nw + [ { "Name": "isolated_nw", @@ -332,6 +343,7 @@ $ docker network inspect isolated_nw ] $ docker network ls + NETWORK ID NAME DRIVER 9f904ee27bf5 none null cf03ee007fb4 host host @@ -340,10 +352,11 @@ c5ee82f76de3 isolated_nw bridge ``` -After you create the network, you can launch containers on it using the `docker run --net=` option. +After you create the network, you can launch containers on it using the `docker run --network=` option. ``` -$ docker run --net=isolated_nw -itd --name=container3 busybox +$ docker run --network=isolated_nw -itd --name=container3 busybox + 8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c $ docker network inspect isolated_nw @@ -460,7 +473,7 @@ provides complete isolation for the containers. Then, on each host, launch containers making sure to specify the network name. - $ docker run -itd --net=my-multi-host-network busybox + $ docker run -itd --network=my-multi-host-network busybox Once connected, each container has access to all the containers in the network regardless of which Docker host the container was launched on. diff --git a/docs/userguide/networking/get-started-overlay.md b/docs/userguide/networking/get-started-overlay.md index 89d5b2ca59..709d48e717 100644 --- a/docs/userguide/networking/get-started-overlay.md +++ b/docs/userguide/networking/get-started-overlay.md @@ -73,6 +73,7 @@ key-value stores. This example uses Consul. 5. Run the `docker ps` command to see the `consul` container. $ docker ps + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4d51392253b3 progrium/consul "/bin/start -server -" 25 minutes ago Up 25 minutes 53/tcp, 53/udp, 8300-8302/tcp, 0.0.0.0:8500->8500/tcp, 8400/tcp, 8301-8302/udp admiring_panini @@ -111,6 +112,7 @@ that machine options that are needed by the `overlay` network driver. 3. List your machines to confirm they are all up and running. $ docker-machine ls + NAME ACTIVE DRIVER STATE URL SWARM default - virtualbox Running tcp://192.168.99.100:2376 mh-keystore * virtualbox Running tcp://192.168.99.103:2376 @@ -134,6 +136,7 @@ To create an overlay network 2. Use the `docker info` command to view the Swarm. $ docker info + Containers: 3 Images: 2 Role: primary @@ -171,6 +174,7 @@ To create an overlay network 4. Check that the network is running: $ docker network ls + NETWORK ID NAME DRIVER 412c2496d0eb mhs-demo1/host host dd51763e6dd2 mhs-demo0/bridge bridge @@ -187,14 +191,19 @@ To create an overlay network 5. Switch to each Swarm agent in turn and list the networks. $ eval $(docker-machine env mhs-demo0) + $ docker network ls + NETWORK ID NAME DRIVER 6b07d0be843f my-net overlay dd51763e6dd2 bridge bridge b4234109bd9b none null 1aeead6dd890 host host + $ eval $(docker-machine env mhs-demo1) + $ docker network ls + NETWORK ID NAME DRIVER d0bb78cbe7bd bridge bridge 1c0eb8f69ebb none null @@ -214,11 +223,12 @@ Once your network is created, you can start a container on any of the hosts and 2. Start an Nginx web server on the `mhs-demo0` instance. - $ docker run -itd --name=web --net=my-net --env="constraint:node==mhs-demo0" nginx + $ docker run -itd --name=web --network=my-net --env="constraint:node==mhs-demo0" nginx 4. Run a BusyBox instance on the `mhs-demo1` instance and get the contents of the Nginx server's home page. - $ docker run -it --rm --net=my-net --env="constraint:node==mhs-demo1" busybox wget -O- http://web + $ docker run -it --rm --network=my-net --env="constraint:node==mhs-demo1" busybox wget -O- http://web + Unable to find image 'busybox:latest' locally latest: Pulling from library/busybox ab2b8a86ca6c: Pull complete @@ -268,6 +278,7 @@ to have external connectivity outside of their cluster. 2. View the `docker_gwbridge` network, by listing the networks. $ docker network ls + NETWORK ID NAME DRIVER 6b07d0be843f my-net overlay dd51763e6dd2 bridge bridge @@ -278,7 +289,9 @@ to have external connectivity outside of their cluster. 3. Repeat steps 1 and 2 on the Swarm master. $ eval $(docker-machine env mhs-demo0) + $ docker network ls + NETWORK ID NAME DRIVER 6b07d0be843f my-net overlay d0bb78cbe7bd bridge bridge @@ -289,6 +302,7 @@ to have external connectivity outside of their cluster. 2. Check the Nginx container's network interfaces. $ docker exec web ip addr + 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo diff --git a/docs/userguide/networking/work-with-networks.md b/docs/userguide/networking/work-with-networks.md index 66c6bd1a63..c142383d4d 100644 --- a/docs/userguide/networking/work-with-networks.md +++ b/docs/userguide/networking/work-with-networks.md @@ -42,7 +42,9 @@ bridge network for you. ```bash $ docker network create simple-network + 69568e6336d8c96bbf57869030919f7c69524f71183b44d80948bd3927c87f6a + $ docker network inspect simple-network [ { @@ -134,8 +136,11 @@ For example, now let's use `-o` or `--opt` options to specify an IP address bind ```bash $ docker network create -o "com.docker.network.bridge.host_binding_ipv4"="172.23.0.1" my-network + b1a086897963e6a2e7fc6868962e55e746bee8ad0c97b54a5831054b5f62672a + $ docker network inspect my-network + [ { "Name": "my-network", @@ -158,9 +163,13 @@ $ docker network inspect my-network } } ] -$ docker run -d -P --name redis --net my-network redis + +$ docker run -d -P --name redis --network my-network redis + bafb0c808c53104b2c90346f284bda33a69beadcab4fc83ab8f2c5a4410cd129 + $ docker ps + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bafb0c808c53 redis "/entrypoint.sh redis" 4 seconds ago Up 3 seconds 172.23.0.1:32770->6379/tcp redis ``` @@ -179,9 +188,11 @@ Create two containers for this example: ```bash $ docker run -itd --name=container1 busybox + 18c062ef45ac0c026ee48a83afa39d25635ee5f02b58de4abc8f467bcaa28731 $ docker run -itd --name=container2 busybox + 498eaaaf328e1018042c04b2de04036fc04719a6e39a097a4f4866043a2c2152 ``` @@ -189,6 +200,7 @@ Then create an isolated, `bridge` network to test with. ```bash $ docker network create -d bridge --subnet 172.25.0.0/16 isolated_nw + 06a62f1c73c4e3107c0f555b7a5f163309827bfbbf999840166065a8f35455a8 ``` @@ -197,7 +209,9 @@ the connection: ``` $ docker network connect isolated_nw container2 + $ docker network inspect isolated_nw + [ { "Name": "isolated_nw", @@ -230,10 +244,11 @@ $ docker network inspect isolated_nw You can see that the Engine automatically assigns an IP address to `container2`. Given we specified a `--subnet` when creating the network, Engine picked an address from that same subnet. Now, start a third container and connect it to -the network on launch using the `docker run` command's `--net` option: +the network on launch using the `docker run` command's `--network` option: ```bash -$ docker run --net=isolated_nw --ip=172.25.3.3 -itd --name=container3 busybox +$ docker run --network=isolated_nw --ip=172.25.3.3 -itd --name=container3 busybox + 467a7863c3f0277ef8e661b38427737f28099b61fa55622d6c30fb288d88c551 ``` @@ -251,6 +266,7 @@ Now, inspect the network resources used by `container3`. ```bash $ docker inspect --format='{{json .NetworkSettings.Networks}}' container3 + {"isolated_nw":{"IPAMConfig":{"IPv4Address":"172.25.3.3"},"NetworkID":"1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b", "EndpointID":"dffc7ec2915af58cc827d995e6ebdc897342be0420123277103c40ae35579103","Gateway":"172.25.0.1","IPAddress":"172.25.3.3","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:19:03:03"}} ``` @@ -258,6 +274,7 @@ Repeat this command for `container2`. If you have Python installed, you can pret ```bash $ docker inspect --format='{{json .NetworkSettings.Networks}}' container2 | python -m json.tool + { "bridge": { "NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812", @@ -391,6 +408,7 @@ same network and cannot communicate. Test, this now by attaching to ```bash $ docker attach container3 + / # ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2): 56 data bytes ^C @@ -432,7 +450,8 @@ Continuing with the above example, create another container `container4` in for other containers in the same network. ```bash -$ docker run --net=isolated_nw -itd --name=container4 --link container5:c5 busybox +$ docker run --network=isolated_nw -itd --name=container4 --link container5:c5 busybox + 01b5df970834b77a9eadbaff39051f237957bd35c4c56f11193e0594cfd5117c ``` @@ -452,7 +471,8 @@ Now let us launch another container named `container5` linking `container4` to c4. ```bash -$ docker run --net=isolated_nw -itd --name=container5 --link container4:c4 busybox +$ docker run --network=isolated_nw -itd --name=container5 --link container4:c4 busybox + 72eccf2208336f31e9e33ba327734125af00d1e1d2657878e2ee8154fbb23c7a ``` @@ -462,6 +482,7 @@ container name and its alias c5 and `container5` will be able to reach ```bash $ docker attach container4 + / # ping -w 4 c5 PING c5 (172.25.0.5): 56 data bytes 64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms @@ -487,6 +508,7 @@ round-trip min/avg/max = 0.070/0.081/0.097 ms ```bash $ docker attach container5 + / # ping -w 4 c4 PING c4 (172.25.0.4): 56 data bytes 64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms @@ -607,12 +629,14 @@ Continuing with the above example, create another container in `isolated_nw` with a network alias. ```bash -$ docker run --net=isolated_nw -itd --name=container6 --net-alias app busybox +$ docker run --network=isolated_nw -itd --name=container6 --network-alias app busybox + 8ebe6767c1e0361f27433090060b33200aac054a68476c3be87ef4005eb1df17 ``` ```bash $ docker attach container4 + / # ping -w 4 app PING app (172.25.0.6): 56 data bytes 64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms @@ -678,7 +702,8 @@ network-scoped alias within the same network. For example, let's launch `container7` in `isolated_nw` with the same alias as `container6` ```bash -$ docker run --net=isolated_nw -itd --name=container7 --net-alias app busybox +$ docker run --network=isolated_nw -itd --name=container7 --network-alias app busybox + 3138c678c123b8799f4c7cc6a0cecc595acbdfa8bf81f621834103cd4f504554 ``` @@ -692,6 +717,7 @@ verify that `container7` is resolving the `app` alias. ```bash $ docker attach container4 + / # ping -w 4 app PING app (172.25.0.6): 56 data bytes 64 bytes from 172.25.0.6: seq=0 ttl=64 time=0.070 ms @@ -706,6 +732,7 @@ round-trip min/avg/max = 0.070/0.081/0.097 ms $ docker stop container6 $ docker attach container4 + / # ping -w 4 app PING app (172.25.0.7): 56 data bytes 64 bytes from 172.25.0.7: seq=0 ttl=64 time=0.095 ms @@ -728,6 +755,7 @@ disconnect` command. $ docker network disconnect isolated_nw container2 $ docker inspect --format='{{json .NetworkSettings.Networks}}' container2 | python -m json.tool + { "bridge": { "NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812", @@ -744,6 +772,7 @@ $ docker inspect --format='{{json .NetworkSettings.Networks}}' container2 | pyt $ docker network inspect isolated_nw + [ { "Name": "isolated_nw", @@ -830,13 +859,16 @@ endpoint from the network. Once the endpoint is cleaned up, the container can be connected to the network. ```bash -$ docker run -d --name redis_db --net multihost redis +$ docker run -d --name redis_db --network multihost redis + ERROR: Cannot start container bc0b19c089978f7845633027aa3435624ca3d12dd4f4f764b61eac4c0610f32e: container already connected to network multihost $ docker rm -f redis_db + $ docker network disconnect -f multihost redis_db -$ docker run -d --name redis_db --net multihost redis +$ docker run -d --name redis_db --network multihost redis + 7d986da974aeea5e9f7aca7e510bdb216d58682faa83a9040c2f2adc0544795a ``` @@ -851,6 +883,7 @@ $ docker network disconnect isolated_nw container3 ```bash docker network inspect isolated_nw + [ { "Name": "isolated_nw", @@ -878,6 +911,7 @@ List all your networks to verify the `isolated_nw` was removed: ```bash $ docker network ls + NETWORK ID NAME DRIVER 72314fa53006 host host f7ab26d71dbd bridge bridge diff --git a/docs/userguide/storagedriver/aufs-driver.md b/docs/userguide/storagedriver/aufs-driver.md index e64c33c972..af0261591f 100644 --- a/docs/userguide/storagedriver/aufs-driver.md +++ b/docs/userguide/storagedriver/aufs-driver.md @@ -97,6 +97,7 @@ You can only use the AUFS storage driver on Linux systems with AUFS installed. Use the following command to determine if your system supports AUFS. $ grep aufs /proc/filesystems + nodev aufs This output indicates the system supports AUFS. Once you've verified your @@ -116,6 +117,7 @@ Once your daemon is running, verify the storage driver with the `docker info` command. $ sudo docker info + Containers: 1 Images: 4 Storage Driver: aufs @@ -153,6 +155,7 @@ stacked below it in the union mount. Remember, these directory names do no map to image layer IDs with Docker 1.10 and higher. $ cat /var/lib/docker/aufs/layers/91e54dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c + d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82 c22013c8472965aa5b62559f2b540cd440716ef149756e7b958a1b2aba421e87 d3a1f33e8a5a513092f01bb7eb1c2abf4d711e5105390a3fe1ae2248cfde1391 diff --git a/docs/userguide/storagedriver/btrfs-driver.md b/docs/userguide/storagedriver/btrfs-driver.md index cc329e731e..dd5da2a229 100644 --- a/docs/userguide/storagedriver/btrfs-driver.md +++ b/docs/userguide/storagedriver/btrfs-driver.md @@ -112,6 +112,7 @@ commands. The example below shows a truncated output of an `ls -l` command an image layer: $ ls -l /var/lib/docker/btrfs/subvolumes/0a17decee4139b0de68478f149cc16346f5e711c5ae3bb969895f22dd6723751/ + total 0 drwxr-xr-x 1 root root 1372 Oct 9 08:39 bin drwxr-xr-x 1 root root 0 Apr 10 2014 boot @@ -173,6 +174,7 @@ Assuming your system meets the prerequisites, do the following: 1. Install the "btrfs-tools" package. $ sudo apt-get install btrfs-tools + Reading package lists... Done Building dependency tree @@ -184,6 +186,7 @@ multiple devices to the `mkfs.btrfs` command creates a pool across all of those devices. Here you create a pool with a single device at `/dev/xvdb`. $ sudo mkfs.btrfs -f /dev/xvdb + WARNING! - Btrfs v3.12 IS EXPERIMENTAL WARNING! - see http://btrfs.wiki.kernel.org before using @@ -209,6 +212,7 @@ multiple devices to the `mkfs.btrfs` command creates a pool across all of those a. Obtain the Btrfs filesystem's UUID. $ sudo blkid /dev/xvdb + /dev/xvdb: UUID="a0ed851e-158b-4120-8416-c9b072c8cf47" UUID_SUB="c3927a64-4454-4eef-95c2-a7d44ac0cf27" TYPE="btrfs" b. Create an `/etc/fstab` entry to automatically mount `/var/lib/docker` @@ -222,7 +226,9 @@ remember to substitute the UUID value with the value obtained from the previous 5. Mount the new filesystem and verify the operation. $ sudo mount -a + $ mount + /dev/xvda1 on / type ext4 (rw,discard) /dev/xvdb on /var/lib/docker type btrfs (rw) @@ -236,6 +242,7 @@ should automatically load with the `btrfs` storage driver. 1. Start the Docker daemon. $ sudo service docker start + docker start/running, process 2315 The procedure for starting the Docker daemon may differ depending on the @@ -249,6 +256,7 @@ daemon` at startup, or adding it to the `DOCKER_OPTS` line to the Docker config 2. Verify the storage driver with the `docker info` command. $ sudo docker info + Containers: 0 Images: 0 Storage Driver: btrfs diff --git a/docs/userguide/storagedriver/device-mapper-driver.md b/docs/userguide/storagedriver/device-mapper-driver.md index 8b8822f847..30ca6fed9b 100644 --- a/docs/userguide/storagedriver/device-mapper-driver.md +++ b/docs/userguide/storagedriver/device-mapper-driver.md @@ -182,6 +182,7 @@ You can detect the mode by viewing the `docker info` command: ```bash $ sudo docker info + Containers: 0 Images: 0 Storage Driver: devicemapper @@ -312,7 +313,7 @@ assumes that the Docker daemon is in the `stopped` state. 14. Configure the Docker daemon with specific devicemapper options. - There are two ways to do this. You can set options on the commmand line if you start the daemon there: + There are two ways to do this. You can set options on the command line if you start the daemon there: ```bash --storage-driver=devicemapper --storage-opt=dm.thinpooldev=/dev/mapper/docker-thinpool --storage-opt dm.use_deferred_removal=true @@ -416,6 +417,7 @@ the specifics of the existing configuration use `docker info`: ```bash $ sudo docker info + Containers: 0 Running: 0 Paused: 0 @@ -453,6 +455,7 @@ The `Data Space` values show that the pool is 100GB total. This example extends ```bash $ sudo ls -lh /var/lib/docker/devicemapper/devicemapper/ + total 1175492 -rw------- 1 root root 100G Mar 30 05:22 data -rw------- 1 root root 2.0G Mar 31 11:17 metadata @@ -468,6 +471,7 @@ The `Data Space` values show that the pool is 100GB total. This example extends ```bash $ sudo ls -lh /var/lib/docker/devicemapper/devicemapper/ + total 1.2G -rw------- 1 root root 200G Apr 14 08:47 data -rw------- 1 root root 2.0G Apr 19 13:27 metadata @@ -477,9 +481,13 @@ The `Data Space` values show that the pool is 100GB total. This example extends ```bash $ sudo blockdev --getsize64 /dev/loop0 + 107374182400 + $ sudo losetup -c /dev/loop0 + $ sudo blockdev --getsize64 /dev/loop0 + 214748364800 ``` @@ -489,6 +497,7 @@ The `Data Space` values show that the pool is 100GB total. This example extends ```bash $ sudo dmsetup status | grep pool + docker-8:1-123141-pool: 0 209715200 thin-pool 91 422/524288 18338/1638400 - rw discard_passdown queue_if_no_space - ``` @@ -499,6 +508,7 @@ The `Data Space` values show that the pool is 100GB total. This example extends ```bash $ sudo dmsetup table docker-8:1-123141-pool + 0 209715200 thin-pool 7:1 7:0 128 32768 1 skip_block_zeroing ``` @@ -540,6 +550,7 @@ disk partition. ```bash $ sudo vgextend vg-docker /dev/sdh1 + Volume group "vg-docker" successfully extended ``` @@ -549,6 +560,7 @@ disk partition. ```bash $ sudo lvextend -l+100%FREE -n vg-docker/data + Extending logical volume data to 200 GiB Logical volume data successfully resized ``` @@ -559,6 +571,7 @@ disk partition. ```bash $ sudo dmsetup status | grep pool + docker-253:17-1835016-pool: 0 96460800 thin-pool 51593 6270/1048576 701943/753600 - rw no_discard_passdown queue_if_no_space ``` @@ -568,6 +581,7 @@ disk partition. ```bash $ sudo dmsetup table docker-253:17-1835016-pool + 0 96460800 thin-pool 252:0 252:1 128 32768 1 skip_block_zeroing ``` @@ -580,6 +594,7 @@ disk partition. ```bash $ sudo blockdev --getsize64 /dev/vg-docker/data + 264132100096 ``` diff --git a/docs/userguide/storagedriver/imagesandcontainers.md b/docs/userguide/storagedriver/imagesandcontainers.md index 0ff08e872d..69d7536cf6 100644 --- a/docs/userguide/storagedriver/imagesandcontainers.md +++ b/docs/userguide/storagedriver/imagesandcontainers.md @@ -101,6 +101,7 @@ single 8GB general purpose SSD EBS volume. The Docker data directory (`/var/lib/docker`) was consuming 2GB of space. $ docker images + REPOSITORY TAG IMAGE ID CREATED SIZE jenkins latest 285c9f0f9d3d 17 hours ago 708.5 MB mysql latest d39c3fa09ced 8 days ago 360.3 MB @@ -111,9 +112,11 @@ single 8GB general purpose SSD EBS volume. The Docker data directory ubuntu 15.04 c8be1ac8145a 7 weeks ago 131.3 MB $ sudo du -hs /var/lib/docker + 2.0G /var/lib/docker $ time docker run --rm -v /var/lib/docker:/var/lib/docker docker/v1.10-migrator + Unable to find image 'docker/v1.10-migrator:latest' locally latest: Pulling from docker/v1.10-migrator ed1f33c5883d: Pull complete @@ -203,6 +206,7 @@ images with `docker pull` and `docker push`. The command below pulls the `ubuntu:15.04` Docker image from Docker Hub. $ docker pull ubuntu:15.04 + 15.04: Pulling from library/ubuntu 1ba8ac955b97: Pull complete f157c4e5ede7: Pull complete @@ -226,6 +230,7 @@ image being pulled from Docker Hub, followed by a directory listing on a host running version 1.9.1 of the Docker Engine. $ docker pull ubuntu:15.04 + 15.04: Pulling from library/ubuntu 47984b517ca9: Pull complete df6e891a3ea9: Pull complete @@ -235,6 +240,7 @@ running version 1.9.1 of the Docker Engine. Status: Downloaded newer image for ubuntu:15.04 $ ls /var/lib/docker/aufs/layers + 47984b517ca9ca0312aced5c9698753ffa964c2015f2a5f18e5efa9848cf30e2 c8be1ac8145a6e59a55667f573883749ad66eaeef92b4df17e5ea1260e2d7356 df6e891a3ea9cdce2a388a2cf1b1711629557454fd120abd5be6d32329a0e0ac @@ -294,6 +300,7 @@ command. command: $ docker build -t changed-ubuntu . + Sending build context to Docker daemon 2.048 kB Step 1 : FROM ubuntu:15.04 ---> 3f7bcee56709 @@ -411,14 +418,23 @@ Let's see what happens if we spin up 5 containers based on our `changed-ubuntu` 5 times. $ docker run -dit changed-ubuntu bash + 75bab0d54f3cf193cfdc3a86483466363f442fba30859f7dcd1b816b6ede82d4 + $ docker run -dit changed-ubuntu bash + 9280e777d109e2eb4b13ab211553516124a3d4d4280a0edfc7abf75c59024d47 + $ docker run -dit changed-ubuntu bash + a651680bd6c2ef64902e154eeb8a064b85c9abf08ac46f922ad8dfc11bb5cd8a + $ docker run -dit changed-ubuntu bash + 8eb24b3b2d246f225b24f2fca39625aaad71689c392a7b552b78baf264647373 + $ docker run -dit changed-ubuntu bash + 0ad25d06bdf6fca0dedc38301b2aff7478b3e1ce3d1acd676573bba57cb1cfef This launches 5 containers based on the `changed-ubuntu` image. As each @@ -442,6 +458,7 @@ creating each container. 3. List the contents of the local storage area. $ sudo ls /var/lib/docker/containers + 0ad25d06bdf6fca0dedc38301b2aff7478b3e1ce3d1acd676573bba57cb1cfef 9280e777d109e2eb4b13ab211553516124a3d4d4280a0edfc7abf75c59024d47 75bab0d54f3cf193cfdc3a86483466363f442fba30859f7dcd1b816b6ede82d4 diff --git a/docs/userguide/storagedriver/overlayfs-driver.md b/docs/userguide/storagedriver/overlayfs-driver.md index bb9eea036e..6d4d47b5af 100644 --- a/docs/userguide/storagedriver/overlayfs-driver.md +++ b/docs/userguide/storagedriver/overlayfs-driver.md @@ -78,6 +78,7 @@ The following `docker pull` command shows a Docker host with downloading a Docker image comprising five layers. $ sudo docker pull ubuntu + Using default tag: latest latest: Pulling from library/ubuntu @@ -98,6 +99,7 @@ layer IDs do not match the directory names in `/var/lib/docker/overlay`. This is normal behavior in Docker 1.10 and later. $ ls -l /var/lib/docker/overlay/ + total 20 drwx------ 3 root root 4096 Jun 20 16:11 38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8 drwx------ 3 root root 4096 Jun 20 16:11 55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358 @@ -110,8 +112,11 @@ hard links to the data that is shared with lower layers. This allows for efficient use of disk space. $ ls -i /var/lib/docker/overlay/38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8/root/bin/ls + 19793696 /var/lib/docker/overlay/38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8/root/bin/ls + $ ls -i /var/lib/docker/overlay/55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358/root/bin/ls + 19793696 /var/lib/docker/overlay/55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358/root/bin/ls Containers also exist on-disk in the Docker host's filesystem under @@ -120,6 +125,7 @@ container using the `ls -l` command, you find the following file and directories. $ ls -l /var/lib/docker/overlay/ + total 16 -rw-r--r-- 1 root root 64 Jun 20 16:39 lower-id drwxr-xr-x 1 root root 4096 Jun 20 16:39 merged @@ -131,6 +137,7 @@ file contains the ID of the top layer of the image the container is based on. This is used by OverlayFS as the "lowerdir". $ cat /var/lib/docker/overlay/ec444863a55a9f1ca2df72223d459c5d940a721b2288ff86a3f27be28b53be6c/lower-id + 55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358 The "upper" directory is the containers read-write layer. Any changes made to @@ -148,6 +155,7 @@ You can verify all of these constructs from the output of the `mount` command. (Ellipses and line breaks are used in the output below to enhance readability.) $ mount | grep overlay + overlay on /var/lib/docker/overlay/ec444863a55a.../merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay/55f1e14c361b.../root, upperdir=/var/lib/docker/overlay/ec444863a55a.../upper, @@ -170,6 +178,7 @@ After downloading a five-layer image using `docker pull ubuntu`, you can see six directories under `/var/lib/docker/overlay2`. $ ls -l /var/lib/docker/overlay2 + total 24 drwx------ 5 root root 4096 Jun 20 07:36 223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7 drwx------ 3 root root 4096 Jun 20 07:36 3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b @@ -183,6 +192,7 @@ shortened identifiers are used for avoid hitting the page size limitation on mount arguments. $ ls -l /var/lib/docker/overlay2/l + total 20 lrwxrwxrwx 1 root root 72 Jun 20 07:36 6Y5IM2XC7TSNIJZZFLJCS6I4I4 -> ../3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/diff lrwxrwxrwx 1 root root 72 Jun 20 07:36 B3WWEFKBG3PLLV737KZFIASSW7 -> ../4e9fa83caff3e8f4cc83693fa407a4a9fac9573deaf481506c102d484dd1e6a1/diff @@ -194,10 +204,15 @@ The lowerest layer contains the "link" file which contains the name of the short identifier, and the "diff" directory which contains the contents. $ ls /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/ + diff link + $ cat /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/link + 6Y5IM2XC7TSNIJZZFLJCS6I4I4 + $ ls /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/diff + bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var The second layer contains the "lower" file for denoting the layer composition, @@ -205,22 +220,30 @@ and the "diff" directory for the layer contents. It also contains the "merged" the "work" directories. $ ls /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7 + diff link lower merged work + $ cat /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7/lower + l/6Y5IM2XC7TSNIJZZFLJCS6I4I4 + $ ls /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7/diff/ + etc sbin usr var A directory for running container have similar files and directories as well. Note that the lower list is separated by ':', and ordered from highest layer to lower. $ ls -l /var/lib/docker/overlay/ + $ cat /var/lib/docker/overlay//lower + l/DJA75GUWHWG7EWICFYX54FIOVT:l/B3WWEFKBG3PLLV737KZFIASSW7:l/JEYMODZYFCZFYSDABYXD5MF6YO:l/UL2MW33MSE3Q5VYIKBRN4ZAGQP:l/NFYKDW6APBCCUCTOUSYDH4DXAT:l/6Y5IM2XC7TSNIJZZFLJCS6I4I4 The result of `mount` is as follows: $ mount | grep overlay + overlay on /var/lib/docker/overlay2/9186877cdf386d0a3b016149cf30c208f326dca307529e646afce5b3f83f5304/merged type overlay (rw,relatime, lowerdir=l/DJA75GUWHWG7EWICFYX54FIOVT:l/B3WWEFKBG3PLLV737KZFIASSW7:l/JEYMODZYFCZFYSDABYXD5MF6YO:l/UL2MW33MSE3Q5VYIKBRN4ZAGQP:l/NFYKDW6APBCCUCTOUSYDH4DXAT:l/6Y5IM2XC7TSNIJZZFLJCS6I4I4, @@ -298,14 +321,17 @@ OverlayFS. The procedure assumes that the Docker daemon is in a stopped state. 2. Verify your kernel version and that the overlay kernel module is loaded. $ uname -r + 3.19.0-21-generic $ lsmod | grep overlay + overlay 3. Start the Docker daemon with the `overlay`/`overlay2` storage driver. $ dockerd --storage-driver=overlay & + [1] 29403 root@ip-10-0-0-174:/home/ubuntu# INFO[0000] Listening for HTTP on unix (/var/run/docker.sock) INFO[0000] Option DefaultDriver: bridge @@ -321,6 +347,7 @@ OverlayFS. The procedure assumes that the Docker daemon is in a stopped state. 4. Verify that the daemon is using the `overlay`/`overlay2` storage driver $ docker info + Containers: 0 Images: 0 Storage Driver: overlay diff --git a/docs/userguide/storagedriver/selectadriver.md b/docs/userguide/storagedriver/selectadriver.md index baa7238a33..0677f5d7a2 100644 --- a/docs/userguide/storagedriver/selectadriver.md +++ b/docs/userguide/storagedriver/selectadriver.md @@ -47,6 +47,7 @@ To find out which storage driver is set on the daemon, you use the `docker info` command: $ docker info + Containers: 0 Images: 0 Storage Driver: overlay @@ -96,6 +97,7 @@ The following command shows how to start the Docker daemon with the $ dockerd --storage-driver=devicemapper & $ docker info + Containers: 0 Images: 0 Storage Driver: devicemapper diff --git a/docs/userguide/storagedriver/zfs-driver.md b/docs/userguide/storagedriver/zfs-driver.md index 87d2472240..e5b6dbcd8e 100644 --- a/docs/userguide/storagedriver/zfs-driver.md +++ b/docs/userguide/storagedriver/zfs-driver.md @@ -136,6 +136,7 @@ you should substitute your own values throughout the procedure. 2. Install the `zfs` package. $ sudo apt-get install -y zfs + Reading package lists... Done Building dependency tree @@ -143,6 +144,7 @@ you should substitute your own values throughout the procedure. 3. Verify that the `zfs` module is loaded correctly. $ lsmod | grep zfs + zfs 2813952 3 zunicode 331776 1 zfs zcommon 57344 1 zfs @@ -159,6 +161,7 @@ you should substitute your own values throughout the procedure. This is required for the `add-apt-repository` command. $ sudo apt-get install -y software-properties-common + Reading package lists... Done Building dependency tree @@ -166,6 +169,7 @@ you should substitute your own values throughout the procedure. 2. Add the `zfs-native` package archive. $ sudo add-apt-repository ppa:zfs-native/stable + The native ZFS filesystem for Linux. Install the ubuntu-zfs package. gpg: key F6B0FC61: public key "Launchpad PPA for Native ZFS for Linux" imported @@ -177,6 +181,7 @@ you should substitute your own values throughout the procedure. archives. $ sudo apt-get update + Ign http://us-west-2.ec2.archive.ubuntu.com trusty InRelease Get:1 http://us-west-2.ec2.archive.ubuntu.com trusty-updates InRelease [64.4 kB] @@ -186,6 +191,7 @@ archives. 4. Install the `ubuntu-zfs` package. $ sudo apt-get install -y ubuntu-zfs + Reading package lists... Done Building dependency tree @@ -197,6 +203,7 @@ archives. 6. Verify that it loaded correctly. $ lsmod | grep zfs + zfs 2768247 0 zunicode 331170 1 zfs zcommon 55411 1 zfs @@ -218,6 +225,7 @@ Once ZFS is installed and loaded, you're ready to configure ZFS for Docker. 2. Check that the `zpool` exists. $ sudo zfs list + NAME USED AVAIL REFER MOUNTPOINT zpool-docker 55K 3.84G 19K /zpool-docker @@ -228,6 +236,7 @@ Once ZFS is installed and loaded, you're ready to configure ZFS for Docker. 4. Check that the previous step worked. $ sudo zfs list -t all + NAME USED AVAIL REFER MOUNTPOINT zpool-docker 93.5K 3.84G 19K /zpool-docker zpool-docker/docker 19K 3.84G 19K /var/lib/docker @@ -238,6 +247,7 @@ Once ZFS is installed and loaded, you're ready to configure ZFS for Docker. 5. Start the Docker daemon. $ sudo service docker start + docker start/running, process 2315 The procedure for starting the Docker daemon may differ depending on the @@ -249,6 +259,7 @@ Once ZFS is installed and loaded, you're ready to configure ZFS for Docker. 6. Verify that the daemon is using the `zfs` storage driver. $ sudo docker info + Containers: 0 Images: 0 Storage Driver: zfs diff --git a/experimental/docker-stacks-and-bundles.md b/experimental/docker-stacks-and-bundles.md index 095cea449e..1da2b8f587 100644 --- a/experimental/docker-stacks-and-bundles.md +++ b/experimental/docker-stacks-and-bundles.md @@ -77,7 +77,7 @@ axqh55ipl40h vossibility-stack_vossibility-collector 1 icecrime/vossibility-co ## Managing stacks -Tasks are managed using the `docker stack` command: +Stacks are managed using the `docker stack` command: ```bash # docker stack --help diff --git a/experimental/vlan-networks.md b/experimental/vlan-networks.md index 66723b9bde..7704c5758f 100644 --- a/experimental/vlan-networks.md +++ b/experimental/vlan-networks.md @@ -627,7 +627,7 @@ docker network create -d ipvlan \ # Start a few of containers on the network (ipnet110) -# in seperate terminals and check connectivity +# in separate terminals and check connectivity docker run --net=ipnet110 -it --rm alpine /bin/sh # Start a second container specifying the v6 address docker run --net=ipnet110 --ip6=2001:db8:abc6::10 -it --rm alpine /bin/sh diff --git a/hack/.vendor-helpers.sh b/hack/.vendor-helpers.sh index 94ed5cc5bb..82fe7b3b38 100755 --- a/hack/.vendor-helpers.sh +++ b/hack/.vendor-helpers.sh @@ -131,6 +131,9 @@ clean() { findArgs+=( -path "vendor/src/$import" ) done + # The docker proxy command is built from libnetwork + findArgs+=( -or -path vendor/src/github.com/docker/libnetwork/cmd/proxy ) + local IFS=$'\n' local prune=( $($find vendor -depth -type d -not '(' "${findArgs[@]}" ')') ) unset IFS diff --git a/hack/make/.binary-setup b/hack/make/.binary-setup index 90c8a336ea..e388c64485 100644 --- a/hack/make/.binary-setup +++ b/hack/make/.binary-setup @@ -2,3 +2,4 @@ DOCKER_CLIENT_BINARY_NAME='docker' DOCKER_DAEMON_BINARY_NAME='dockerd' +DOCKER_PROXY_BINARY_NAME='docker-proxy' diff --git a/hack/make/.build-deb/rules b/hack/make/.build-deb/rules index 2cd86691d3..bd097c7619 100755 --- a/hack/make/.build-deb/rules +++ b/hack/make/.build-deb/rules @@ -1,6 +1,8 @@ #!/usr/bin/make -f VERSION = $(shell cat VERSION) +SYSTEMD_VERSION := $(shell dpkg-query -W -f='$${Version}\n' systemd | cut -d- -f1) +SYSTEMD_GT_227 := $(shell [ '$(SYSTEMD_VERSION)' ] && [ '$(SYSTEMD_VERSION)' -gt 227 ] && echo true ) override_dh_gencontrol: # if we're on Ubuntu, we need to Recommends: apparmor @@ -22,6 +24,7 @@ override_dh_auto_install: mkdir -p debian/docker-engine/usr/bin cp -aT "$$(readlink -f bundles/$(VERSION)/dynbinary-client/docker)" debian/docker-engine/usr/bin/docker cp -aT "$$(readlink -f bundles/$(VERSION)/dynbinary-daemon/dockerd)" debian/docker-engine/usr/bin/dockerd + cp -aT "$$(readlink -f bundles/$(VERSION)/dynbinary-daemon/docker-proxy)" debian/docker-engine/usr/bin/docker-proxy cp -aT /usr/local/bin/containerd debian/docker-engine/usr/bin/docker-containerd cp -aT /usr/local/bin/containerd-shim debian/docker-engine/usr/bin/docker-containerd-shim cp -aT /usr/local/bin/ctr debian/docker-engine/usr/bin/docker-containerd-ctr @@ -31,6 +34,10 @@ override_dh_auto_install: override_dh_installinit: # use "docker" as our service name, not "docker-engine" dh_installinit --name=docker +ifeq (true, $(SYSTEMD_GT_227)) + $(warning "Setting TasksMax=infinity") + sed -i -- 's/#TasksMax=infinity/TasksMax=infinity/' debian/docker-engine/lib/systemd/system/docker.service +endif override_dh_installudev: # match our existing priority diff --git a/hack/make/.build-rpm/docker-engine.spec b/hack/make/.build-rpm/docker-engine.spec index a433d54bc7..29535e53c4 100644 --- a/hack/make/.build-rpm/docker-engine.spec +++ b/hack/make/.build-rpm/docker-engine.spec @@ -126,6 +126,7 @@ export DOCKER_GITCOMMIT=%{_gitcommit} install -d $RPM_BUILD_ROOT/%{_bindir} install -p -m 755 bundles/%{_origversion}/dynbinary-client/docker-%{_origversion} $RPM_BUILD_ROOT/%{_bindir}/docker install -p -m 755 bundles/%{_origversion}/dynbinary-daemon/dockerd-%{_origversion} $RPM_BUILD_ROOT/%{_bindir}/dockerd +install -p -m 755 bundles/%{_origversion}/dynbinary-daemon/docker-proxy-%{_origversion} $RPM_BUILD_ROOT/%{_bindir}/docker-proxy # install containerd install -p -m 755 /usr/local/bin/containerd $RPM_BUILD_ROOT/%{_bindir}/docker-containerd @@ -188,6 +189,7 @@ install -p -m 644 contrib/syntax/nano/Dockerfile.nanorc $RPM_BUILD_ROOT/usr/shar /%{_bindir}/docker-containerd /%{_bindir}/docker-containerd-shim /%{_bindir}/docker-containerd-ctr +/%{_bindir}/docker-proxy /%{_bindir}/docker-runc /%{_sysconfdir}/udev/rules.d/80-docker.rules %if 0%{?is_systemd} diff --git a/hack/make/binary-daemon b/hack/make/binary-daemon index bf2fb7b2ca..e75c44c587 100644 --- a/hack/make/binary-daemon +++ b/hack/make/binary-daemon @@ -9,5 +9,8 @@ set -e export BINARY_SHORT_NAME="$DOCKER_DAEMON_BINARY_NAME" export SOURCE_PATH='./cmd/dockerd' source "${MAKEDIR}/.binary" + export BINARY_SHORT_NAME="$DOCKER_PROXY_BINARY_NAME" + export SOURCE_PATH='./vendor/src/github.com/docker/libnetwork/cmd/proxy' + source "${MAKEDIR}/.binary" copy_containerd "$DEST" 'hash' ) diff --git a/hack/make/dynbinary b/hack/make/dynbinary index a1285327d1..1a435dc4bf 100644 --- a/hack/make/dynbinary +++ b/hack/make/dynbinary @@ -1,7 +1,7 @@ #!/bin/bash set -e -# This script exists as backwards compatiblity for CI +# This script exists as backwards compatibility for CI ( DEST="${DEST}-client" ABS_DEST="${ABS_DEST}-client" diff --git a/hack/make/dynbinary-daemon b/hack/make/dynbinary-daemon index 398b951d85..cd7937859c 100644 --- a/hack/make/dynbinary-daemon +++ b/hack/make/dynbinary-daemon @@ -9,4 +9,7 @@ set -e export BUILDFLAGS=( "${BUILDFLAGS[@]/netgo /}" ) # disable netgo, since we don't need it for a dynamic binary export BUILDFLAGS=( "${BUILDFLAGS[@]/static_build /}" ) # we're not building a "static" binary here source "${MAKEDIR}/.binary" + export BINARY_SHORT_NAME='docker-proxy' + export SOURCE_PATH='./vendor/src/github.com/docker/libnetwork/cmd/proxy' + source "${MAKEDIR}/.binary" ) diff --git a/hack/make/gccgo b/hack/make/gccgo index 93e064a879..54c983eb2e 100644 --- a/hack/make/gccgo +++ b/hack/make/gccgo @@ -5,6 +5,9 @@ BINARY_NAME="dockerd-$VERSION" BINARY_EXTENSION="$(binary_extension)" BINARY_FULLNAME="$BINARY_NAME$BINARY_EXTENSION" +PROXY_NAME="docker-proxy-$VERSION" +PROXY_FULLNAME="$PROXY_NAME$BINARY_EXTENSION" + CLIENTBIN_NAME="docker-$VERSION" CLIENTBIN_FULLNAME="$CLIENTBIN_NAME$BINARY_EXTENSION" @@ -29,6 +32,21 @@ go build -compiler=gccgo \ echo "Created binary: $DEST/$BINARY_FULLNAME" ln -sf "$BINARY_FULLNAME" "$DEST/dockerd$BINARY_EXTENSION" +go build -compiler=gccgo \ + -o "$DEST/$PROXY_FULLNAME" \ + "${BUILDFLAGS[@]}" \ + -gccgoflags " + -g + $EXTLDFLAGS_STATIC + -Wl,--no-export-dynamic + -ldl + -pthread + " \ + ./vendor/src/github.com/docker/libnetwork/cmd/proxy + +echo "Created binary: $DEST/$PROXY_FULLNAME" +ln -sf "$PROXY_FULLNAME" "$DEST/docker-proxy$BINARY_EXTENSION" + copy_containerd "$DEST" "hash" hash_files "$DEST/$BINARY_FULLNAME" diff --git a/hack/make/install-binary-daemon b/hack/make/install-binary-daemon index 36b6c5e95a..e80d8431fd 100644 --- a/hack/make/install-binary-daemon +++ b/hack/make/install-binary-daemon @@ -7,4 +7,5 @@ rm -rf "$DEST" DEST="$(dirname $DEST)/binary-daemon" source "${MAKEDIR}/.binary-setup" install_binary "${DEST}/${DOCKER_DAEMON_BINARY_NAME}" + install_binary "${DEST}/${DOCKER_PROXY_BINARY_NAME}" ) diff --git a/hack/make/tgz b/hack/make/tgz index 5b1663256b..b1abfef92f 100644 --- a/hack/make/tgz +++ b/hack/make/tgz @@ -18,6 +18,7 @@ for d in "$CROSS/"*/*; do BINARY_NAME="${DOCKER_CLIENT_BINARY_NAME}-$VERSION" DAEMON_BINARY_NAME="${DOCKER_DAEMON_BINARY_NAME}-$VERSION" + PROXY_BINARY_NAME="${DOCKER_PROXY_BINARY_NAME}-$VERSION" BINARY_EXTENSION="$(export GOOS && binary_extension)" if [ "$GOOS" = 'windows' ]; then # if windows use a zip, not tgz @@ -29,6 +30,7 @@ for d in "$CROSS/"*/*; do fi BINARY_FULLNAME="$BINARY_NAME$BINARY_EXTENSION" DAEMON_BINARY_FULLNAME="$DAEMON_BINARY_NAME$BINARY_EXTENSION" + PROXY_BINARY_FULLNAME="$PROXY_BINARY_NAME$BINARY_EXTENSION" mkdir -p "$DEST/$GOOS/$GOARCH" TGZ="$DEST/$GOOS/$GOARCH/$BINARY_NAME$BUNDLE_EXTENSION" @@ -47,6 +49,9 @@ for d in "$CROSS/"*/*; do if [ -f "$d/$DAEMON_BINARY_FULLNAME" ]; then cp -L "$d/$DAEMON_BINARY_FULLNAME" "$TAR_PATH/${DOCKER_DAEMON_BINARY_NAME}${BINARY_EXTENSION}" fi + if [ -f "$d/$PROXY_BINARY_FULLNAME" ]; then + cp -L "$d/$PROXY_BINARY_FULLNAME" "$TAR_PATH/${DOCKER_PROXY_BINARY_NAME}${BINARY_EXTENSION}" + fi # copy over all the containerd binaries copy_containerd $TAR_PATH diff --git a/hack/vendor.sh b/hack/vendor.sh index 1cd71e48ad..d759fe10f6 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -60,12 +60,12 @@ clone git golang.org/x/net 2beffdc2e92c8a3027590f898fe88f69af48a3f8 https://gith clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://github.com/golang/sys.git clone git github.com/docker/go-units 651fc226e7441360384da338d0fd37f2440ffbe3 clone git github.com/docker/go-connections fa2850ff103453a9ad190da0df0af134f0314b3d -clone git github.com/docker/engine-api 62043eb79d581a32ea849645277023c550732e52 +clone git github.com/docker/engine-api 1d247454d4307fb1ddf10d09fd2996394b085904 clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837 clone git github.com/imdario/mergo 0.2.1 #get libnetwork packages -clone git github.com/docker/libnetwork 377a7337f2387cce3be1df7a4503446147b68ff1 +clone git github.com/docker/libnetwork 9b821dc123ca07e2c4d7244943f4e3e9632904fb clone git github.com/docker/go-events 39718a26497694185f8fb58a7d6f31947f3dc42d clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec @@ -87,7 +87,7 @@ clone git github.com/boltdb/bolt v1.2.1 clone git github.com/miekg/dns 75e6e86cc601825c5dbcd4e0c209eab180997cd7 # get graph and distribution packages -clone git github.com/docker/distribution 5bbf65499960b184fe8e0f045397375e1a6722b8 +clone git github.com/docker/distribution 4e17ab5d319ac5b70b2769442947567a83386fbc clone git github.com/vbatts/tar-split v0.9.11 # get go-zfs packages @@ -139,7 +139,7 @@ clone git github.com/docker/docker-credential-helpers v0.3.0 clone git github.com/docker/containerd 1b3a81545ca79456086dc2aa424357be98b962ee # cluster -clone git github.com/docker/swarmkit 036a4a1e934bd1bbb35c3ec7f85dea2ba6d4e336 +clone git github.com/docker/swarmkit 6478bc19cf4bc1d7ba2d6f04ccaacf099508f4a0 clone git github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9 clone git github.com/gogo/protobuf 43a2e0b1c32252bfbbdf81f7faa7a88fb3fa4028 clone git github.com/cloudflare/cfssl b895b0549c0ff676f92cf09ba971ae02bb41367b diff --git a/image/spec/v1.1.md b/image/spec/v1.1.md index 0b7d5395f6..3a32b6bd36 100644 --- a/image/spec/v1.1.md +++ b/image/spec/v1.1.md @@ -87,7 +87,8 @@ This specification uses the following terms:

A tag serves to map a descriptive, user-given name to any single image ID. Tag values are limited to the set of characters - [a-zA-Z_0-9]. + [a-zA-Z0-9_.-], except they may not start with a . + or - character. Tags are limited to 127 characters.
Repository @@ -573,7 +574,7 @@ these directories contains 3 files: * `json` - The legacy JSON metadata for an image layer. In this version of the image specification, layers don't have JSON metadata, but in [version 1](v1.md), they did. A file is created for each layer in the - v1 format for backward compatiblity. + v1 format for backward compatibility. * `layer.tar` - The Tar archive of the filesystem changeset for an image layer. diff --git a/integration-cli/check_test.go b/integration-cli/check_test.go index 4bdd9512e7..06f599407d 100644 --- a/integration-cli/check_test.go +++ b/integration-cli/check_test.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path/filepath" + "sync" "testing" "github.com/docker/docker/cliconfig" @@ -80,7 +81,7 @@ type DockerSchema1RegistrySuite struct { } func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) { - testRequires(c, DaemonIsLinux, RegistryHosting) + testRequires(c, DaemonIsLinux, RegistryHosting, NotArm64) s.reg = setupRegistry(c, true, "", "") s.d = NewDaemon(c) } @@ -194,9 +195,10 @@ func init() { } type DockerSwarmSuite struct { - ds *DockerSuite - daemons []*SwarmDaemon - portIndex int + ds *DockerSuite + daemons []*SwarmDaemon + daemonsLock sync.Mutex // protect access to daemons + portIndex int } func (s *DockerSwarmSuite) SetUpTest(c *check.C) { @@ -227,19 +229,23 @@ func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *Swarm } s.portIndex++ + s.daemonsLock.Lock() s.daemons = append(s.daemons, d) + s.daemonsLock.Unlock() return d } func (s *DockerSwarmSuite) TearDownTest(c *check.C) { testRequires(c, DaemonIsLinux) + s.daemonsLock.Lock() for _, d := range s.daemons { d.Stop() } s.daemons = nil - s.portIndex = 0 + s.daemonsLock.Unlock() + s.portIndex = 0 s.ds.TearDownTest(c) } diff --git a/integration-cli/daemon_swarm.go b/integration-cli/daemon_swarm.go index 47ca4422e8..1fca8aeacf 100644 --- a/integration-cli/daemon_swarm.go +++ b/integration-cli/daemon_swarm.go @@ -9,6 +9,7 @@ import ( "github.com/docker/docker/pkg/integration/checker" "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/filters" "github.com/docker/engine-api/types/swarm" "github.com/go-check/check" ) @@ -131,6 +132,32 @@ func (d *SwarmDaemon) getService(c *check.C, id string) *swarm.Service { return &service } +func (d *SwarmDaemon) getServiceTasks(c *check.C, service string) []swarm.Task { + var tasks []swarm.Task + + filterArgs := filters.NewArgs() + filterArgs.Add("desired-state", "running") + filterArgs.Add("service", service) + filters, err := filters.ToParam(filterArgs) + c.Assert(err, checker.IsNil) + + status, out, err := d.SockRequest("GET", "/tasks?filters="+filters, nil) + c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) + c.Assert(err, checker.IsNil, check.Commentf(string(out))) + c.Assert(json.Unmarshal(out, &tasks), checker.IsNil) + return tasks +} + +func (d *SwarmDaemon) getTask(c *check.C, id string) swarm.Task { + var task swarm.Task + + status, out, err := d.SockRequest("GET", "/tasks/"+id, nil) + c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) + c.Assert(err, checker.IsNil, check.Commentf(string(out))) + c.Assert(json.Unmarshal(out, &task), checker.IsNil) + return task +} + func (d *SwarmDaemon) updateService(c *check.C, service *swarm.Service, f ...serviceConstructor) { for _, fn := range f { fn(service) @@ -185,6 +212,16 @@ func (d *SwarmDaemon) listNodes(c *check.C) []swarm.Node { return nodes } +func (d *SwarmDaemon) listServices(c *check.C) []swarm.Service { + status, out, err := d.SockRequest("GET", "/services", nil) + c.Assert(err, checker.IsNil) + c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) + + services := []swarm.Service{} + c.Assert(json.Unmarshal(out, &services), checker.IsNil) + return services +} + func (d *SwarmDaemon) updateSwarm(c *check.C, f ...specConstructor) { var sw swarm.Swarm status, out, err := d.SockRequest("GET", "/swarm", nil) @@ -200,3 +237,16 @@ func (d *SwarmDaemon) updateSwarm(c *check.C, f ...specConstructor) { c.Assert(err, checker.IsNil) c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) } + +func (d *SwarmDaemon) checkLocalNodeState(c *check.C) (interface{}, check.CommentInterface) { + info, err := d.info() + c.Assert(err, checker.IsNil) + return info.LocalNodeState, nil +} + +func (d *SwarmDaemon) checkControlAvailable(c *check.C) (interface{}, check.CommentInterface) { + info, err := d.info() + c.Assert(err, checker.IsNil) + c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) + return info.ControlAvailable, nil +} diff --git a/integration-cli/daemon_swarm_hack.go b/integration-cli/daemon_swarm_hack.go new file mode 100644 index 0000000000..d516ec4012 --- /dev/null +++ b/integration-cli/daemon_swarm_hack.go @@ -0,0 +1,20 @@ +package main + +import "github.com/go-check/check" + +func (s *DockerSwarmSuite) getDaemon(c *check.C, nodeID string) *SwarmDaemon { + s.daemonsLock.Lock() + defer s.daemonsLock.Unlock() + for _, d := range s.daemons { + if d.NodeID == nodeID { + return d + } + } + c.Fatalf("could not find node with id: %s", nodeID) + return nil +} + +// nodeCmd executes a command on a given node via the normal docker socket +func (s *DockerSwarmSuite) nodeCmd(c *check.C, id, cmd string, args ...string) (string, error) { + return s.getDaemon(c, id).Cmd(cmd, args...) +} diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index 1e2c4a891c..f54168d953 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -1432,7 +1432,7 @@ func (s *DockerSuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c *che } } -// test case for #22210 where an emtpy container name caused panic. +// test case for #22210 where an empty container name caused panic. func (s *DockerSuite) TestContainerApiDeleteWithEmptyName(c *check.C) { status, out, err := sockRequest("DELETE", "/containers/", nil) c.Assert(err, checker.IsNil) diff --git a/integration-cli/docker_api_info_test.go b/integration-cli/docker_api_info_test.go index f80b8a198c..2ff69c0596 100644 --- a/integration-cli/docker_api_info_test.go +++ b/integration-cli/docker_api_info_test.go @@ -22,7 +22,6 @@ func (s *DockerSuite) TestInfoApi(c *check.C) { "ContainersPaused", "ContainersStopped", "Images", - "ExecutionDriver", "LoggingDriver", "OperatingSystem", "NCPU", diff --git a/integration-cli/docker_api_swarm_test.go b/integration-cli/docker_api_swarm_test.go index 7b8d0431ff..aa305b6eca 100644 --- a/integration-cli/docker_api_swarm_test.go +++ b/integration-cli/docker_api_swarm_test.go @@ -3,9 +3,13 @@ package main import ( + "fmt" "net/http" + "os" + "path/filepath" "strconv" "strings" + "sync" "syscall" "time" @@ -17,17 +21,18 @@ import ( var defaultReconciliationTimeout = 30 * time.Second func (s *DockerSwarmSuite) TestApiSwarmInit(c *check.C) { + testRequires(c, Network) // todo: should find a better way to verify that components are running than /info d1 := s.AddDaemon(c, true, true) info, err := d1.info() c.Assert(err, checker.IsNil) - c.Assert(info.ControlAvailable, checker.Equals, true) + c.Assert(info.ControlAvailable, checker.True) c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) d2 := s.AddDaemon(c, true, false) info, err = d2.info() c.Assert(err, checker.IsNil) - c.Assert(info.ControlAvailable, checker.Equals, false) + c.Assert(info.ControlAvailable, checker.False) c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) // Leaving cluster @@ -35,14 +40,14 @@ func (s *DockerSwarmSuite) TestApiSwarmInit(c *check.C) { info, err = d2.info() c.Assert(err, checker.IsNil) - c.Assert(info.ControlAvailable, checker.Equals, false) + c.Assert(info.ControlAvailable, checker.False) c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) c.Assert(d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.listenAddr}}), checker.IsNil) info, err = d2.info() c.Assert(err, checker.IsNil) - c.Assert(info.ControlAvailable, checker.Equals, false) + c.Assert(info.ControlAvailable, checker.False) c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) // Current state restoring after restarts @@ -58,19 +63,21 @@ func (s *DockerSwarmSuite) TestApiSwarmInit(c *check.C) { info, err = d1.info() c.Assert(err, checker.IsNil) - c.Assert(info.ControlAvailable, checker.Equals, true) + c.Assert(info.ControlAvailable, checker.True) c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) info, err = d2.info() c.Assert(err, checker.IsNil) - c.Assert(info.ControlAvailable, checker.Equals, false) + c.Assert(info.ControlAvailable, checker.False) c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) } func (s *DockerSwarmSuite) TestApiSwarmManualAcceptance(c *check.C) { + testRequires(c, Network) s.testAPISwarmManualAcceptance(c, "") } func (s *DockerSwarmSuite) TestApiSwarmManualAcceptanceSecret(c *check.C) { + testRequires(c, Network) s.testAPISwarmManualAcceptance(c, "foobaz") } @@ -114,20 +121,11 @@ func (s *DockerSwarmSuite) testAPISwarmManualAcceptance(c *check.C, secret strin d1.updateNode(c, info.NodeID, func(n *swarm.Node) { n.Spec.Membership = swarm.NodeMembershipAccepted }) - for i := 0; ; i++ { - info, err := d3.info() - c.Assert(err, checker.IsNil) - if info.LocalNodeState == swarm.LocalNodeStateActive { - break - } - if i > 100 { - c.Fatalf("node did not become active") - } - time.Sleep(200 * time.Millisecond) - } + waitAndAssert(c, defaultReconciliationTimeout, d3.checkLocalNodeState, checker.Equals, swarm.LocalNodeStateActive) } func (s *DockerSwarmSuite) TestApiSwarmSecretAcceptance(c *check.C) { + testRequires(c, Network) d1 := s.AddDaemon(c, false, false) secret := "foobar" c.Assert(d1.Init(swarm.InitRequest{ @@ -235,6 +233,7 @@ func (s *DockerSwarmSuite) TestApiSwarmSecretAcceptance(c *check.C) { } func (s *DockerSwarmSuite) TestApiSwarmCAHash(c *check.C) { + testRequires(c, Network) d1 := s.AddDaemon(c, true, true) d2 := s.AddDaemon(c, false, false) err := d2.Join(swarm.JoinRequest{CACertHash: "foobar", RemoteAddrs: []string{d1.listenAddr}}) @@ -246,6 +245,7 @@ func (s *DockerSwarmSuite) TestApiSwarmCAHash(c *check.C) { } func (s *DockerSwarmSuite) TestApiSwarmPromoteDemote(c *check.C) { + testRequires(c, Network) d1 := s.AddDaemon(c, false, false) c.Assert(d1.Init(swarm.InitRequest{ Spec: swarm.Spec{ @@ -261,51 +261,53 @@ func (s *DockerSwarmSuite) TestApiSwarmPromoteDemote(c *check.C) { info, err := d2.info() c.Assert(err, checker.IsNil) - c.Assert(info.ControlAvailable, checker.Equals, false) + c.Assert(info.ControlAvailable, checker.False) c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) d1.updateNode(c, d2.NodeID, func(n *swarm.Node) { n.Spec.Role = swarm.NodeRoleManager }) - for i := 0; ; i++ { - info, err := d2.info() - c.Assert(err, checker.IsNil) - c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) - if info.ControlAvailable { - break - } - if i > 100 { - c.Errorf("node did not turn into manager") - } else { - break - } - time.Sleep(100 * time.Millisecond) - } + waitAndAssert(c, defaultReconciliationTimeout, d2.checkControlAvailable, checker.True) d1.updateNode(c, d2.NodeID, func(n *swarm.Node) { n.Spec.Role = swarm.NodeRoleWorker }) - for i := 0; ; i++ { - info, err := d2.info() - c.Assert(err, checker.IsNil) - c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) - if !info.ControlAvailable { - break - } - if i > 100 { - c.Errorf("node did not turn into worker") - } else { - break - } - time.Sleep(100 * time.Millisecond) - } + waitAndAssert(c, defaultReconciliationTimeout, d2.checkControlAvailable, checker.False) - // todo: test raft qourum stability + // Demoting last node should fail + node := d1.getNode(c, d1.NodeID) + node.Spec.Role = swarm.NodeRoleWorker + url := fmt.Sprintf("/nodes/%s/update?version=%d", node.ID, node.Version.Index) + status, out, err := d1.SockRequest("POST", url, node.Spec) + c.Assert(err, checker.IsNil) + c.Assert(status, checker.Equals, http.StatusInternalServerError, check.Commentf("output: %q", string(out))) + c.Assert(string(out), checker.Contains, "last manager of the swarm") + info, err = d1.info() + c.Assert(err, checker.IsNil) + c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) + c.Assert(info.ControlAvailable, checker.True) + + // Promote already demoted node + d1.updateNode(c, d2.NodeID, func(n *swarm.Node) { + n.Spec.Role = swarm.NodeRoleManager + }) + + waitAndAssert(c, defaultReconciliationTimeout, d2.checkControlAvailable, checker.True) +} + +func (s *DockerSwarmSuite) TestApiSwarmServicesEmptyList(c *check.C) { + testRequires(c, Network) + d := s.AddDaemon(c, true, true) + + services := d.listServices(c) + c.Assert(services, checker.NotNil) + c.Assert(len(services), checker.Equals, 0, check.Commentf("services: %#v", services)) } func (s *DockerSwarmSuite) TestApiSwarmServicesCreate(c *check.C) { + testRequires(c, Network) d := s.AddDaemon(c, true, true) instances := 2 @@ -322,6 +324,7 @@ func (s *DockerSwarmSuite) TestApiSwarmServicesCreate(c *check.C) { } func (s *DockerSwarmSuite) TestApiSwarmServicesMultipleAgents(c *check.C) { + testRequires(c, Network) d1 := s.AddDaemon(c, true, true) d2 := s.AddDaemon(c, true, false) d3 := s.AddDaemon(c, true, false) @@ -350,6 +353,7 @@ func (s *DockerSwarmSuite) TestApiSwarmServicesMultipleAgents(c *check.C) { } func (s *DockerSwarmSuite) TestApiSwarmServicesCreateGlobal(c *check.C) { + testRequires(c, Network) d1 := s.AddDaemon(c, true, true) d2 := s.AddDaemon(c, true, false) d3 := s.AddDaemon(c, true, false) @@ -368,6 +372,7 @@ func (s *DockerSwarmSuite) TestApiSwarmServicesCreateGlobal(c *check.C) { } func (s *DockerSwarmSuite) TestApiSwarmServicesStateReporting(c *check.C) { + testRequires(c, Network) testRequires(c, SameHostDaemon) testRequires(c, DaemonIsLinux) @@ -442,6 +447,7 @@ func (s *DockerSwarmSuite) TestApiSwarmServicesStateReporting(c *check.C) { } func (s *DockerSwarmSuite) TestApiSwarmRaftQuorum(c *check.C) { + testRequires(c, Network) d1 := s.AddDaemon(c, true, true) d2 := s.AddDaemon(c, true, true) d3 := s.AddDaemon(c, true, true) @@ -471,6 +477,7 @@ func (s *DockerSwarmSuite) TestApiSwarmRaftQuorum(c *check.C) { } func (s *DockerSwarmSuite) TestApiSwarmListNodes(c *check.C) { + testRequires(c, Network) d1 := s.AddDaemon(c, true, true) d2 := s.AddDaemon(c, true, false) d3 := s.AddDaemon(c, true, false) @@ -490,6 +497,7 @@ loop0: } func (s *DockerSwarmSuite) TestApiSwarmNodeUpdate(c *check.C) { + testRequires(c, Network) d := s.AddDaemon(c, true, true) nodes := d.listNodes(c) @@ -503,6 +511,7 @@ func (s *DockerSwarmSuite) TestApiSwarmNodeUpdate(c *check.C) { } func (s *DockerSwarmSuite) TestApiSwarmNodeDrainPause(c *check.C) { + testRequires(c, Network) d1 := s.AddDaemon(c, true, true) d2 := s.AddDaemon(c, true, false) @@ -557,6 +566,7 @@ func (s *DockerSwarmSuite) TestApiSwarmNodeDrainPause(c *check.C) { } func (s *DockerSwarmSuite) TestApiSwarmLeaveRemovesContainer(c *check.C) { + testRequires(c, Network) d := s.AddDaemon(c, true, true) instances := 2 @@ -591,17 +601,7 @@ func (s *DockerSwarmSuite) TestApiSwarmLeaveOnPendingJoin(c *check.C) { RemoteAddrs: []string{"nosuchhost:1234"}, }) // will block on pending state - for i := 0; ; i++ { - info, err := d2.info() - c.Assert(err, checker.IsNil) - if info.LocalNodeState == swarm.LocalNodeStatePending { - break - } - if i > 100 { - c.Fatalf("node did not go to pending state: %v", info.LocalNodeState) - } - time.Sleep(100 * time.Millisecond) - } + waitAndAssert(c, defaultReconciliationTimeout, d2.checkLocalNodeState, checker.Equals, swarm.LocalNodeStatePending) c.Assert(d2.Leave(true), checker.IsNil) @@ -619,17 +619,7 @@ func (s *DockerSwarmSuite) TestApiSwarmRestoreOnPendingJoin(c *check.C) { RemoteAddrs: []string{"nosuchhost:1234"}, }) // will block on pending state - for i := 0; ; i++ { - info, err := d.info() - c.Assert(err, checker.IsNil) - if info.LocalNodeState == swarm.LocalNodeStatePending { - break - } - if i > 100 { - c.Fatalf("node did not go to pending state: %v", info.LocalNodeState) - } - time.Sleep(100 * time.Millisecond) - } + waitAndAssert(c, defaultReconciliationTimeout, d.checkLocalNodeState, checker.Equals, swarm.LocalNodeStatePending) c.Assert(d.Stop(), checker.IsNil) c.Assert(d.Start(), checker.IsNil) @@ -640,6 +630,7 @@ func (s *DockerSwarmSuite) TestApiSwarmRestoreOnPendingJoin(c *check.C) { } func (s *DockerSwarmSuite) TestApiSwarmManagerRestore(c *check.C) { + testRequires(c, Network) d1 := s.AddDaemon(c, true, true) instances := 2 @@ -669,6 +660,7 @@ func (s *DockerSwarmSuite) TestApiSwarmManagerRestore(c *check.C) { } func (s *DockerSwarmSuite) TestApiSwarmScaleNoRollingUpdate(c *check.C) { + testRequires(c, Network) d := s.AddDaemon(c, true, true) instances := 2 @@ -734,7 +726,7 @@ func (s *DockerSwarmSuite) TestApiSwarmForceNewCluster(c *check.C) { d3 := s.AddDaemon(c, true, true) info, err := d3.info() c.Assert(err, checker.IsNil) - c.Assert(info.ControlAvailable, checker.Equals, true) + c.Assert(info.ControlAvailable, checker.True) c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) instances = 4 @@ -778,3 +770,108 @@ func setGlobalMode(s *swarm.Service) { Global: &swarm.GlobalService{}, } } + +func checkClusterHealth(c *check.C, cl []*SwarmDaemon, managerCount, workerCount int) { + var totalMCount, totalWCount int + for _, d := range cl { + info, err := d.info() + c.Assert(err, check.IsNil) + if !info.ControlAvailable { + totalWCount++ + continue + } + var leaderFound bool + totalMCount++ + var mCount, wCount int + for _, n := range d.listNodes(c) { + c.Assert(n.Status.State, checker.Equals, swarm.NodeStateReady, check.Commentf("state of node %s, reported by %s", n.ID, d.Info.NodeID)) + c.Assert(n.Spec.Availability, checker.Equals, swarm.NodeAvailabilityActive, check.Commentf("availability of node %s, reported by %s", n.ID, d.Info.NodeID)) + c.Assert(n.Spec.Membership, checker.Equals, swarm.NodeMembershipAccepted, check.Commentf("membership of node %s, reported by %s", n.ID, d.Info.NodeID)) + if n.Spec.Role == swarm.NodeRoleManager { + c.Assert(n.ManagerStatus, checker.NotNil, check.Commentf("manager status of node %s (manager), reported by %s", n.ID, d.Info.NodeID)) + if n.ManagerStatus.Leader { + leaderFound = true + } + mCount++ + } else { + c.Assert(n.ManagerStatus, checker.IsNil, check.Commentf("manager status of node %s (worker), reported by %s", n.ID, d.Info.NodeID)) + wCount++ + } + } + c.Assert(leaderFound, checker.True, check.Commentf("lack of leader reported by node %s", info.NodeID)) + c.Assert(mCount, checker.Equals, managerCount, check.Commentf("managers count reported by node %s", info.NodeID)) + c.Assert(wCount, checker.Equals, workerCount, check.Commentf("workers count reported by node %s", info.NodeID)) + } + c.Assert(totalMCount, checker.Equals, managerCount) + c.Assert(totalWCount, checker.Equals, workerCount) +} + +func (s *DockerSwarmSuite) TestApiSwarmRestartCluster(c *check.C) { + mCount, wCount := 5, 1 + + var nodes []*SwarmDaemon + for i := 0; i < mCount; i++ { + manager := s.AddDaemon(c, true, true) + info, err := manager.info() + c.Assert(err, checker.IsNil) + c.Assert(info.ControlAvailable, checker.True) + c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) + nodes = append(nodes, manager) + } + + for i := 0; i < wCount; i++ { + worker := s.AddDaemon(c, true, false) + info, err := worker.info() + c.Assert(err, checker.IsNil) + c.Assert(info.ControlAvailable, checker.False) + c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) + nodes = append(nodes, worker) + } + + // stop whole cluster + { + var wg sync.WaitGroup + wg.Add(len(nodes)) + errs := make(chan error, len(nodes)) + + for _, d := range nodes { + go func(daemon *SwarmDaemon) { + defer wg.Done() + if err := daemon.Stop(); err != nil { + errs <- err + } + if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" { + daemon.root = filepath.Dir(daemon.root) + } + }(d) + } + wg.Wait() + close(errs) + for err := range errs { + c.Assert(err, check.IsNil) + } + } + + // start whole cluster + { + var wg sync.WaitGroup + wg.Add(len(nodes)) + errs := make(chan error, len(nodes)) + + for _, d := range nodes { + go func(daemon *SwarmDaemon) { + defer wg.Done() + if err := daemon.Start("--iptables=false"); err != nil { + errs <- err + } + }(d) + } + wg.Wait() + close(errs) + for err := range errs { + c.Assert(err, check.IsNil) + } + } + + checkClusterHealth(c, nodes, mCount, wCount) +} diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 2312bdc21e..ff1daf40e5 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -4915,7 +4915,7 @@ func (s *DockerSuite) TestBuildRenamedDockerfile(c *check.C) { } if expected := fmt.Sprintf("The Dockerfile (%s) must be within the build context (.)", nonDockerfileFile); !strings.Contains(out, expected) { - c.Fatalf("wrong error messsage:%v\nexpected to contain=%v", out, expected) + c.Fatalf("wrong error message:%v\nexpected to contain=%v", out, expected) } out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test6", "..") diff --git a/integration-cli/docker_cli_by_digest_test.go b/integration-cli/docker_cli_by_digest_test.go index b89c76cce3..b62b24e220 100644 --- a/integration-cli/docker_cli_by_digest_test.go +++ b/integration-cli/docker_cli_by_digest_test.go @@ -314,6 +314,79 @@ func (s *DockerRegistrySuite) TestListImagesWithDigests(c *check.C) { c.Assert(busyboxRe.MatchString(out), checker.True, check.Commentf("expected %q: %s", busyboxRe.String(), out)) } +func (s *DockerRegistrySuite) TestListDanglingImagesWithDigests(c *check.C) { + // setup image1 + digest1, err := setupImageWithTag(c, "dangle1") + c.Assert(err, checker.IsNil, check.Commentf("error setting up image")) + imageReference1 := fmt.Sprintf("%s@%s", repoName, digest1) + c.Logf("imageReference1 = %s", imageReference1) + + // pull image1 by digest + dockerCmd(c, "pull", imageReference1) + + // list images + out, _ := dockerCmd(c, "images", "--digests") + + // make sure repo shown, tag=, digest = $digest1 + re1 := regexp.MustCompile(`\s*` + repoName + `\s*\s*` + digest1.String() + `\s`) + c.Assert(re1.MatchString(out), checker.True, check.Commentf("expected %q: %s", re1.String(), out)) + // setup image2 + digest2, err := setupImageWithTag(c, "dangle2") + //error setting up image + c.Assert(err, checker.IsNil) + imageReference2 := fmt.Sprintf("%s@%s", repoName, digest2) + c.Logf("imageReference2 = %s", imageReference2) + + // pull image1 by digest + dockerCmd(c, "pull", imageReference1) + + // pull image2 by digest + dockerCmd(c, "pull", imageReference2) + + // list images + out, _ = dockerCmd(c, "images", "--digests", "--filter=\"dangling=true\"") + + // make sure repo shown, tag=, digest = $digest1 + c.Assert(re1.MatchString(out), checker.True, check.Commentf("expected %q: %s", re1.String(), out)) + + // make sure repo shown, tag=, digest = $digest2 + re2 := regexp.MustCompile(`\s*` + repoName + `\s*\s*` + digest2.String() + `\s`) + c.Assert(re2.MatchString(out), checker.True, check.Commentf("expected %q: %s", re2.String(), out)) + + // pull dangle1 tag + dockerCmd(c, "pull", repoName+":dangle1") + + // list images + out, _ = dockerCmd(c, "images", "--digests", "--filter=\"dangling=true\"") + + // make sure image 1 has repo, tag, AND repo, , digest + reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*dangle1\s*` + digest1.String() + `\s`) + c.Assert(reWithDigest1.MatchString(out), checker.False, check.Commentf("unexpected %q: %s", reWithDigest1.String(), out)) + // make sure image 2 has repo, , digest + c.Assert(re2.MatchString(out), checker.True, check.Commentf("expected %q: %s", re2.String(), out)) + + // pull dangle2 tag + dockerCmd(c, "pull", repoName+":dangle2") + + // list images, show tagged images + out, _ = dockerCmd(c, "images", "--digests") + + // make sure image 1 has repo, tag, digest + c.Assert(reWithDigest1.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithDigest1.String(), out)) + + // make sure image 2 has repo, tag, digest + reWithDigest2 := regexp.MustCompile(`\s*` + repoName + `\s*dangle2\s*` + digest2.String() + `\s`) + c.Assert(reWithDigest2.MatchString(out), checker.True, check.Commentf("expected %q: %s", reWithDigest2.String(), out)) + + // list images, no longer dangling, should not match + out, _ = dockerCmd(c, "images", "--digests", "--filter=\"dangling=true\"") + + // make sure image 1 has repo, tag, digest + c.Assert(reWithDigest1.MatchString(out), checker.False, check.Commentf("unexpected %q: %s", reWithDigest1.String(), out)) + // make sure image 2 has repo, tag, digest + c.Assert(reWithDigest2.MatchString(out), checker.False, check.Commentf("unexpected %q: %s", reWithDigest2.String(), out)) +} + func (s *DockerRegistrySuite) TestInspectImageWithDigests(c *check.C) { digest, err := setupImage(c) c.Assert(err, check.IsNil, check.Commentf("error setting up image")) diff --git a/integration-cli/docker_cli_daemon_experimental_test.go b/integration-cli/docker_cli_daemon_experimental_test.go index 7230dbb67d..74b20e9580 100644 --- a/integration-cli/docker_cli_daemon_experimental_test.go +++ b/integration-cli/docker_cli_daemon_experimental_test.go @@ -5,6 +5,9 @@ package main import ( "github.com/docker/docker/pkg/integration/checker" "github.com/go-check/check" + "os" + "os/exec" + "time" ) var pluginName = "tiborvass/no-remove" @@ -67,3 +70,66 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithPluginDisabled(c *check.C) { c.Assert(out, checker.Contains, pluginName) c.Assert(out, checker.Contains, "false") } + +// TestDaemonShutdownLiveRestoreWithPlugins leaves plugin running. +func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C) { + if err := s.d.Start("--live-restore"); err != nil { + c.Fatalf("Could not start daemon: %v", err) + } + if out, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", pluginName); err != nil { + c.Fatalf("Could not install plugin: %v %s", err, out) + } + defer func() { + if err := s.d.Restart("--live-restore"); err != nil { + c.Fatalf("Could not restart daemon: %v", err) + } + if out, err := s.d.Cmd("plugin", "disable", pluginName); err != nil { + c.Fatalf("Could not disable plugin: %v %s", err, out) + } + if out, err := s.d.Cmd("plugin", "remove", pluginName); err != nil { + c.Fatalf("Could not remove plugin: %v %s", err, out) + } + }() + + if err := s.d.Kill(); err != nil { + c.Fatalf("Could not kill daemon: %v", err) + } + + cmd := exec.Command("pgrep", "-f", "plugin-no-remove") + if out, ec, err := runCommandWithOutput(cmd); ec != 0 { + c.Fatalf("Expected exit code '0', got %d err: %v output: %s ", ec, err, out) + } +} + +// TestDaemonShutdownWithPlugins shuts down running plugins. +func (s *DockerDaemonSuite) TestDaemonShutdownWithPlugins(c *check.C) { + if err := s.d.Start(); err != nil { + c.Fatalf("Could not start daemon: %v", err) + } + if out, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", pluginName); err != nil { + c.Fatalf("Could not install plugin: %v %s", err, out) + } + + defer func() { + if err := s.d.Restart(); err != nil { + c.Fatalf("Could not restart daemon: %v", err) + } + if out, err := s.d.Cmd("plugin", "disable", pluginName); err != nil { + c.Fatalf("Could not disable plugin: %v %s", err, out) + } + if out, err := s.d.Cmd("plugin", "remove", pluginName); err != nil { + c.Fatalf("Could not remove plugin: %v %s", err, out) + } + }() + + if err := s.d.cmd.Process.Signal(os.Interrupt); err != nil { + c.Fatalf("Could not kill daemon: %v", err) + } + + time.Sleep(5 * time.Second) + + cmd := exec.Command("pgrep", "-f", "plugin-no-remove") + if out, ec, err := runCommandWithOutput(cmd); ec != 1 { + c.Fatalf("Expected exit code '1', got %d err: %v output: %s ", ec, err, out) + } +} diff --git a/integration-cli/docker_cli_external_graphdriver_unix_test.go b/integration-cli/docker_cli_external_graphdriver_unix_test.go index 2e1f04a8a5..771996bb11 100644 --- a/integration-cli/docker_cli_external_graphdriver_unix_test.go +++ b/integration-cli/docker_cli_external_graphdriver_unix_test.go @@ -359,7 +359,7 @@ func (s *DockerExternalGraphdriverSuite) testExternalGraphDriver(name string, ex out, err = s.d.Cmd("diff", "graphtest") c.Assert(err, check.IsNil, check.Commentf(out)) - c.Assert(strings.Contains(out, "A /hello"), check.Equals, true, check.Commentf("diff ouput: %s", out)) + c.Assert(strings.Contains(out, "A /hello"), check.Equals, true, check.Commentf("diff output: %s", out)) out, err = s.d.Cmd("rm", "-f", "graphtest") c.Assert(err, check.IsNil, check.Commentf(out)) diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go index 25f08f3cb8..0611b2c089 100644 --- a/integration-cli/docker_cli_network_unix_test.go +++ b/integration-cli/docker_cli_network_unix_test.go @@ -1660,3 +1660,15 @@ func (s *DockerDaemonSuite) TestDaemonRestartRestoreBridgeNetwork(t *check.C) { t.Fatal(err) } } + +func (s *DockerNetworkSuite) TestDockerNetworkFlagAlias(c *check.C) { + dockerCmd(c, "network", "create", "user") + output, status := dockerCmd(c, "run", "--rm", "--network=user", "--network-alias=foo", "busybox", "true") + c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output)) + + output, status, _ = dockerCmdWithError("run", "--rm", "--net=user", "--network=user", "busybox", "true") + c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output)) + + output, status, _ = dockerCmdWithError("run", "--rm", "--network=user", "--net-alias=foo", "--network-alias=bar", "busybox", "true") + c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output)) +} diff --git a/integration-cli/docker_cli_plugins_test.go b/integration-cli/docker_cli_plugins_test.go index 4846744d62..252df5acef 100644 --- a/integration-cli/docker_cli_plugins_test.go +++ b/integration-cli/docker_cli_plugins_test.go @@ -52,3 +52,10 @@ func (s *DockerSuite) TestPluginInstallDisable(c *check.C) { c.Assert(err, checker.IsNil) c.Assert(out, checker.Contains, nameWithTag) } + +func (s *DockerSuite) TestPluginInstallImage(c *check.C) { + testRequires(c, DaemonIsLinux, ExperimentalDaemon) + out, _, err := dockerCmdWithError("plugin", "install", "redis") + c.Assert(err, checker.NotNil) + c.Assert(out, checker.Contains, "content is not a plugin") +} diff --git a/integration-cli/docker_cli_push_test.go b/integration-cli/docker_cli_push_test.go index dd3a0572a1..f9d53449fb 100644 --- a/integration-cli/docker_cli_push_test.go +++ b/integration-cli/docker_cli_push_test.go @@ -231,11 +231,19 @@ func (s *DockerRegistrySuite) TestCrossRepositoryLayerPush(c *check.C) { c.Assert(len(digest2), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest")) c.Assert(digest1, check.Equals, digest2) + // ensure that pushing again produces the same digest + out3, _, err := dockerCmdWithError("push", destRepoName) + c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out2)) + + digest3 := reference.DigestRegexp.FindString(out3) + c.Assert(len(digest2), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest")) + c.Assert(digest3, check.Equals, digest2) + // ensure that we can pull and run the cross-repo-pushed repository dockerCmd(c, "rmi", destRepoName) dockerCmd(c, "pull", destRepoName) - out3, _ := dockerCmd(c, "run", destRepoName, "echo", "-n", "hello world") - c.Assert(out3, check.Equals, "hello world") + out4, _ := dockerCmd(c, "run", destRepoName, "echo", "-n", "hello world") + c.Assert(out4, check.Equals, "hello world") } func (s *DockerSchema1RegistrySuite) TestCrossRepositoryLayerPushNotSupported(c *check.C) { @@ -287,7 +295,7 @@ func (s *DockerTrustSuite) TestTrustedPush(c *check.C) { s.trustedCmd(pullCmd) out, _, err = runCommandWithOutput(pullCmd) c.Assert(err, check.IsNil, check.Commentf(out)) - c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) + c.Assert(string(out), checker.Contains, "Status: Image is up to date", check.Commentf(out)) // Assert that we rotated the snapshot key to the server by checking our local keystore contents, err := ioutil.ReadDir(filepath.Join(cliconfig.ConfigDir(), "trust/private/tuf_keys", privateRegistryURL, "dockerclitrusted/pushtest")) @@ -312,7 +320,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithEnvPasswords(c *check.C) { s.trustedCmd(pullCmd) out, _, err = runCommandWithOutput(pullCmd) c.Assert(err, check.IsNil, check.Commentf(out)) - c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) + c.Assert(string(out), checker.Contains, "Status: Image is up to date", check.Commentf(out)) } func (s *DockerTrustSuite) TestTrustedPushWithFailingServer(c *check.C) { @@ -358,7 +366,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) { s.trustedCmd(pullCmd) out, _, err = runCommandWithOutput(pullCmd) c.Assert(err, check.IsNil, check.Commentf(out)) - c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) + c.Assert(string(out), checker.Contains, "Status: Image is up to date", check.Commentf(out)) } func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) { @@ -492,7 +500,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C) s.trustedCmd(pullCmd) out, _, err = runCommandWithOutput(pullCmd) c.Assert(err, check.IsNil, check.Commentf(out)) - c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) + c.Assert(string(out), checker.Contains, "Status: Image is up to date", check.Commentf(out)) } func (s *DockerTrustSuite) TestTrustedPushSignsAllFirstLevelRolesWeHaveKeysFor(c *check.C) { diff --git a/integration-cli/docker_cli_run_unix_test.go b/integration-cli/docker_cli_run_unix_test.go index 164a51549c..c1995b7ce1 100644 --- a/integration-cli/docker_cli_run_unix_test.go +++ b/integration-cli/docker_cli_run_unix_test.go @@ -955,6 +955,14 @@ func (s *DockerSuite) TestRunSeccompProfileDenyChmod(c *check.C) { { "name": "chmod", "action": "SCMP_ACT_ERRNO" + }, + { + "name":"fchmod", + "action": "SCMP_ACT_ERRNO" + }, + { + "name": "fchmodat", + "action":"SCMP_ACT_ERRNO" } ] }` diff --git a/integration-cli/docker_cli_service_create_hack_test.go b/integration-cli/docker_cli_service_create_hack_test.go new file mode 100644 index 0000000000..4814ddee59 --- /dev/null +++ b/integration-cli/docker_cli_service_create_hack_test.go @@ -0,0 +1,45 @@ +// +build !windows + +package main + +import ( + "encoding/json" + "strings" + + "github.com/docker/docker/pkg/integration/checker" + "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/swarm" + "github.com/go-check/check" +) + +func (s *DockerSwarmSuite) TestServiceCreateMountVolume(c *check.C) { + d := s.AddDaemon(c, true, true) + out, err := d.Cmd("service", "create", "--mount", "type=volume,source=foo,target=/foo", "busybox", "top") + c.Assert(err, checker.IsNil, check.Commentf(out)) + id := strings.TrimSpace(out) + + var tasks []swarm.Task + waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { + tasks = d.getServiceTasks(c, id) + return len(tasks) > 0, nil + }, checker.Equals, true) + + task := tasks[0] + waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) { + if task.NodeID == "" || task.Status.ContainerStatus.ContainerID == "" { + task = d.getTask(c, task.ID) + } + return task.NodeID != "" && task.Status.ContainerStatus.ContainerID != "", nil + }, checker.Equals, true) + + out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .Mounts}}", task.Status.ContainerStatus.ContainerID) + c.Assert(err, checker.IsNil, check.Commentf(out)) + + var mounts []types.MountPoint + c.Assert(json.Unmarshal([]byte(out), &mounts), checker.IsNil) + c.Assert(mounts, checker.HasLen, 1) + + c.Assert(mounts[0].Name, checker.Equals, "foo") + c.Assert(mounts[0].Destination, checker.Equals, "/foo") + c.Assert(mounts[0].RW, checker.Equals, true) +} diff --git a/integration-cli/docker_cli_stack_test.go b/integration-cli/docker_cli_stack_test.go new file mode 100644 index 0000000000..cbfa588a14 --- /dev/null +++ b/integration-cli/docker_cli_stack_test.go @@ -0,0 +1,28 @@ +// +build experimental + +package main + +import ( + "github.com/docker/docker/pkg/integration/checker" + "github.com/go-check/check" +) + +func (s *DockerSwarmSuite) TestStackRemove(c *check.C) { + d := s.AddDaemon(c, true, true) + + stackArgs := append([]string{"remove", "UNKNOWN_STACK"}) + + out, err := d.Cmd("stack", stackArgs...) + c.Assert(err, checker.IsNil) + c.Assert(out, check.Equals, "Nothing found in stack: UNKNOWN_STACK\n") +} + +func (s *DockerSwarmSuite) TestStackTasks(c *check.C) { + d := s.AddDaemon(c, true, true) + + stackArgs := append([]string{"tasks", "UNKNOWN_STACK"}) + + out, err := d.Cmd("stack", stackArgs...) + c.Assert(err, checker.IsNil) + c.Assert(out, check.Equals, "Nothing found in stack: UNKNOWN_STACK\n") +} diff --git a/integration-cli/docker_cli_swarm_test.go b/integration-cli/docker_cli_swarm_test.go index 83b09d43fc..dffa2f4834 100644 --- a/integration-cli/docker_cli_swarm_test.go +++ b/integration-cli/docker_cli_swarm_test.go @@ -106,7 +106,7 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) { c.Assert(d.Leave(true), checker.IsNil) - out, err = d.Cmd("swarm", "init", "--auto-accept", "none") + out, err = d.Cmd("swarm", "init", "--auto-accept", "none", "--secret", "") c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) spec = getSpec() diff --git a/integration-cli/docker_utils.go b/integration-cli/docker_utils.go index 73a7a85efa..1141cae2c1 100644 --- a/integration-cli/docker_utils.go +++ b/integration-cli/docker_utils.go @@ -1260,7 +1260,7 @@ func daemonTime(c *check.C) time.Time { return dt } -// daemonUnixTime returns the current time on the daemon host with nanoseconds precission. +// daemonUnixTime returns the current time on the daemon host with nanoseconds precision. // It return the time formatted how the client sends timestamps to the server. func daemonUnixTime(c *check.C) string { return parseEventTime(daemonTime(c)) diff --git a/integration-cli/requirements.go b/integration-cli/requirements.go index 56a1596c2d..359359dab5 100644 --- a/integration-cli/requirements.go +++ b/integration-cli/requirements.go @@ -42,6 +42,10 @@ var ( func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "arm" }, "Test requires a daemon not running on ARM", } + NotArm64 = testRequirement{ + func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "arm64" }, + "Test requires a daemon not running on arm64", + } NotPpc64le = testRequirement{ func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "ppc64le" }, "Test requires a daemon not running on ppc64le", diff --git a/libcontainerd/client_windows.go b/libcontainerd/client_windows.go index 78b3b992f1..6df959b6d8 100644 --- a/libcontainerd/client_windows.go +++ b/libcontainerd/client_windows.go @@ -81,6 +81,7 @@ func (clnt *client) Create(containerID string, spec Spec, options ...CreateOptio } if spec.Windows.HvRuntime != nil { + configuration.VolumePath = "" // Always empty for Hyper-V containers configuration.HvPartition = true configuration.HvRuntime = &hcsshim.HvRuntime{ ImagePath: spec.Windows.HvRuntime.ImagePath, diff --git a/man/Dockerfile.5.md b/man/Dockerfile.5.md index 7d56bda0fa..df69935397 100644 --- a/man/Dockerfile.5.md +++ b/man/Dockerfile.5.md @@ -376,8 +376,9 @@ A Dockerfile is similar to a Makefile. defined and the `what_user` value was passed on the command line. Prior to its definition by an `ARG` instruction, any use of a variable results in an empty string. - > **Note:** It is not recommended to use build-time variables for - > passing secrets like github keys, user credentials etc. + > **Warning:** It is not recommended to use build-time variables for + > passing secrets like github keys, user credentials etc. Build-time variable + > values are visible to any user of the image with the `docker history` command. You can use an `ARG` or an `ENV` instruction to specify variables that are available to the `RUN` instruction. Environment variables defined using the diff --git a/man/docker-create.1.md b/man/docker-create.1.md index be0e5e9d29..e9b1ebe31a 100644 --- a/man/docker-create.1.md +++ b/man/docker-create.1.md @@ -52,8 +52,8 @@ docker-create - Create a new container [**--memory-swap**[=*LIMIT*]] [**--memory-swappiness**[=*MEMORY-SWAPPINESS*]] [**--name**[=*NAME*]] -[**--net**[=*"bridge"*]] -[**--net-alias**[=*[]*]] +[**--network-alias**[=*[]*]] +[**--network**[=*"bridge"*]] [**--oom-kill-disable**] [**--oom-score-adj**[=*0*]] [**-P**|**--publish-all**] @@ -276,7 +276,7 @@ unit, `b` is used. Set LIMIT to `-1` to enable unlimited swap. 'host': use the Docker host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. '|': connect to a user-defined network -**--net-alias**=[] +**--network-alias**=[] Add network-scoped alias for the container **--oom-kill-disable**=*true*|*false* diff --git a/man/docker-run.1.md b/man/docker-run.1.md index 6fdc93cd60..d4a2953161 100644 --- a/man/docker-run.1.md +++ b/man/docker-run.1.md @@ -54,8 +54,8 @@ docker-run - Run a command in a new container [**--memory-swap**[=*LIMIT*]] [**--memory-swappiness**[=*MEMORY-SWAPPINESS*]] [**--name**[=*NAME*]] -[**--net**[=*"bridge"*]] -[**--net-alias**[=*[]*]] +[**--network-alias**[=*[]*]] +[**--network**[=*"bridge"*]] [**--oom-kill-disable**] [**--oom-score-adj**[=*0*]] [**-P**|**--publish-all**] @@ -395,7 +395,7 @@ and foreground Docker containers. 'host': use the Docker host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. '|': connect to a user-defined network -**--net-alias**=[] +**--network-alias**=[] Add network-scoped alias for the container **--oom-kill-disable**=*true*|*false* diff --git a/man/dockerd.8.md b/man/dockerd.8.md index 267592ebbe..fc9226d387 100644 --- a/man/dockerd.8.md +++ b/man/dockerd.8.md @@ -6,6 +6,7 @@ dockerd - Enable daemon mode # SYNOPSIS **dockerd** +[**--add-runtime**[=*[]*]] [**--api-cors-header**=[=*API-CORS-HEADER*]] [**--authorization-plugin**[=*[]*]] [**-b**|**--bridge**[=*BRIDGE*]] @@ -75,6 +76,9 @@ format. # OPTIONS +**--add-runtime**=[] + 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. diff --git a/pkg/integration/checker/checker.go b/pkg/integration/checker/checker.go index a5314994cd..d1b703a599 100644 --- a/pkg/integration/checker/checker.go +++ b/pkg/integration/checker/checker.go @@ -1,4 +1,4 @@ -// Package checker provide Docker specific implementations of the go-check.Checker interface. +// Package checker provides Docker specific implementations of the go-check.Checker interface. package checker import ( diff --git a/pkg/proxy/network_proxy_test.go b/pkg/proxy/network_proxy_test.go deleted file mode 100644 index 9a73548019..0000000000 --- a/pkg/proxy/network_proxy_test.go +++ /dev/null @@ -1,216 +0,0 @@ -package proxy - -import ( - "bytes" - "fmt" - "io" - "net" - "strings" - "testing" - "time" -) - -var testBuf = []byte("Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo") -var testBufSize = len(testBuf) - -type EchoServer interface { - Run() - Close() - LocalAddr() net.Addr -} - -type TCPEchoServer struct { - listener net.Listener - testCtx *testing.T -} - -type UDPEchoServer struct { - conn net.PacketConn - testCtx *testing.T -} - -func NewEchoServer(t *testing.T, proto, address string) EchoServer { - var server EchoServer - if strings.HasPrefix(proto, "tcp") { - listener, err := net.Listen(proto, address) - if err != nil { - t.Fatal(err) - } - server = &TCPEchoServer{listener: listener, testCtx: t} - } else { - socket, err := net.ListenPacket(proto, address) - if err != nil { - t.Fatal(err) - } - server = &UDPEchoServer{conn: socket, testCtx: t} - } - return server -} - -func (server *TCPEchoServer) Run() { - go func() { - for { - client, err := server.listener.Accept() - if err != nil { - return - } - go func(client net.Conn) { - if _, err := io.Copy(client, client); err != nil { - server.testCtx.Logf("can't echo to the client: %v\n", err.Error()) - } - client.Close() - }(client) - } - }() -} - -func (server *TCPEchoServer) LocalAddr() net.Addr { return server.listener.Addr() } -func (server *TCPEchoServer) Close() { server.listener.Close() } - -func (server *UDPEchoServer) Run() { - go func() { - readBuf := make([]byte, 1024) - for { - read, from, err := server.conn.ReadFrom(readBuf) - if err != nil { - return - } - for i := 0; i != read; { - written, err := server.conn.WriteTo(readBuf[i:read], from) - if err != nil { - break - } - i += written - } - } - }() -} - -func (server *UDPEchoServer) LocalAddr() net.Addr { return server.conn.LocalAddr() } -func (server *UDPEchoServer) Close() { server.conn.Close() } - -func testProxyAt(t *testing.T, proto string, proxy Proxy, addr string) { - defer proxy.Close() - go proxy.Run() - client, err := net.Dial(proto, addr) - if err != nil { - t.Fatalf("Can't connect to the proxy: %v", err) - } - defer client.Close() - client.SetDeadline(time.Now().Add(10 * time.Second)) - if _, err = client.Write(testBuf); err != nil { - t.Fatal(err) - } - recvBuf := make([]byte, testBufSize) - if _, err = client.Read(recvBuf); err != nil { - t.Fatal(err) - } - if !bytes.Equal(testBuf, recvBuf) { - t.Fatal(fmt.Errorf("Expected [%v] but got [%v]", testBuf, recvBuf)) - } -} - -func testProxy(t *testing.T, proto string, proxy Proxy) { - testProxyAt(t, proto, proxy, proxy.FrontendAddr().String()) -} - -func TestTCP4Proxy(t *testing.T) { - backend := NewEchoServer(t, "tcp", "127.0.0.1:0") - defer backend.Close() - backend.Run() - frontendAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0} - proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) - if err != nil { - t.Fatal(err) - } - testProxy(t, "tcp", proxy) -} - -func TestTCP6Proxy(t *testing.T) { - backend := NewEchoServer(t, "tcp", "[::1]:0") - defer backend.Close() - backend.Run() - frontendAddr := &net.TCPAddr{IP: net.IPv6loopback, Port: 0} - proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) - if err != nil { - t.Fatal(err) - } - testProxy(t, "tcp", proxy) -} - -func TestTCPDualStackProxy(t *testing.T) { - // If I understand `godoc -src net favoriteAddrFamily` (used by the - // net.Listen* functions) correctly this should work, but it doesn't. - t.Skip("No support for dual stack yet") - backend := NewEchoServer(t, "tcp", "[::1]:0") - defer backend.Close() - backend.Run() - frontendAddr := &net.TCPAddr{IP: net.IPv6loopback, Port: 0} - proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) - if err != nil { - t.Fatal(err) - } - ipv4ProxyAddr := &net.TCPAddr{ - IP: net.IPv4(127, 0, 0, 1), - Port: proxy.FrontendAddr().(*net.TCPAddr).Port, - } - testProxyAt(t, "tcp", proxy, ipv4ProxyAddr.String()) -} - -func TestUDP4Proxy(t *testing.T) { - backend := NewEchoServer(t, "udp", "127.0.0.1:0") - defer backend.Close() - backend.Run() - frontendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0} - proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) - if err != nil { - t.Fatal(err) - } - testProxy(t, "udp", proxy) -} - -func TestUDP6Proxy(t *testing.T) { - backend := NewEchoServer(t, "udp", "[::1]:0") - defer backend.Close() - backend.Run() - frontendAddr := &net.UDPAddr{IP: net.IPv6loopback, Port: 0} - proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) - if err != nil { - t.Fatal(err) - } - testProxy(t, "udp", proxy) -} - -func TestUDPWriteError(t *testing.T) { - frontendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0} - // Hopefully, this port will be free: */ - backendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 25587} - proxy, err := NewProxy(frontendAddr, backendAddr) - if err != nil { - t.Fatal(err) - } - defer proxy.Close() - go proxy.Run() - client, err := net.Dial("udp", "127.0.0.1:25587") - if err != nil { - t.Fatalf("Can't connect to the proxy: %v", err) - } - defer client.Close() - // Make sure the proxy doesn't stop when there is no actual backend: - client.Write(testBuf) - client.Write(testBuf) - backend := NewEchoServer(t, "udp", "127.0.0.1:25587") - defer backend.Close() - backend.Run() - client.SetDeadline(time.Now().Add(10 * time.Second)) - if _, err = client.Write(testBuf); err != nil { - t.Fatal(err) - } - recvBuf := make([]byte, testBufSize) - if _, err = client.Read(recvBuf); err != nil { - t.Fatal(err) - } - if !bytes.Equal(testBuf, recvBuf) { - t.Fatal(fmt.Errorf("Expected [%v] but got [%v]", testBuf, recvBuf)) - } -} diff --git a/pkg/testutil/assert/assert.go b/pkg/testutil/assert/assert.go index a36b58bae4..5b0dcce67a 100644 --- a/pkg/testutil/assert/assert.go +++ b/pkg/testutil/assert/assert.go @@ -2,6 +2,9 @@ package assert import ( + "fmt" + "path/filepath" + "runtime" "strings" ) @@ -15,7 +18,7 @@ type TestingT interface { // they are not equal. func Equal(t TestingT, actual, expected interface{}) { if expected != actual { - t.Fatalf("Expected '%v' (%T) got '%v' (%T)", expected, expected, actual, actual) + fatal(t, fmt.Sprintf("Expected '%v' (%T) got '%v' (%T)", expected, expected, actual, actual)) } } @@ -37,7 +40,7 @@ func EqualStringSlice(t TestingT, actual, expected []string) { // NilError asserts that the error is nil, otherwise it fails the test. func NilError(t TestingT, err error) { if err != nil { - t.Fatalf("Expected no error, got: %s", err.Error()) + fatal(t, fmt.Sprintf("Expected no error, got: %s", err.Error())) } } @@ -45,11 +48,11 @@ func NilError(t TestingT, err error) { // otherwise it fails the test. func Error(t TestingT, err error, contains string) { if err == nil { - t.Fatalf("Expected an error, but error was nil") + fatal(t, "Expected an error, but error was nil") } if !strings.Contains(err.Error(), contains) { - t.Fatalf("Expected error to contain '%s', got '%s'", contains, err.Error()) + fatal(t, fmt.Sprintf("Expected error to contain '%s', got '%s'", contains, err.Error())) } } @@ -57,6 +60,11 @@ func Error(t TestingT, err error, contains string) { // test. func Contains(t TestingT, actual, contains string) { if !strings.Contains(actual, contains) { - t.Fatalf("Expected '%s' to contain '%s'", actual, contains) + fatal(t, fmt.Sprintf("Expected '%s' to contain '%s'", actual, contains)) } } + +func fatal(t TestingT, msg string) { + _, file, line, _ := runtime.Caller(2) + t.Fatalf("%s:%d: %s", filepath.Base(file), line, msg) +} diff --git a/plugin/distribution/pull.go b/plugin/distribution/pull.go index 61971b3ee6..1bae8d4bb7 100644 --- a/plugin/distribution/pull.go +++ b/plugin/distribution/pull.go @@ -104,7 +104,7 @@ func Pull(name string, rs registry.Service, metaheader http.Header, authConfig * } if !confirmedV2 { logrus.Debugf("pull.go: !confirmedV2") - return nil, ErrUnSupportedRegistry + return nil, ErrUnsupportedRegistry } logrus.Debugf("Trying to pull %s from %s %s", repoInfo.Name(), endpoint.URL, endpoint.Version) break @@ -143,6 +143,9 @@ func Pull(name string, rs registry.Service, metaheader http.Header, authConfig * logrus.Debugf("pull.go: error in json.Unmarshal(): %v", err) return nil, err } + if m.Config.MediaType != MediaTypeConfig { + return nil, ErrUnsupportedMediaType + } pd := &pullData{ repository: repository, diff --git a/plugin/distribution/push.go b/plugin/distribution/push.go index 45deea83bb..27e717af4c 100644 --- a/plugin/distribution/push.go +++ b/plugin/distribution/push.go @@ -51,7 +51,7 @@ func Push(name string, rs registry.Service, metaHeader http.Header, authConfig * return "", err } if !confirmedV2 { - return "", ErrUnSupportedRegistry + return "", ErrUnsupportedRegistry } logrus.Debugf("Trying to push %s to %s %s", repoInfo.Name(), endpoint.URL, endpoint.Version) // This means that we found an endpoint. and we are ready to push diff --git a/plugin/distribution/types.go b/plugin/distribution/types.go index e1c05b76ff..0b1fd7aea1 100644 --- a/plugin/distribution/types.go +++ b/plugin/distribution/types.go @@ -4,8 +4,11 @@ package distribution import "errors" -// ErrUnSupportedRegistry indicates that the registry does not support v2 protocol -var ErrUnSupportedRegistry = errors.New("Only V2 repositories are supported for plugin distribution") +// ErrUnsupportedRegistry indicates that the registry does not support v2 protocol +var ErrUnsupportedRegistry = errors.New("only V2 repositories are supported for plugin distribution") + +// ErrUnsupportedMediaType indicates we are pulling content that's not a plugin +var ErrUnsupportedMediaType = errors.New("content is not a plugin") // Plugin related media types const ( diff --git a/plugin/manager.go b/plugin/manager.go index 267ea2e4c0..5ee7de64c7 100644 --- a/plugin/manager.go +++ b/plugin/manager.go @@ -47,6 +47,7 @@ type plugin struct { client *plugins.Client restartManager restartmanager.RestartManager runtimeSourcePath string + exitChan chan bool } func (p *plugin) Client() *plugins.Client { @@ -98,6 +99,7 @@ type Manager struct { registryService registry.Service handleLegacy bool liveRestore bool + shutdown bool } // GetManager returns the singleton plugin Manager @@ -250,9 +252,22 @@ func LookupWithCapability(name, capability string) (Plugin, error) { return nil, ErrInadequateCapability{name, capability} } -// StateChanged updates daemon inter... +// StateChanged updates plugin internals using from libcontainerd events. func (pm *Manager) StateChanged(id string, e libcontainerd.StateInfo) error { - logrus.Debugf("plugin statechanged %s %#v", id, e) + logrus.Debugf("plugin state changed %s %#v", id, e) + + switch e.State { + case libcontainerd.StateExit: + pm.RLock() + p, idOk := pm.plugins[id] + pm.RUnlock() + if !idOk { + return ErrNotFound(id) + } + if pm.shutdown == true { + p.exitChan <- true + } + } return nil } diff --git a/plugin/manager_linux.go b/plugin/manager_linux.go index 277fa3c48e..6b9b570f72 100644 --- a/plugin/manager_linux.go +++ b/plugin/manager_linux.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "syscall" + "time" "github.com/Sirupsen/logrus" "github.com/docker/docker/libcontainerd" @@ -128,3 +129,39 @@ func (pm *Manager) disable(p *plugin) error { pm.save() return nil } + +// Shutdown stops all plugins and called during daemon shutdown. +func (pm *Manager) Shutdown() { + pm.RLock() + defer pm.RUnlock() + + pm.shutdown = true + for _, p := range pm.plugins { + if p.restartManager != nil { + if err := p.restartManager.Cancel(); err != nil { + logrus.Error(err) + } + } + if pm.containerdClient != nil { + p.exitChan = make(chan bool) + err := pm.containerdClient.Signal(p.P.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(p.P.ID, int(syscall.SIGKILL)); err != nil { + logrus.Errorf("Sending SIGKILL to plugin failed with error: %v", err) + } + } + } + close(p.exitChan) + } + if err := os.RemoveAll(p.runtimeSourcePath); err != nil { + logrus.Errorf("Remove plugin runtime failed with error: %v", err) + } + } +} diff --git a/plugin/manager_windows.go b/plugin/manager_windows.go index 84d7a4c1c9..cbdb78b682 100644 --- a/plugin/manager_windows.go +++ b/plugin/manager_windows.go @@ -23,3 +23,7 @@ func (pm *Manager) disable(p *plugin) error { func (pm *Manager) restore(p *plugin) error { return fmt.Errorf("Not implemented") } + +// Shutdown plugins +func (pm *Manager) Shutdown() { +} diff --git a/runconfig/opts/parse.go b/runconfig/opts/parse.go index a899dd418f..e6409cc4d5 100644 --- a/runconfig/opts/parse.go +++ b/runconfig/opts/parse.go @@ -55,54 +55,54 @@ type ContainerOptions struct { flStorageOpt opts.ListOpts flLabelsFile opts.ListOpts flLoggingOpts opts.ListOpts - flPrivileged *bool - flPidMode *string - flUTSMode *string - flUsernsMode *string - flPublishAll *bool - flStdin *bool - flTty *bool - flOomKillDisable *bool - flOomScoreAdj *int - flContainerIDFile *string - flEntrypoint *string - flHostname *string - flMemoryString *string - flMemoryReservation *string - flMemorySwap *string - flKernelMemory *string - flUser *string - flWorkingDir *string - flCPUShares *int64 - flCPUPercent *int64 - flCPUPeriod *int64 - flCPUQuota *int64 - flCpusetCpus *string - flCpusetMems *string - flBlkioWeight *uint16 - flIOMaxBandwidth *string - flIOMaxIOps *uint64 - flSwappiness *int64 - flNetMode *string - flMacAddress *string - flIPv4Address *string - flIPv6Address *string - flIpcMode *string - flPidsLimit *int64 - flRestartPolicy *string - flReadonlyRootfs *bool - flLoggingDriver *string - flCgroupParent *string - flVolumeDriver *string - flStopSignal *string - flIsolation *string - flShmSize *string - flNoHealthcheck *bool - flHealthCmd *string - flHealthInterval *time.Duration - flHealthTimeout *time.Duration - flHealthRetries *int - flRuntime *string + flPrivileged bool + flPidMode string + flUTSMode string + flUsernsMode string + flPublishAll bool + flStdin bool + flTty bool + flOomKillDisable bool + flOomScoreAdj int + flContainerIDFile string + flEntrypoint string + flHostname string + flMemoryString string + flMemoryReservation string + flMemorySwap string + flKernelMemory string + flUser string + flWorkingDir string + flCPUShares int64 + flCPUPercent int64 + flCPUPeriod int64 + flCPUQuota int64 + flCpusetCpus string + flCpusetMems string + flBlkioWeight uint16 + flIOMaxBandwidth string + flIOMaxIOps uint64 + flSwappiness int64 + flNetMode string + flMacAddress string + flIPv4Address string + flIPv6Address string + flIpcMode string + flPidsLimit int64 + flRestartPolicy string + flReadonlyRootfs bool + flLoggingDriver string + flCgroupParent string + flVolumeDriver string + flStopSignal string + flIsolation string + flShmSize string + flNoHealthcheck bool + flHealthCmd string + flHealthInterval time.Duration + flHealthTimeout time.Duration + flHealthRetries int + flRuntime string Image string Args []string @@ -111,122 +111,137 @@ type ContainerOptions struct { // AddFlags adds all command line flags that will be used by Parse to the FlagSet func AddFlags(flags *pflag.FlagSet) *ContainerOptions { copts := &ContainerOptions{ - flAttach: opts.NewListOpts(ValidateAttach), - flVolumes: opts.NewListOpts(nil), - flTmpfs: opts.NewListOpts(nil), - flBlkioWeightDevice: NewWeightdeviceOpt(ValidateWeightDevice), - flDeviceReadBps: NewThrottledeviceOpt(ValidateThrottleBpsDevice), - flDeviceWriteBps: NewThrottledeviceOpt(ValidateThrottleBpsDevice), - flLinks: opts.NewListOpts(ValidateLink), flAliases: opts.NewListOpts(nil), - flLinkLocalIPs: opts.NewListOpts(nil), + flAttach: opts.NewListOpts(ValidateAttach), + flBlkioWeightDevice: NewWeightdeviceOpt(ValidateWeightDevice), + flCapAdd: opts.NewListOpts(nil), + flCapDrop: opts.NewListOpts(nil), + flDNS: opts.NewListOpts(opts.ValidateIPAddress), + flDNSOptions: opts.NewListOpts(nil), + flDNSSearch: opts.NewListOpts(opts.ValidateDNSSearch), + flDeviceReadBps: NewThrottledeviceOpt(ValidateThrottleBpsDevice), flDeviceReadIOps: NewThrottledeviceOpt(ValidateThrottleIOpsDevice), + flDeviceWriteBps: NewThrottledeviceOpt(ValidateThrottleBpsDevice), flDeviceWriteIOps: NewThrottledeviceOpt(ValidateThrottleIOpsDevice), - flEnv: opts.NewListOpts(ValidateEnv), - flLabels: opts.NewListOpts(ValidateEnv), flDevices: opts.NewListOpts(ValidateDevice), - - flUlimits: NewUlimitOpt(nil), - flSysctls: opts.NewMapOpts(nil, opts.ValidateSysctl), - - flPublish: opts.NewListOpts(nil), - flExpose: opts.NewListOpts(nil), - flDNS: opts.NewListOpts(opts.ValidateIPAddress), - flDNSSearch: opts.NewListOpts(opts.ValidateDNSSearch), - flDNSOptions: opts.NewListOpts(nil), - flExtraHosts: opts.NewListOpts(ValidateExtraHost), - flVolumesFrom: opts.NewListOpts(nil), - flEnvFile: opts.NewListOpts(nil), - flCapAdd: opts.NewListOpts(nil), - flCapDrop: opts.NewListOpts(nil), - flGroupAdd: opts.NewListOpts(nil), - flSecurityOpt: opts.NewListOpts(nil), - flStorageOpt: opts.NewListOpts(nil), - flLabelsFile: opts.NewListOpts(nil), - flLoggingOpts: opts.NewListOpts(nil), - - flPrivileged: flags.Bool("privileged", false, "Give extended privileges to this container"), - flPidMode: flags.String("pid", "", "PID namespace to use"), - flUTSMode: flags.String("uts", "", "UTS namespace to use"), - flUsernsMode: flags.String("userns", "", "User namespace to use"), - flPublishAll: flags.BoolP("publish-all", "P", false, "Publish all exposed ports to random ports"), - flStdin: flags.BoolP("interactive", "i", false, "Keep STDIN open even if not attached"), - flTty: flags.BoolP("tty", "t", false, "Allocate a pseudo-TTY"), - flOomKillDisable: flags.Bool("oom-kill-disable", false, "Disable OOM Killer"), - flOomScoreAdj: flags.Int("oom-score-adj", 0, "Tune host's OOM preferences (-1000 to 1000)"), - flContainerIDFile: flags.String("cidfile", "", "Write the container ID to the file"), - flEntrypoint: flags.String("entrypoint", "", "Overwrite the default ENTRYPOINT of the image"), - flHostname: flags.StringP("hostname", "h", "", "Container host name"), - flMemoryString: flags.StringP("memory", "m", "", "Memory limit"), - flMemoryReservation: flags.String("memory-reservation", "", "Memory soft limit"), - flMemorySwap: flags.String("memory-swap", "", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap"), - flKernelMemory: flags.String("kernel-memory", "", "Kernel memory limit"), - flUser: flags.StringP("user", "u", "", "Username or UID (format: [:])"), - flWorkingDir: flags.StringP("workdir", "w", "", "Working directory inside the container"), - flCPUShares: flags.Int64P("cpu-shares", "c", 0, "CPU shares (relative weight)"), - flCPUPercent: flags.Int64("cpu-percent", 0, "CPU percent (Windows only)"), - flCPUPeriod: flags.Int64("cpu-period", 0, "Limit CPU CFS (Completely Fair Scheduler) period"), - flCPUQuota: flags.Int64("cpu-quota", 0, "Limit CPU CFS (Completely Fair Scheduler) quota"), - flCpusetCpus: flags.String("cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)"), - flCpusetMems: flags.String("cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)"), - flBlkioWeight: flags.Uint16("blkio-weight", 0, "Block IO (relative weight), between 10 and 1000"), - flIOMaxBandwidth: flags.String("io-maxbandwidth", "", "Maximum IO bandwidth limit for the system drive (Windows only)"), - flIOMaxIOps: flags.Uint64("io-maxiops", 0, "Maximum IOps limit for the system drive (Windows only)"), - flSwappiness: flags.Int64("memory-swappiness", -1, "Tune container memory swappiness (0 to 100)"), - flNetMode: flags.String("net", "default", "Connect a container to a network"), - flMacAddress: flags.String("mac-address", "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)"), - flIPv4Address: flags.String("ip", "", "Container IPv4 address (e.g. 172.30.100.104)"), - flIPv6Address: flags.String("ip6", "", "Container IPv6 address (e.g. 2001:db8::33)"), - flIpcMode: flags.String("ipc", "", "IPC namespace to use"), - flPidsLimit: flags.Int64("pids-limit", 0, "Tune container pids limit (set -1 for unlimited)"), - flRestartPolicy: flags.String("restart", "no", "Restart policy to apply when a container exits"), - flReadonlyRootfs: flags.Bool("read-only", false, "Mount the container's root filesystem as read only"), - flLoggingDriver: flags.String("log-driver", "", "Logging driver for container"), - flCgroupParent: flags.String("cgroup-parent", "", "Optional parent cgroup for the container"), - flVolumeDriver: flags.String("volume-driver", "", "Optional volume driver for the container"), - flStopSignal: flags.String("stop-signal", signal.DefaultStopSignal, fmt.Sprintf("Signal to stop a container, %v by default", signal.DefaultStopSignal)), - flIsolation: flags.String("isolation", "", "Container isolation technology"), - flShmSize: flags.String("shm-size", "", "Size of /dev/shm, default value is 64MB"), - flNoHealthcheck: flags.Bool("no-healthcheck", false, "Disable any container-specified HEALTHCHECK"), - flHealthCmd: flags.String("health-cmd", "", "Command to run to check health"), - flHealthInterval: flags.Duration("health-interval", 0, "Time between running the check"), - flHealthTimeout: flags.Duration("health-timeout", 0, "Maximum time to allow one check to run"), - flHealthRetries: flags.Int("health-retries", 0, "Consecutive failures needed to report unhealthy"), - flRuntime: flags.String("runtime", "", "Runtime to use for this container"), + flEnv: opts.NewListOpts(ValidateEnv), + flEnvFile: opts.NewListOpts(nil), + flExpose: opts.NewListOpts(nil), + flExtraHosts: opts.NewListOpts(ValidateExtraHost), + flGroupAdd: opts.NewListOpts(nil), + flLabels: opts.NewListOpts(ValidateEnv), + flLabelsFile: opts.NewListOpts(nil), + flLinkLocalIPs: opts.NewListOpts(nil), + flLinks: opts.NewListOpts(ValidateLink), + flLoggingOpts: opts.NewListOpts(nil), + flPublish: opts.NewListOpts(nil), + flSecurityOpt: opts.NewListOpts(nil), + flStorageOpt: opts.NewListOpts(nil), + flSysctls: opts.NewMapOpts(nil, opts.ValidateSysctl), + flTmpfs: opts.NewListOpts(nil), + flUlimits: NewUlimitOpt(nil), + flVolumes: opts.NewListOpts(nil), + flVolumesFrom: opts.NewListOpts(nil), } + // General purpose flags flags.VarP(&copts.flAttach, "attach", "a", "Attach to STDIN, STDOUT or STDERR") - flags.Var(&copts.flBlkioWeightDevice, "blkio-weight-device", "Block IO weight (relative device weight)") - flags.Var(&copts.flDeviceReadBps, "device-read-bps", "Limit read rate (bytes per second) from a device") - flags.Var(&copts.flDeviceWriteBps, "device-write-bps", "Limit write rate (bytes per second) to a device") - flags.Var(&copts.flDeviceReadIOps, "device-read-iops", "Limit read rate (IO per second) from a device") - flags.Var(&copts.flDeviceWriteIOps, "device-write-iops", "Limit write rate (IO per second) to a device") - flags.VarP(&copts.flVolumes, "volume", "v", "Bind mount a volume") - flags.Var(&copts.flTmpfs, "tmpfs", "Mount a tmpfs directory") - flags.Var(&copts.flLinks, "link", "Add link to another container") - flags.Var(&copts.flAliases, "net-alias", "Add network-scoped alias for the container") - flags.Var(&copts.flLinkLocalIPs, "link-local-ip", "Container IPv4/IPv6 link-local addresses") flags.Var(&copts.flDevices, "device", "Add a host device to the container") - flags.VarP(&copts.flLabels, "label", "l", "Set meta data on a container") - flags.Var(&copts.flLabelsFile, "label-file", "Read in a line delimited file of labels") flags.VarP(&copts.flEnv, "env", "e", "Set environment variables") flags.Var(&copts.flEnvFile, "env-file", "Read in a file of environment variables") - flags.VarP(&copts.flPublish, "publish", "p", "Publish a container's port(s) to the host") - flags.Var(&copts.flExpose, "expose", "Expose a port or a range of ports") - flags.Var(&copts.flDNS, "dns", "Set custom DNS servers") - flags.Var(&copts.flDNSSearch, "dns-search", "Set custom DNS search domains") - flags.Var(&copts.flDNSOptions, "dns-opt", "Set DNS options") - flags.Var(&copts.flExtraHosts, "add-host", "Add a custom host-to-IP mapping (host:ip)") - flags.Var(&copts.flVolumesFrom, "volumes-from", "Mount volumes from the specified container(s)") + flags.StringVar(&copts.flEntrypoint, "entrypoint", "", "Overwrite the default ENTRYPOINT of the image") + flags.Var(&copts.flGroupAdd, "group-add", "Add additional groups to join") + flags.StringVarP(&copts.flHostname, "hostname", "h", "", "Container host name") + flags.BoolVarP(&copts.flStdin, "interactive", "i", false, "Keep STDIN open even if not attached") + flags.VarP(&copts.flLabels, "label", "l", "Set meta data on a container") + flags.Var(&copts.flLabelsFile, "label-file", "Read in a line delimited file of labels") + flags.BoolVar(&copts.flReadonlyRootfs, "read-only", false, "Mount the container's root filesystem as read only") + flags.StringVar(&copts.flRestartPolicy, "restart", "no", "Restart policy to apply when a container exits") + flags.StringVar(&copts.flStopSignal, "stop-signal", signal.DefaultStopSignal, fmt.Sprintf("Signal to stop a container, %v by default", signal.DefaultStopSignal)) + flags.Var(copts.flSysctls, "sysctl", "Sysctl options") + flags.BoolVarP(&copts.flTty, "tty", "t", false, "Allocate a pseudo-TTY") + flags.Var(copts.flUlimits, "ulimit", "Ulimit options") + flags.StringVarP(&copts.flUser, "user", "u", "", "Username or UID (format: [:])") + flags.StringVarP(&copts.flWorkingDir, "workdir", "w", "", "Working directory inside the container") + + // Security flags.Var(&copts.flCapAdd, "cap-add", "Add Linux capabilities") flags.Var(&copts.flCapDrop, "cap-drop", "Drop Linux capabilities") - flags.Var(&copts.flGroupAdd, "group-add", "Add additional groups to join") + flags.BoolVar(&copts.flPrivileged, "privileged", false, "Give extended privileges to this container") flags.Var(&copts.flSecurityOpt, "security-opt", "Security Options") - flags.Var(&copts.flStorageOpt, "storage-opt", "Set storage driver options per container") - flags.Var(copts.flUlimits, "ulimit", "Ulimit options") - flags.Var(copts.flSysctls, "sysctl", "Sysctl options") - flags.Var(&copts.flLoggingOpts, "log-opt", "Log driver options") + flags.StringVar(&copts.flUsernsMode, "userns", "", "User namespace to use") + // Network and port publishing flag + flags.Var(&copts.flExtraHosts, "add-host", "Add a custom host-to-IP mapping (host:ip)") + flags.Var(&copts.flDNS, "dns", "Set custom DNS servers") + flags.Var(&copts.flDNSOptions, "dns-opt", "Set DNS options") + flags.Var(&copts.flDNSSearch, "dns-search", "Set custom DNS search domains") + flags.Var(&copts.flExpose, "expose", "Expose a port or a range of ports") + flags.StringVar(&copts.flIPv4Address, "ip", "", "Container IPv4 address (e.g. 172.30.100.104)") + flags.StringVar(&copts.flIPv6Address, "ip6", "", "Container IPv6 address (e.g. 2001:db8::33)") + flags.Var(&copts.flLinks, "link", "Add link to another container") + flags.Var(&copts.flLinkLocalIPs, "link-local-ip", "Container IPv4/IPv6 link-local addresses") + flags.StringVar(&copts.flMacAddress, "mac-address", "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)") + flags.VarP(&copts.flPublish, "publish", "p", "Publish a container's port(s) to the host") + flags.BoolVarP(&copts.flPublishAll, "publish-all", "P", false, "Publish all exposed ports to random ports") + // We allow for both "--net" and "--network", although the latter is the recommended way. + flags.StringVar(&copts.flNetMode, "net", "default", "Connect a container to a network") + flags.StringVar(&copts.flNetMode, "network", "default", "Connect a container to a network") + flags.MarkHidden("net") + // We allow for both "--net-alias" and "--network-alias", although the latter is the recommended way. + flags.Var(&copts.flAliases, "net-alias", "Add network-scoped alias for the container") + flags.Var(&copts.flAliases, "network-alias", "Add network-scoped alias for the container") + flags.MarkHidden("net-alias") + + // Logging and storage + flags.StringVar(&copts.flLoggingDriver, "log-driver", "", "Logging driver for container") + flags.StringVar(&copts.flVolumeDriver, "volume-driver", "", "Optional volume driver for the container") + flags.Var(&copts.flLoggingOpts, "log-opt", "Log driver options") + flags.Var(&copts.flStorageOpt, "storage-opt", "Set storage driver options per container") + flags.Var(&copts.flTmpfs, "tmpfs", "Mount a tmpfs directory") + flags.Var(&copts.flVolumesFrom, "volumes-from", "Mount volumes from the specified container(s)") + flags.VarP(&copts.flVolumes, "volume", "v", "Bind mount a volume") + + // Health-checking + flags.StringVar(&copts.flHealthCmd, "health-cmd", "", "Command to run to check health") + flags.DurationVar(&copts.flHealthInterval, "health-interval", 0, "Time between running the check") + flags.IntVar(&copts.flHealthRetries, "health-retries", 0, "Consecutive failures needed to report unhealthy") + flags.DurationVar(&copts.flHealthTimeout, "health-timeout", 0, "Maximum time to allow one check to run") + flags.BoolVar(&copts.flNoHealthcheck, "no-healthcheck", false, "Disable any container-specified HEALTHCHECK") + + // Resource management + flags.Uint16Var(&copts.flBlkioWeight, "blkio-weight", 0, "Block IO (relative weight), between 10 and 1000") + flags.Var(&copts.flBlkioWeightDevice, "blkio-weight-device", "Block IO weight (relative device weight)") + flags.StringVar(&copts.flContainerIDFile, "cidfile", "", "Write the container ID to the file") + flags.StringVar(&copts.flCpusetCpus, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)") + flags.StringVar(&copts.flCpusetMems, "cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)") + flags.Int64Var(&copts.flCPUPercent, "cpu-percent", 0, "CPU percent (Windows only)") + flags.Int64Var(&copts.flCPUPeriod, "cpu-period", 0, "Limit CPU CFS (Completely Fair Scheduler) period") + flags.Int64Var(&copts.flCPUQuota, "cpu-quota", 0, "Limit CPU CFS (Completely Fair Scheduler) quota") + flags.Int64VarP(&copts.flCPUShares, "cpu-shares", "c", 0, "CPU shares (relative weight)") + flags.Var(&copts.flDeviceReadBps, "device-read-bps", "Limit read rate (bytes per second) from a device") + flags.Var(&copts.flDeviceReadIOps, "device-read-iops", "Limit read rate (IO per second) from a device") + flags.Var(&copts.flDeviceWriteBps, "device-write-bps", "Limit write rate (bytes per second) to a device") + flags.Var(&copts.flDeviceWriteIOps, "device-write-iops", "Limit write rate (IO per second) to a device") + flags.StringVar(&copts.flIOMaxBandwidth, "io-maxbandwidth", "", "Maximum IO bandwidth limit for the system drive (Windows only)") + flags.Uint64Var(&copts.flIOMaxIOps, "io-maxiops", 0, "Maximum IOps limit for the system drive (Windows only)") + flags.StringVar(&copts.flKernelMemory, "kernel-memory", "", "Kernel memory limit") + flags.StringVarP(&copts.flMemoryString, "memory", "m", "", "Memory limit") + flags.StringVar(&copts.flMemoryReservation, "memory-reservation", "", "Memory soft limit") + flags.StringVar(&copts.flMemorySwap, "memory-swap", "", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap") + flags.Int64Var(&copts.flSwappiness, "memory-swappiness", -1, "Tune container memory swappiness (0 to 100)") + flags.BoolVar(&copts.flOomKillDisable, "oom-kill-disable", false, "Disable OOM Killer") + flags.IntVar(&copts.flOomScoreAdj, "oom-score-adj", 0, "Tune host's OOM preferences (-1000 to 1000)") + flags.Int64Var(&copts.flPidsLimit, "pids-limit", 0, "Tune container pids limit (set -1 for unlimited)") + + // Low-level execution (cgroups, namespaces, ...) + flags.StringVar(&copts.flCgroupParent, "cgroup-parent", "", "Optional parent cgroup for the container") + flags.StringVar(&copts.flIpcMode, "ipc", "", "IPC namespace to use") + flags.StringVar(&copts.flIsolation, "isolation", "", "Container isolation technology") + flags.StringVar(&copts.flPidMode, "pid", "", "PID namespace to use") + flags.StringVar(&copts.flShmSize, "shm-size", "", "Size of /dev/shm, default value is 64MB") + flags.StringVar(&copts.flUTSMode, "uts", "", "UTS namespace to use") + flags.StringVar(&copts.flRuntime, "runtime", "", "Runtime to use for this container") return copts } @@ -241,12 +256,12 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c ) // Validate the input mac address - if *copts.flMacAddress != "" { - if _, err := ValidateMACAddress(*copts.flMacAddress); err != nil { - return nil, nil, nil, fmt.Errorf("%s is not a valid mac address", *copts.flMacAddress) + if copts.flMacAddress != "" { + if _, err := ValidateMACAddress(copts.flMacAddress); err != nil { + return nil, nil, nil, fmt.Errorf("%s is not a valid mac address", copts.flMacAddress) } } - if *copts.flStdin { + if copts.flStdin { attachStdin = true } // If -a is not set, attach to stdout and stderr @@ -258,27 +273,27 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c var err error var flMemory int64 - if *copts.flMemoryString != "" { - flMemory, err = units.RAMInBytes(*copts.flMemoryString) + if copts.flMemoryString != "" { + flMemory, err = units.RAMInBytes(copts.flMemoryString) if err != nil { return nil, nil, nil, err } } var MemoryReservation int64 - if *copts.flMemoryReservation != "" { - MemoryReservation, err = units.RAMInBytes(*copts.flMemoryReservation) + if copts.flMemoryReservation != "" { + MemoryReservation, err = units.RAMInBytes(copts.flMemoryReservation) if err != nil { return nil, nil, nil, err } } var memorySwap int64 - if *copts.flMemorySwap != "" { - if *copts.flMemorySwap == "-1" { + if copts.flMemorySwap != "" { + if copts.flMemorySwap == "-1" { memorySwap = -1 } else { - memorySwap, err = units.RAMInBytes(*copts.flMemorySwap) + memorySwap, err = units.RAMInBytes(copts.flMemorySwap) if err != nil { return nil, nil, nil, err } @@ -286,21 +301,21 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c } var KernelMemory int64 - if *copts.flKernelMemory != "" { - KernelMemory, err = units.RAMInBytes(*copts.flKernelMemory) + if copts.flKernelMemory != "" { + KernelMemory, err = units.RAMInBytes(copts.flKernelMemory) if err != nil { return nil, nil, nil, err } } - swappiness := *copts.flSwappiness + swappiness := copts.flSwappiness if swappiness != -1 && (swappiness < 0 || swappiness > 100) { return nil, nil, nil, fmt.Errorf("invalid value: %d. Valid memory swappiness range is 0-100", swappiness) } var shmSize int64 - if *copts.flShmSize != "" { - shmSize, err = units.RAMInBytes(*copts.flShmSize) + if copts.flShmSize != "" { + shmSize, err = units.RAMInBytes(copts.flShmSize) if err != nil { return nil, nil, nil, err } @@ -308,13 +323,13 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c // TODO FIXME units.RAMInBytes should have a uint64 version var maxIOBandwidth int64 - if *copts.flIOMaxBandwidth != "" { - maxIOBandwidth, err = units.RAMInBytes(*copts.flIOMaxBandwidth) + if copts.flIOMaxBandwidth != "" { + maxIOBandwidth, err = units.RAMInBytes(copts.flIOMaxBandwidth) if err != nil { return nil, nil, nil, err } if maxIOBandwidth < 0 { - return nil, nil, nil, fmt.Errorf("invalid value: %s. Maximum IO Bandwidth must be positive", *copts.flIOMaxBandwidth) + return nil, nil, nil, fmt.Errorf("invalid value: %s. Maximum IO Bandwidth must be positive", copts.flIOMaxBandwidth) } } @@ -349,8 +364,8 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c if len(copts.Args) > 0 { runCmd = strslice.StrSlice(copts.Args) } - if *copts.flEntrypoint != "" { - entrypoint = strslice.StrSlice{*copts.flEntrypoint} + if copts.flEntrypoint != "" { + entrypoint = strslice.StrSlice{copts.flEntrypoint} } ports, portBindings, err := nat.ParsePortSpecs(copts.flPublish.GetAll()) @@ -404,32 +419,32 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c return nil, nil, nil, err } - ipcMode := container.IpcMode(*copts.flIpcMode) + ipcMode := container.IpcMode(copts.flIpcMode) if !ipcMode.Valid() { return nil, nil, nil, fmt.Errorf("--ipc: invalid IPC mode") } - pidMode := container.PidMode(*copts.flPidMode) + pidMode := container.PidMode(copts.flPidMode) if !pidMode.Valid() { return nil, nil, nil, fmt.Errorf("--pid: invalid PID mode") } - utsMode := container.UTSMode(*copts.flUTSMode) + utsMode := container.UTSMode(copts.flUTSMode) if !utsMode.Valid() { return nil, nil, nil, fmt.Errorf("--uts: invalid UTS mode") } - usernsMode := container.UsernsMode(*copts.flUsernsMode) + usernsMode := container.UsernsMode(copts.flUsernsMode) if !usernsMode.Valid() { return nil, nil, nil, fmt.Errorf("--userns: invalid USER mode") } - restartPolicy, err := ParseRestartPolicy(*copts.flRestartPolicy) + restartPolicy, err := ParseRestartPolicy(copts.flRestartPolicy) if err != nil { return nil, nil, nil, err } - loggingOpts, err := parseLoggingOpts(*copts.flLoggingDriver, copts.flLoggingOpts.GetAll()) + loggingOpts, err := parseLoggingOpts(copts.flLoggingDriver, copts.flLoggingOpts.GetAll()) if err != nil { return nil, nil, nil, err } @@ -446,11 +461,11 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c // Healthcheck var healthConfig *container.HealthConfig - haveHealthSettings := *copts.flHealthCmd != "" || - *copts.flHealthInterval != 0 || - *copts.flHealthTimeout != 0 || - *copts.flHealthRetries != 0 - if *copts.flNoHealthcheck { + haveHealthSettings := copts.flHealthCmd != "" || + copts.flHealthInterval != 0 || + copts.flHealthTimeout != 0 || + copts.flHealthRetries != 0 + if copts.flNoHealthcheck { if haveHealthSettings { return nil, nil, nil, fmt.Errorf("--no-healthcheck conflicts with --health-* options") } @@ -458,62 +473,62 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c healthConfig = &container.HealthConfig{Test: test} } else if haveHealthSettings { var probe strslice.StrSlice - if *copts.flHealthCmd != "" { - args := []string{"CMD-SHELL", *copts.flHealthCmd} + if copts.flHealthCmd != "" { + args := []string{"CMD-SHELL", copts.flHealthCmd} probe = strslice.StrSlice(args) } - if *copts.flHealthInterval < 0 { + if copts.flHealthInterval < 0 { return nil, nil, nil, fmt.Errorf("--health-interval cannot be negative") } - if *copts.flHealthTimeout < 0 { + if copts.flHealthTimeout < 0 { return nil, nil, nil, fmt.Errorf("--health-timeout cannot be negative") } healthConfig = &container.HealthConfig{ Test: probe, - Interval: *copts.flHealthInterval, - Timeout: *copts.flHealthTimeout, - Retries: *copts.flHealthRetries, + Interval: copts.flHealthInterval, + Timeout: copts.flHealthTimeout, + Retries: copts.flHealthRetries, } } resources := container.Resources{ - CgroupParent: *copts.flCgroupParent, + CgroupParent: copts.flCgroupParent, Memory: flMemory, MemoryReservation: MemoryReservation, MemorySwap: memorySwap, - MemorySwappiness: copts.flSwappiness, + MemorySwappiness: &copts.flSwappiness, KernelMemory: KernelMemory, - OomKillDisable: copts.flOomKillDisable, - CPUPercent: *copts.flCPUPercent, - CPUShares: *copts.flCPUShares, - CPUPeriod: *copts.flCPUPeriod, - CpusetCpus: *copts.flCpusetCpus, - CpusetMems: *copts.flCpusetMems, - CPUQuota: *copts.flCPUQuota, - PidsLimit: *copts.flPidsLimit, - BlkioWeight: *copts.flBlkioWeight, + OomKillDisable: &copts.flOomKillDisable, + CPUPercent: copts.flCPUPercent, + CPUShares: copts.flCPUShares, + CPUPeriod: copts.flCPUPeriod, + CpusetCpus: copts.flCpusetCpus, + CpusetMems: copts.flCpusetMems, + CPUQuota: copts.flCPUQuota, + PidsLimit: copts.flPidsLimit, + BlkioWeight: copts.flBlkioWeight, BlkioWeightDevice: copts.flBlkioWeightDevice.GetList(), BlkioDeviceReadBps: copts.flDeviceReadBps.GetList(), BlkioDeviceWriteBps: copts.flDeviceWriteBps.GetList(), BlkioDeviceReadIOps: copts.flDeviceReadIOps.GetList(), BlkioDeviceWriteIOps: copts.flDeviceWriteIOps.GetList(), - IOMaximumIOps: *copts.flIOMaxIOps, + IOMaximumIOps: copts.flIOMaxIOps, IOMaximumBandwidth: uint64(maxIOBandwidth), Ulimits: copts.flUlimits.GetList(), Devices: deviceMappings, } config := &container.Config{ - Hostname: *copts.flHostname, + Hostname: copts.flHostname, ExposedPorts: ports, - User: *copts.flUser, - Tty: *copts.flTty, + User: copts.flUser, + Tty: copts.flTty, // TODO: deprecated, it comes from -n, --networking // it's still needed internally to set the network to disabled // if e.g. bridge is none in daemon opts, and in inspect NetworkDisabled: false, - OpenStdin: *copts.flStdin, + OpenStdin: copts.flStdin, AttachStdin: attachStdin, AttachStdout: attachStdout, AttachStderr: attachStderr, @@ -521,24 +536,24 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c Cmd: runCmd, Image: copts.Image, Volumes: copts.flVolumes.GetMap(), - MacAddress: *copts.flMacAddress, + MacAddress: copts.flMacAddress, Entrypoint: entrypoint, - WorkingDir: *copts.flWorkingDir, + WorkingDir: copts.flWorkingDir, Labels: ConvertKVStringsToMap(labels), Healthcheck: healthConfig, } if flags.Changed("stop-signal") { - config.StopSignal = *copts.flStopSignal + config.StopSignal = copts.flStopSignal } hostConfig := &container.HostConfig{ Binds: binds, - ContainerIDFile: *copts.flContainerIDFile, - OomScoreAdj: *copts.flOomScoreAdj, - Privileged: *copts.flPrivileged, + ContainerIDFile: copts.flContainerIDFile, + OomScoreAdj: copts.flOomScoreAdj, + Privileged: copts.flPrivileged, PortBindings: portBindings, Links: copts.flLinks.GetAll(), - PublishAllPorts: *copts.flPublishAll, + PublishAllPorts: copts.flPublishAll, // Make sure the dns fields are never nil. // New containers don't ever have those fields nil, // but pre created containers can still have those nil values. @@ -549,7 +564,7 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c DNSOptions: copts.flDNSOptions.GetAllOrEmpty(), ExtraHosts: copts.flExtraHosts.GetAll(), VolumesFrom: copts.flVolumesFrom.GetAll(), - NetworkMode: container.NetworkMode(*copts.flNetMode), + NetworkMode: container.NetworkMode(copts.flNetMode), IpcMode: ipcMode, PidMode: pidMode, UTSMode: utsMode, @@ -560,15 +575,15 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c RestartPolicy: restartPolicy, SecurityOpt: securityOpts, StorageOpt: storageOpts, - ReadonlyRootfs: *copts.flReadonlyRootfs, - LogConfig: container.LogConfig{Type: *copts.flLoggingDriver, Config: loggingOpts}, - VolumeDriver: *copts.flVolumeDriver, - Isolation: container.Isolation(*copts.flIsolation), + ReadonlyRootfs: copts.flReadonlyRootfs, + LogConfig: container.LogConfig{Type: copts.flLoggingDriver, Config: loggingOpts}, + VolumeDriver: copts.flVolumeDriver, + Isolation: container.Isolation(copts.flIsolation), ShmSize: shmSize, Resources: resources, Tmpfs: tmpfs, Sysctls: copts.flSysctls.GetAll(), - Runtime: *copts.flRuntime, + Runtime: copts.flRuntime, } // When allocating stdin in attached mode, close stdin at client disconnect @@ -580,13 +595,13 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c EndpointsConfig: make(map[string]*networktypes.EndpointSettings), } - if *copts.flIPv4Address != "" || *copts.flIPv6Address != "" || copts.flLinkLocalIPs.Len() > 0 { + if copts.flIPv4Address != "" || copts.flIPv6Address != "" || copts.flLinkLocalIPs.Len() > 0 { epConfig := &networktypes.EndpointSettings{} networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig epConfig.IPAMConfig = &networktypes.EndpointIPAMConfig{ - IPv4Address: *copts.flIPv4Address, - IPv6Address: *copts.flIPv6Address, + IPv4Address: copts.flIPv4Address, + IPv6Address: copts.flIPv6Address, } if copts.flLinkLocalIPs.Len() > 0 { diff --git a/vendor/src/github.com/docker/distribution/.mailmap b/vendor/src/github.com/docker/distribution/.mailmap index f0452da619..d991060198 100644 --- a/vendor/src/github.com/docker/distribution/.mailmap +++ b/vendor/src/github.com/docker/distribution/.mailmap @@ -13,4 +13,6 @@ Sharif Nassar Sharif Nassar Sven Dowideit Vincent Giersch Vincent Giersch davidli davidli -Omer Cohen Omer Cohen \ No newline at end of file +Omer Cohen Omer Cohen +Eric Yang Eric Yang +Nikita Tarasov Nikita diff --git a/vendor/src/github.com/docker/distribution/AUTHORS b/vendor/src/github.com/docker/distribution/AUTHORS index 70d525999b..9e80e062bb 100644 --- a/vendor/src/github.com/docker/distribution/AUTHORS +++ b/vendor/src/github.com/docker/distribution/AUTHORS @@ -6,6 +6,8 @@ Adrian Mouat Ahmet Alp Balkan Alex Chan Alex Elman +Alexey Gladkov +allencloud amitshukla Amy Lindburg Andrew Hsu @@ -30,6 +32,7 @@ Brian Bland burnettk Carson A Chris Dillon +cyli Daisuke Fujita Daniel Huhn Darren Shepherd @@ -52,6 +55,7 @@ Felix Yan Florentin Raud Frederick F. Kautz IV gabriell nascimento +Gleb Schukin harche Henri Gomez Hu Keping @@ -72,6 +76,7 @@ Jonathan Boulle Jordan Liggitt Josh Hawn Julien Fernandez +Ke Xu Keerthan Mala Kelsey Hightower Kenneth Lim @@ -94,6 +99,7 @@ moxiegirl Nathan Sullivan nevermosby Nghia Tran +Nikita Tarasov Nuutti Kotivuori Oilbeater Olivier Gambier @@ -137,4 +143,5 @@ xg.song xiekeyang Yann ROBERT yuzou +zhouhaibing089 姜继忠 diff --git a/vendor/src/github.com/docker/distribution/BUILDING.md b/vendor/src/github.com/docker/distribution/BUILDING.md new file mode 100644 index 0000000000..d9577022b6 --- /dev/null +++ b/vendor/src/github.com/docker/distribution/BUILDING.md @@ -0,0 +1,119 @@ + +# Building the registry source + +## Use-case + +This is useful if you intend to actively work on the registry. + +### Alternatives + +Most people should use the [official Registry docker image](https://hub.docker.com/r/library/registry/). + +People looking for advanced operational use cases might consider rolling their own image with a custom Dockerfile inheriting `FROM registry:2`. + +OS X users who want to run natively can do so following [the instructions here](osx-setup-guide.md). + +### Gotchas + +You are expected to know your way around with go & git. + +If you are a casual user with no development experience, and no preliminary knowledge of go, building from source is probably not a good solution for you. + +## Build the development environment + +The first prerequisite of properly building distribution targets is to have a Go +development environment setup. Please follow [How to Write Go Code](https://golang.org/doc/code.html) +for proper setup. If done correctly, you should have a GOROOT and GOPATH set in the +environment. + +If a Go development environment is setup, one can use `go get` to install the +`registry` command from the current latest: + + go get github.com/docker/distribution/cmd/registry + +The above will install the source repository into the `GOPATH`. + +Now create the directory for the registry data (this might require you to set permissions properly) + + mkdir -p /var/lib/registry + +... or alternatively `export REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/somewhere` if you want to store data into another location. + +The `registry` +binary can then be run with the following: + + $ $GOPATH/bin/registry --version + $GOPATH/bin/registry github.com/docker/distribution v2.0.0-alpha.1+unknown + +> __NOTE:__ While you do not need to use `go get` to checkout the distribution +> project, for these build instructions to work, the project must be checked +> out in the correct location in the `GOPATH`. This should almost always be +> `$GOPATH/src/github.com/docker/distribution`. + +The registry can be run with the default config using the following +incantation: + + $ $GOPATH/bin/registry serve $GOPATH/src/github.com/docker/distribution/cmd/registry/config-example.yml + INFO[0000] endpoint local-5003 disabled, skipping app.id=34bbec38-a91a-494a-9a3f-b72f9010081f version=v2.0.0-alpha.1+unknown + INFO[0000] endpoint local-8083 disabled, skipping app.id=34bbec38-a91a-494a-9a3f-b72f9010081f version=v2.0.0-alpha.1+unknown + INFO[0000] listening on :5000 app.id=34bbec38-a91a-494a-9a3f-b72f9010081f version=v2.0.0-alpha.1+unknown + INFO[0000] debug server listening localhost:5001 + +If it is working, one should see the above log messages. + +### Repeatable Builds + +For the full development experience, one should `cd` into +`$GOPATH/src/github.com/docker/distribution`. From there, the regular `go` +commands, such as `go test`, should work per package (please see +[Developing](#developing) if they don't work). + +A `Makefile` has been provided as a convenience to support repeatable builds. +Please install the following into `GOPATH` for it to work: + + go get github.com/tools/godep github.com/golang/lint/golint + +**TODO(stevvooe):** Add a `make setup` command to Makefile to run this. Have to think about how to interact with Godeps properly. + +Once these commands are available in the `GOPATH`, run `make` to get a full +build: + + $ make + + clean + + fmt + + vet + + lint + + build + github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar + github.com/Sirupsen/logrus + github.com/docker/libtrust + ... + github.com/yvasiyarov/gorelic + github.com/docker/distribution/registry/handlers + github.com/docker/distribution/cmd/registry + + test + ... + ok github.com/docker/distribution/digest 7.875s + ok github.com/docker/distribution/manifest 0.028s + ok github.com/docker/distribution/notifications 17.322s + ? github.com/docker/distribution/registry [no test files] + ok github.com/docker/distribution/registry/api/v2 0.101s + ? github.com/docker/distribution/registry/auth [no test files] + ok github.com/docker/distribution/registry/auth/silly 0.011s + ... + + /Users/sday/go/src/github.com/docker/distribution/bin/registry + + /Users/sday/go/src/github.com/docker/distribution/bin/registry-api-descriptor-template + + binaries + +The above provides a repeatable build using the contents of the vendored +Godeps directory. This includes formatting, vetting, linting, building, +testing and generating tagged binaries. We can verify this worked by running +the registry binary generated in the "./bin" directory: + + $ ./bin/registry -version + ./bin/registry github.com/docker/distribution v2.0.0-alpha.2-80-g16d8b2c.m + +### Optional build tags + +Optional [build tags](http://golang.org/pkg/go/build/) can be provided using +the environment variable `DOCKER_BUILDTAGS`. diff --git a/vendor/src/github.com/docker/distribution/CHANGELOG.md b/vendor/src/github.com/docker/distribution/CHANGELOG.md new file mode 100644 index 0000000000..3445c090c2 --- /dev/null +++ b/vendor/src/github.com/docker/distribution/CHANGELOG.md @@ -0,0 +1,35 @@ +# Changelog + +## 2.5.0 (2016-06-14) + +### Storage +- Ensure uploads directory is cleaned after upload is commited +- Add ability to cap concurrent operations in filesystem driver +- S3: Add 'us-gov-west-1' to the valid region list +- Swift: Handle ceph not returning Last-Modified header for HEAD requests +- Add redirect middleware + +#### Registry +- Add support for blobAccessController middleware +- Add support for layers from foreign sources +- Remove signature store +- Add support for Let's Encrypt +- Correct yaml key names in configuration + +#### Client +- Add option to get content digest from manifest get + +#### Spec +- Update the auth spec scope grammar to reflect the fact that hostnames are optionally supported +- Clarify API documentation around catalog fetch behavior + +### API +- Support returning HTTP 429 (Too Many Requests) + +### Documentation +- Update auth documentation examples to show "expires in" as int + +### Docker Image +- Use Alpine Linux as base image + + diff --git a/vendor/src/github.com/docker/distribution/MAINTAINERS b/vendor/src/github.com/docker/distribution/MAINTAINERS index 97f415dbfb..bda400150c 100644 --- a/vendor/src/github.com/docker/distribution/MAINTAINERS +++ b/vendor/src/github.com/docker/distribution/MAINTAINERS @@ -32,11 +32,6 @@ Email = "aaron.lehmann@docker.com" GitHub = "aaronlehmann" - [people.brianbland] - Name = "Brian Bland" - Email = "brian.bland@docker.com" - GitHub = "BrianBland" - [people.dmcgowan] Name = "Derek McGowan" Email = "derek@mcgstyle.net" diff --git a/vendor/src/github.com/docker/distribution/README.md b/vendor/src/github.com/docker/distribution/README.md index c21d47243a..d35bcb682d 100644 --- a/vendor/src/github.com/docker/distribution/README.md +++ b/vendor/src/github.com/docker/distribution/README.md @@ -83,7 +83,7 @@ created. For more information see [docker/migrator] Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute issues, fixes, and patches to this project. If you are contributing code, see -the instructions for [building a development environment](docs/building.md). +the instructions for [building a development environment](docs/recipes/building.md). ## Support diff --git a/vendor/src/github.com/docker/distribution/ROADMAP.md b/vendor/src/github.com/docker/distribution/ROADMAP.md index 9cdfa36c92..701127afec 100644 --- a/vendor/src/github.com/docker/distribution/ROADMAP.md +++ b/vendor/src/github.com/docker/distribution/ROADMAP.md @@ -156,7 +156,7 @@ full and understand the problems behind deletes. While, at first glance, implementing deleting seems simple, there are a number mitigating factors that make many solutions not ideal or even pathological in the context of a registry. The following paragraph discuss the background and -approaches that could be applied to a arrive at a solution. +approaches that could be applied to arrive at a solution. The goal of deletes in any system is to remove unused or unneeded data. Only data requested for deletion should be removed and no other data. Removing diff --git a/vendor/src/github.com/docker/distribution/blobs.go b/vendor/src/github.com/docker/distribution/blobs.go index 9f572bfabb..d125330117 100644 --- a/vendor/src/github.com/docker/distribution/blobs.go +++ b/vendor/src/github.com/docker/distribution/blobs.go @@ -127,6 +127,11 @@ type BlobDescriptorService interface { Clear(ctx context.Context, dgst digest.Digest) error } +// BlobDescriptorServiceFactory creates middleware for BlobDescriptorService. +type BlobDescriptorServiceFactory interface { + BlobAccessController(svc BlobDescriptorService) BlobDescriptorService +} + // ReadSeekCloser is the primary reader type for blob data, combining // io.ReadSeeker with io.Closer. type ReadSeekCloser interface { diff --git a/vendor/src/github.com/docker/distribution/manifest/schema2/builder.go b/vendor/src/github.com/docker/distribution/manifest/schema2/builder.go index 44b94eaae9..ec0bf858d1 100644 --- a/vendor/src/github.com/docker/distribution/manifest/schema2/builder.go +++ b/vendor/src/github.com/docker/distribution/manifest/schema2/builder.go @@ -46,6 +46,9 @@ func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) { m.Config, err = mb.bs.Stat(ctx, configDigest) switch err { case nil: + // Override MediaType, since Put always replaces the specified media + // type with application/octet-stream in the descriptor it returns. + m.Config.MediaType = MediaTypeConfig return FromStruct(m) case distribution.ErrBlobUnknown: // nop diff --git a/vendor/src/github.com/docker/distribution/manifests.go b/vendor/src/github.com/docker/distribution/manifests.go index 3bf912a659..2ac7c8f211 100644 --- a/vendor/src/github.com/docker/distribution/manifests.go +++ b/vendor/src/github.com/docker/distribution/manifests.go @@ -61,12 +61,6 @@ type ManifestEnumerator interface { Enumerate(ctx context.Context, ingester func(digest.Digest) error) error } -// SignaturesGetter provides an interface for getting the signatures of a schema1 manifest. If the digest -// referred to is not a schema1 manifest, an error should be returned. -type SignaturesGetter interface { - GetSignatures(ctx context.Context, manifestDigest digest.Digest) ([]digest.Digest, error) -} - // Describable is an interface for descriptors type Describable interface { Descriptor() Descriptor diff --git a/vendor/src/github.com/docker/distribution/registry/api/errcode/register.go b/vendor/src/github.com/docker/distribution/registry/api/errcode/register.go index 7489e84f7d..d1e8826c6d 100644 --- a/vendor/src/github.com/docker/distribution/registry/api/errcode/register.go +++ b/vendor/src/github.com/docker/distribution/registry/api/errcode/register.go @@ -55,7 +55,7 @@ var ( HTTPStatusCode: http.StatusForbidden, }) - // ErrorCodeUnavailable provides a common error to report unavialability + // ErrorCodeUnavailable provides a common error to report unavailability // of a service or endpoint. ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{ Value: "UNAVAILABLE", @@ -71,10 +71,7 @@ var ( Message: "too many requests", Description: `Returned when a client attempts to contact a service too many times`, - // FIXME: go1.5 doesn't export http.StatusTooManyRequests while - // go1.6 does. Update the hardcoded value to the constant once - // Docker updates golang version to 1.6. - HTTPStatusCode: 429, + HTTPStatusCode: http.StatusTooManyRequests, }) ) diff --git a/vendor/src/github.com/docker/distribution/registry/api/v2/descriptors.go b/vendor/src/github.com/docker/distribution/registry/api/v2/descriptors.go index 582799948a..fc42c1c410 100644 --- a/vendor/src/github.com/docker/distribution/registry/api/v2/descriptors.go +++ b/vendor/src/github.com/docker/distribution/registry/api/v2/descriptors.go @@ -1497,8 +1497,8 @@ var routeDescriptors = []RouteDescriptor{ Description: "Retrieve a sorted, json list of repositories available in the registry.", Requests: []RequestDescriptor{ { - Name: "Catalog Fetch Complete", - Description: "Request an unabridged list of repositories available.", + Name: "Catalog Fetch", + Description: "Request an unabridged list of repositories available. The implementation may impose a maximum limit and return a partial set with pagination links.", Successes: []ResponseDescriptor{ { Description: "Returns the unabridged list of repositories as a json response.", diff --git a/vendor/src/github.com/docker/distribution/registry/client/errors.go b/vendor/src/github.com/docker/distribution/registry/client/errors.go index adbaacf4bb..f73e3c2301 100644 --- a/vendor/src/github.com/docker/distribution/registry/client/errors.go +++ b/vendor/src/github.com/docker/distribution/registry/client/errors.go @@ -11,7 +11,7 @@ import ( "github.com/docker/distribution/registry/api/errcode" ) -// ErrNoErrorsInBody is returned when a HTTP response body parses to an empty +// ErrNoErrorsInBody is returned when an HTTP response body parses to an empty // errcode.Errors slice. var ErrNoErrorsInBody = errors.New("no error details found in HTTP response body") @@ -54,10 +54,7 @@ func parseHTTPErrorResponse(statusCode int, r io.Reader) error { switch statusCode { case http.StatusUnauthorized: return errcode.ErrorCodeUnauthorized.WithMessage(detailsErr.Details) - // FIXME: go1.5 doesn't export http.StatusTooManyRequests while - // go1.6 does. Update the hardcoded value to the constant once - // Docker updates golang version to 1.6. - case 429: + case http.StatusTooManyRequests: return errcode.ErrorCodeTooManyRequests.WithMessage(detailsErr.Details) default: return errcode.ErrorCodeUnknown.WithMessage(detailsErr.Details) diff --git a/vendor/src/github.com/docker/distribution/registry/client/repository.go b/vendor/src/github.com/docker/distribution/registry/client/repository.go index 8cc5f7f9aa..9731255615 100644 --- a/vendor/src/github.com/docker/distribution/registry/client/repository.go +++ b/vendor/src/github.com/docker/distribution/registry/client/repository.go @@ -10,6 +10,7 @@ import ( "net/http" "net/url" "strconv" + "strings" "time" "github.com/docker/distribution" @@ -213,28 +214,35 @@ func (t *tags) All(ctx context.Context) ([]string, error) { return tags, err } - resp, err := t.client.Get(u) - if err != nil { - return tags, err - } - defer resp.Body.Close() - - if SuccessStatus(resp.StatusCode) { - b, err := ioutil.ReadAll(resp.Body) + for { + resp, err := t.client.Get(u) if err != nil { return tags, err } + defer resp.Body.Close() - tagsResponse := struct { - Tags []string `json:"tags"` - }{} - if err := json.Unmarshal(b, &tagsResponse); err != nil { - return tags, err + if SuccessStatus(resp.StatusCode) { + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return tags, err + } + + tagsResponse := struct { + Tags []string `json:"tags"` + }{} + if err := json.Unmarshal(b, &tagsResponse); err != nil { + return tags, err + } + tags = append(tags, tagsResponse.Tags...) + if link := resp.Header.Get("Link"); link != "" { + u = strings.Trim(strings.Split(link, ";")[0], "<>") + } else { + return tags, nil + } + } else { + return tags, HandleErrorResponse(resp) } - tags = tagsResponse.Tags - return tags, nil } - return tags, HandleErrorResponse(resp) } func descriptorFromResponse(response *http.Response) (distribution.Descriptor, error) { @@ -394,11 +402,26 @@ func (o etagOption) Apply(ms distribution.ManifestService) error { return fmt.Errorf("etag options is a client-only option") } +// ReturnContentDigest allows a client to set a the content digest on +// a successful request from the 'Docker-Content-Digest' header. This +// returned digest is represents the digest which the registry uses +// to refer to the content and can be used to delete the content. +func ReturnContentDigest(dgst *digest.Digest) distribution.ManifestServiceOption { + return contentDigestOption{dgst} +} + +type contentDigestOption struct{ digest *digest.Digest } + +func (o contentDigestOption) Apply(ms distribution.ManifestService) error { + return nil +} + func (ms *manifests) Get(ctx context.Context, dgst digest.Digest, options ...distribution.ManifestServiceOption) (distribution.Manifest, error) { var ( digestOrTag string ref reference.Named err error + contentDgst *digest.Digest ) for _, option := range options { @@ -408,6 +431,8 @@ func (ms *manifests) Get(ctx context.Context, dgst digest.Digest, options ...dis if err != nil { return nil, err } + } else if opt, ok := option.(contentDigestOption); ok { + contentDgst = opt.digest } else { err := option.Apply(ms) if err != nil { @@ -450,6 +475,12 @@ func (ms *manifests) Get(ctx context.Context, dgst digest.Digest, options ...dis if resp.StatusCode == http.StatusNotModified { return nil, distribution.ErrManifestNotModified } else if SuccessStatus(resp.StatusCode) { + if contentDgst != nil { + dgst, err := digest.ParseDigest(resp.Header.Get("Docker-Content-Digest")) + if err == nil { + *contentDgst = dgst + } + } mt := resp.Header.Get("Content-Type") body, err := ioutil.ReadAll(resp.Body) diff --git a/vendor/src/github.com/docker/engine-api/client/interface.go b/vendor/src/github.com/docker/engine-api/client/interface.go index 4ad2a5c399..1cadaef56b 100644 --- a/vendor/src/github.com/docker/engine-api/client/interface.go +++ b/vendor/src/github.com/docker/engine-api/client/interface.go @@ -100,11 +100,11 @@ type NodeAPIClient interface { // ServiceAPIClient defines API client methods for the services type ServiceAPIClient interface { - ServiceCreate(ctx context.Context, service swarm.ServiceSpec, headers map[string][]string) (types.ServiceCreateResponse, error) + ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) ServiceInspectWithRaw(ctx context.Context, serviceID string) (swarm.Service, []byte, error) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) ServiceRemove(ctx context.Context, serviceID string) error - ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, headers map[string][]string) error + ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) error TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) } diff --git a/vendor/src/github.com/docker/engine-api/client/service_create.go b/vendor/src/github.com/docker/engine-api/client/service_create.go index 4153e04d57..7349a984e7 100644 --- a/vendor/src/github.com/docker/engine-api/client/service_create.go +++ b/vendor/src/github.com/docker/engine-api/client/service_create.go @@ -9,7 +9,15 @@ import ( ) // ServiceCreate creates a new Service. -func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, headers map[string][]string) (types.ServiceCreateResponse, error) { +func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) { + var headers map[string][]string + + if options.EncodedRegistryAuth != "" { + headers = map[string][]string{ + "X-Registry-Auth": []string{options.EncodedRegistryAuth}, + } + } + var response types.ServiceCreateResponse resp, err := cli.post(ctx, "/services/create", nil, service, headers) if err != nil { diff --git a/vendor/src/github.com/docker/engine-api/client/service_update.go b/vendor/src/github.com/docker/engine-api/client/service_update.go index 4281b1e2c1..ee8b46126b 100644 --- a/vendor/src/github.com/docker/engine-api/client/service_update.go +++ b/vendor/src/github.com/docker/engine-api/client/service_update.go @@ -4,14 +4,26 @@ import ( "net/url" "strconv" + "github.com/docker/engine-api/types" "github.com/docker/engine-api/types/swarm" "golang.org/x/net/context" ) // ServiceUpdate updates a Service. -func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, headers map[string][]string) error { - query := url.Values{} +func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) error { + var ( + headers map[string][]string + query = url.Values{} + ) + + if options.EncodedRegistryAuth != "" { + headers = map[string][]string{ + "X-Registry-Auth": []string{options.EncodedRegistryAuth}, + } + } + query.Set("version", strconv.FormatUint(version.Index, 10)) + resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers) ensureReaderClosed(resp) return err diff --git a/vendor/src/github.com/docker/engine-api/types/client.go b/vendor/src/github.com/docker/engine-api/types/client.go index b7993b74f0..def3f06197 100644 --- a/vendor/src/github.com/docker/engine-api/types/client.go +++ b/vendor/src/github.com/docker/engine-api/types/client.go @@ -246,6 +246,15 @@ type NodeListOptions struct { Filter filters.Args } +// ServiceCreateOptions contains the options to use when creating a service. +type ServiceCreateOptions struct { + // EncodedRegistryAuth is the encoded registry authorization credentials to + // use when updating the service. + // + // This field follows the format of the X-Registry-Auth header. + EncodedRegistryAuth string +} + // ServiceCreateResponse contains the information returned to a client // on the creation of a new service. type ServiceCreateResponse struct { @@ -253,6 +262,19 @@ type ServiceCreateResponse struct { ID string } +// ServiceUpdateOptions contains the options to be used for updating services. +type ServiceUpdateOptions struct { + // EncodedRegistryAuth is the encoded registry authorization credentials to + // use when updating the service. + // + // This field follows the format of the X-Registry-Auth header. + EncodedRegistryAuth string + + // TODO(stevvooe): Consider moving the version parameter of ServiceUpdate + // into this field. While it does open API users up to racy writes, most + // users may not need that level of consistency in practice. +} + // ServiceListOptions holds parameters to list services with. type ServiceListOptions struct { Filter filters.Args diff --git a/vendor/src/github.com/docker/engine-api/types/container/host_config.go b/vendor/src/github.com/docker/engine-api/types/container/host_config.go index 8e653fcf8d..a9ff755b04 100644 --- a/vendor/src/github.com/docker/engine-api/types/container/host_config.go +++ b/vendor/src/github.com/docker/engine-api/types/container/host_config.go @@ -308,8 +308,8 @@ type HostConfig struct { UTSMode UTSMode // UTS namespace to use for the container UsernsMode UsernsMode // The user namespace to use for the container ShmSize int64 // Total shm memory usage - Sysctls map[string]string `json:",omitempty"` // List of Namespaced sysctls used for the container - Runtime string `json:"runtime,omitempty"` // Runtime to use with this container + Sysctls map[string]string `json:",omitempty"` // List of Namespaced sysctls used for the container + Runtime string `json:",omitempty"` // Runtime to use with this container // Applicable to Windows ConsoleSize [2]int // Initial console size diff --git a/vendor/src/github.com/docker/engine-api/types/swarm/container.go b/vendor/src/github.com/docker/engine-api/types/swarm/container.go index 40718b247b..29f2e8a647 100644 --- a/vendor/src/github.com/docker/engine-api/types/swarm/container.go +++ b/vendor/src/github.com/docker/engine-api/types/swarm/container.go @@ -30,7 +30,7 @@ type Mount struct { Type MountType `json:",omitempty"` Source string `json:",omitempty"` Target string `json:",omitempty"` - Writable bool `json:",omitempty"` + ReadOnly bool `json:",omitempty"` BindOptions *BindOptions `json:",omitempty"` VolumeOptions *VolumeOptions `json:",omitempty"` @@ -61,7 +61,7 @@ type BindOptions struct { // VolumeOptions represents the options for a mount of type volume. type VolumeOptions struct { - Populate bool `json:",omitempty"` + NoCopy bool `json:",omitempty"` Labels map[string]string `json:",omitempty"` DriverConfig *Driver `json:",omitempty"` } diff --git a/vendor/src/github.com/docker/engine-api/types/swarm/network.go b/vendor/src/github.com/docker/engine-api/types/swarm/network.go index 3715a114ed..84804da2fb 100644 --- a/vendor/src/github.com/docker/engine-api/types/swarm/network.go +++ b/vendor/src/github.com/docker/engine-api/types/swarm/network.go @@ -67,13 +67,13 @@ type NetworkSpec struct { IPAMOptions *IPAMOptions `json:",omitempty"` } -// NetworkAttachmentConfig represents the configuration of a network attachement. +// NetworkAttachmentConfig represents the configuration of a network attachment. type NetworkAttachmentConfig struct { Target string `json:",omitempty"` Aliases []string `json:",omitempty"` } -// NetworkAttachment represents a network attchement. +// NetworkAttachment represents a network attachment. type NetworkAttachment struct { Network Network `json:",omitempty"` Addresses []string `json:",omitempty"` diff --git a/vendor/src/github.com/docker/engine-api/types/swarm/swarm.go b/vendor/src/github.com/docker/engine-api/types/swarm/swarm.go index da110fc7e1..0a0685d0f1 100644 --- a/vendor/src/github.com/docker/engine-api/types/swarm/swarm.go +++ b/vendor/src/github.com/docker/engine-api/types/swarm/swarm.go @@ -18,6 +18,14 @@ type Spec struct { Raft RaftConfig `json:",omitempty"` Dispatcher DispatcherConfig `json:",omitempty"` CAConfig CAConfig `json:",omitempty"` + + // DefaultLogDriver sets the log driver to use at task creation time if + // unspecified by a task. + // + // Updating this value will only have an affect on new tasks. Old tasks + // will continue use their previously configured log driver until + // recreated. + DefaultLogDriver *Driver `json:",omitempty"` } // AcceptancePolicy represents the list of policies. diff --git a/vendor/src/github.com/docker/engine-api/types/swarm/task.go b/vendor/src/github.com/docker/engine-api/types/swarm/task.go index ca5fcdef6f..fa8228a497 100644 --- a/vendor/src/github.com/docker/engine-api/types/swarm/task.go +++ b/vendor/src/github.com/docker/engine-api/types/swarm/task.go @@ -54,6 +54,11 @@ type TaskSpec struct { Resources *ResourceRequirements `json:",omitempty"` RestartPolicy *RestartPolicy `json:",omitempty"` Placement *Placement `json:",omitempty"` + + // LogDriver specifies the LogDriver to use for tasks created from this + // spec. If not present, the one on cluster default on swarm.Spec will be + // used, finally falling back to the engine default if not specified. + LogDriver *Driver `json:",omitempty"` } // Resources represents resources (CPU/Memory). @@ -88,7 +93,7 @@ const ( // RestartPolicyConditionNone NONE RestartPolicyConditionNone RestartPolicyCondition = "none" // RestartPolicyConditionOnFailure ON_FAILURE - RestartPolicyConditionOnFailure RestartPolicyCondition = "on_failure" + RestartPolicyConditionOnFailure RestartPolicyCondition = "on-failure" // RestartPolicyConditionAny ANY RestartPolicyConditionAny RestartPolicyCondition = "any" ) diff --git a/vendor/src/github.com/docker/engine-api/types/types.go b/vendor/src/github.com/docker/engine-api/types/types.go index c70d1c8cbb..3cc8db8c11 100644 --- a/vendor/src/github.com/docker/engine-api/types/types.go +++ b/vendor/src/github.com/docker/engine-api/types/types.go @@ -444,12 +444,12 @@ type VolumeCreateRequest struct { // NetworkResource is the body of the "get network" http response message type NetworkResource struct { Name string // Name is the requested name of the network - ID string `json:"Id"` // ID uniquely indentifies a network on a single machine + ID string `json:"Id"` // ID uniquely identifies a network on a single machine Scope string // Scope describes the level at which the network exists (e.g. `global` for cluster-wide or `local` for machine level) Driver string // Driver is the Driver name used to create the network (e.g. `bridge`, `overlay`) EnableIPv6 bool // EnableIPv6 represents whether to enable IPv6 IPAM network.IPAM // IPAM is the network's IP Address Management - Internal bool // Internal respresents if the network is used internal only + Internal bool // Internal represents if the network is used internal only Containers map[string]EndpointResource // Containers contains endpoints belonging to the network Options map[string]string // Options holds the network specific options to use for when creating the network Labels map[string]string // Labels holds metadata specific to the network being created diff --git a/vendor/src/github.com/docker/libnetwork/Makefile b/vendor/src/github.com/docker/libnetwork/Makefile index 899ca4b9be..a130dc656d 100644 --- a/vendor/src/github.com/docker/libnetwork/Makefile +++ b/vendor/src/github.com/docker/libnetwork/Makefile @@ -7,6 +7,7 @@ docker = docker run --rm -it ${dockerargs} $$EXTRA_ARGS ${container_env} ${build ciargs = -e CIRCLECI -e "COVERALLS_TOKEN=$$COVERALLS_TOKEN" -e "INSIDECONTAINER=-incontainer=true" cidocker = docker run ${dockerargs} ${ciargs} $$EXTRA_ARGS ${container_env} ${build_image} CROSS_PLATFORMS = linux/amd64 linux/386 linux/arm windows/amd64 +export PATH := $(CURDIR)/bin:$(PATH) all: ${build_image}.created build check integration-tests clean @@ -24,10 +25,11 @@ build: ${build_image}.created build-local: @mkdir -p "bin" $(shell which godep) go build -tags experimental -o "bin/dnet" ./cmd/dnet + $(shell which godep) go build -o "bin/docker-proxy" ./cmd/proxy clean: @if [ -d bin ]; then \ - echo "Removing dnet binaries"; \ + echo "Removing dnet and proxy binaries"; \ rm -rf bin; \ fi @@ -41,6 +43,7 @@ cross: ${build_image}.created cross-local: $(shell which godep) go build -o "bin/dnet-$$GOOS-$$GOARCH" ./cmd/dnet + $(shell which godep) go build -o "bin/docker-proxy-$$GOOS-$$GOARCH" ./cmd/proxy check: ${build_image}.created @${docker} ./wrapmake.sh check-local @@ -102,4 +105,4 @@ circle-ci-check: ${build_image}.created circle-ci-build: ${build_image}.created @${cidocker} make build-local -circle-ci: circle-ci-check circle-ci-cross circle-ci-build integration-tests +circle-ci: circle-ci-build circle-ci-check circle-ci-cross integration-tests diff --git a/vendor/src/github.com/docker/libnetwork/cmd/proxy/main.go b/vendor/src/github.com/docker/libnetwork/cmd/proxy/main.go new file mode 100644 index 0000000000..fb68796148 --- /dev/null +++ b/vendor/src/github.com/docker/libnetwork/cmd/proxy/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "flag" + "fmt" + "log" + "net" + "os" + "os/signal" + "syscall" +) + +func main() { + f := os.NewFile(3, "signal-parent") + host, container := parseHostContainerAddrs() + + p, err := NewProxy(host, container) + if err != nil { + fmt.Fprintf(f, "1\n%s", err) + f.Close() + os.Exit(1) + } + go handleStopSignals(p) + fmt.Fprint(f, "0\n") + f.Close() + + // Run will block until the proxy stops + p.Run() +} + +// parseHostContainerAddrs parses the flags passed on reexec to create the TCP or UDP +// net.Addrs to map the host and container ports +func parseHostContainerAddrs() (host net.Addr, container net.Addr) { + var ( + proto = flag.String("proto", "tcp", "proxy protocol") + hostIP = flag.String("host-ip", "", "host ip") + hostPort = flag.Int("host-port", -1, "host port") + containerIP = flag.String("container-ip", "", "container ip") + containerPort = flag.Int("container-port", -1, "container port") + ) + + flag.Parse() + + switch *proto { + case "tcp": + host = &net.TCPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort} + container = &net.TCPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort} + case "udp": + host = &net.UDPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort} + container = &net.UDPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort} + default: + log.Fatalf("unsupported protocol %s", *proto) + } + + return host, container +} + +func handleStopSignals(p Proxy) { + s := make(chan os.Signal, 10) + signal.Notify(s, os.Interrupt, syscall.SIGTERM) + + for range s { + p.Close() + + os.Exit(0) + } +} diff --git a/pkg/proxy/proxy.go b/vendor/src/github.com/docker/libnetwork/cmd/proxy/proxy.go similarity index 92% rename from pkg/proxy/proxy.go rename to vendor/src/github.com/docker/libnetwork/cmd/proxy/proxy.go index 4e24e5f6a8..44dd177bb6 100644 --- a/pkg/proxy/proxy.go +++ b/vendor/src/github.com/docker/libnetwork/cmd/proxy/proxy.go @@ -1,6 +1,6 @@ -// Package proxy provides a network Proxy interface and implementations for TCP +// docker-proxy provides a network Proxy interface and implementations for TCP // and UDP. -package proxy +package main import ( "fmt" diff --git a/pkg/proxy/stub_proxy.go b/vendor/src/github.com/docker/libnetwork/cmd/proxy/stub_proxy.go similarity index 97% rename from pkg/proxy/stub_proxy.go rename to vendor/src/github.com/docker/libnetwork/cmd/proxy/stub_proxy.go index 571749e467..95e0e36352 100644 --- a/pkg/proxy/stub_proxy.go +++ b/vendor/src/github.com/docker/libnetwork/cmd/proxy/stub_proxy.go @@ -1,4 +1,4 @@ -package proxy +package main import ( "net" diff --git a/pkg/proxy/tcp_proxy.go b/vendor/src/github.com/docker/libnetwork/cmd/proxy/tcp_proxy.go similarity index 99% rename from pkg/proxy/tcp_proxy.go rename to vendor/src/github.com/docker/libnetwork/cmd/proxy/tcp_proxy.go index 8f42580c1b..514b778773 100644 --- a/pkg/proxy/tcp_proxy.go +++ b/vendor/src/github.com/docker/libnetwork/cmd/proxy/tcp_proxy.go @@ -1,4 +1,4 @@ -package proxy +package main import ( "io" diff --git a/pkg/proxy/udp_proxy.go b/vendor/src/github.com/docker/libnetwork/cmd/proxy/udp_proxy.go similarity index 99% rename from pkg/proxy/udp_proxy.go rename to vendor/src/github.com/docker/libnetwork/cmd/proxy/udp_proxy.go index b8375c374f..2b895ae9d4 100644 --- a/pkg/proxy/udp_proxy.go +++ b/vendor/src/github.com/docker/libnetwork/cmd/proxy/udp_proxy.go @@ -1,4 +1,4 @@ -package proxy +package main import ( "encoding/binary" diff --git a/vendor/src/github.com/docker/libnetwork/controller.go b/vendor/src/github.com/docker/libnetwork/controller.go index 9108d87844..216f7ccd10 100644 --- a/vendor/src/github.com/docker/libnetwork/controller.go +++ b/vendor/src/github.com/docker/libnetwork/controller.go @@ -193,6 +193,11 @@ func New(cfgOptions ...config.Option) (NetworkController, error) { return nil, err } } + + if err = initIPAMDrivers(drvRegistry, nil, c.getStore(datastore.GlobalScope)); err != nil { + return nil, err + } + c.drvRegistry = drvRegistry if c.cfg != nil && c.cfg.Cluster.Watcher != nil { diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go index c75ec9f4f9..d2b1d24829 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go @@ -330,7 +330,7 @@ func (c *networkConfiguration) conflictsWithNetworks(id string, others []*bridge // bridges. This could not be completely caught by the config conflict // check, because networks which config does not specify the AddressIPv4 // get their address and subnet selected by the driver (see electBridgeIPv4()) - if c.AddressIPv4 != nil { + if c.AddressIPv4 != nil && nwBridge.bridgeIPv4 != nil { if nwBridge.bridgeIPv4.Contains(c.AddressIPv4.IP) || c.AddressIPv4.Contains(nwBridge.bridgeIPv4.IP) { return types.ForbiddenErrorf("conflicts with network %s (%s) by ip network", nwID, nwConfig.BridgeName) diff --git a/vendor/src/github.com/docker/libnetwork/drivers_ipam.go b/vendor/src/github.com/docker/libnetwork/drivers_ipam.go new file mode 100644 index 0000000000..be0204ab10 --- /dev/null +++ b/vendor/src/github.com/docker/libnetwork/drivers_ipam.go @@ -0,0 +1,23 @@ +package libnetwork + +import ( + "github.com/docker/libnetwork/drvregistry" + "github.com/docker/libnetwork/ipamapi" + builtinIpam "github.com/docker/libnetwork/ipams/builtin" + nullIpam "github.com/docker/libnetwork/ipams/null" + remoteIpam "github.com/docker/libnetwork/ipams/remote" +) + +func initIPAMDrivers(r *drvregistry.DrvRegistry, lDs, gDs interface{}) error { + for _, fn := range [](func(ipamapi.Callback, interface{}, interface{}) error){ + builtinIpam.Init, + remoteIpam.Init, + nullIpam.Init, + } { + if err := fn(r, lDs, gDs); err != nil { + return err + } + } + + return nil +} diff --git a/vendor/src/github.com/docker/libnetwork/drvregistry/drvregistry.go b/vendor/src/github.com/docker/libnetwork/drvregistry/drvregistry.go index f12da15c0b..d2cf781193 100644 --- a/vendor/src/github.com/docker/libnetwork/drvregistry/drvregistry.go +++ b/vendor/src/github.com/docker/libnetwork/drvregistry/drvregistry.go @@ -8,10 +8,6 @@ import ( "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/ipamapi" "github.com/docker/libnetwork/types" - - builtinIpam "github.com/docker/libnetwork/ipams/builtin" - nullIpam "github.com/docker/libnetwork/ipams/null" - remoteIpam "github.com/docker/libnetwork/ipams/remote" ) type driverData struct { @@ -64,10 +60,6 @@ func New(lDs, gDs interface{}, dfn DriverNotifyFunc, ifn IPAMNotifyFunc) (*DrvRe ifn: ifn, } - if err := r.initIPAMs(lDs, gDs); err != nil { - return nil, err - } - return r, nil } @@ -157,20 +149,6 @@ func (r *DrvRegistry) IPAMDefaultAddressSpaces(name string) (string, string, err return i.defaultLocalAddressSpace, i.defaultGlobalAddressSpace, nil } -func (r *DrvRegistry) initIPAMs(lDs, gDs interface{}) error { - for _, fn := range [](func(ipamapi.Callback, interface{}, interface{}) error){ - builtinIpam.Init, - remoteIpam.Init, - nullIpam.Init, - } { - if err := fn(r, nil, gDs); err != nil { - return err - } - } - - return nil -} - // RegisterDriver registers the network driver when it gets discovered. func (r *DrvRegistry) RegisterDriver(ntype string, driver driverapi.Driver, capability driverapi.Capability) error { if strings.TrimSpace(ntype) == "" { diff --git a/vendor/src/github.com/docker/libnetwork/etchosts/etchosts.go b/vendor/src/github.com/docker/libnetwork/etchosts/etchosts.go index 4526532593..d55298af45 100644 --- a/vendor/src/github.com/docker/libnetwork/etchosts/etchosts.go +++ b/vendor/src/github.com/docker/libnetwork/etchosts/etchosts.go @@ -119,25 +119,34 @@ func Add(path string, recs []Record) error { return nil } - f, err := os.Open(path) + b, err := mergeRecords(path, recs) if err != nil { return err } + return ioutil.WriteFile(path, b, 0644) +} + +func mergeRecords(path string, recs []Record) ([]byte, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + content := bytes.NewBuffer(nil) - _, err = content.ReadFrom(f) - if err != nil { - return err + if _, err := content.ReadFrom(f); err != nil { + return nil, err } for _, r := range recs { if _, err := r.WriteTo(content); err != nil { - return err + return nil, err } } - return ioutil.WriteFile(path, content.Bytes(), 0644) + return content.Bytes(), nil } // Delete deletes an arbitrary number of Records already existing in /etc/hosts file diff --git a/vendor/src/github.com/docker/libnetwork/network.go b/vendor/src/github.com/docker/libnetwork/network.go index 6063ef085b..09a63615ee 100644 --- a/vendor/src/github.com/docker/libnetwork/network.go +++ b/vendor/src/github.com/docker/libnetwork/network.go @@ -320,6 +320,7 @@ func (n *network) CopyTo(o datastore.KVObject) error { dstN.id = n.id dstN.networkType = n.networkType dstN.scope = n.scope + dstN.dynamic = n.dynamic dstN.ipamType = n.ipamType dstN.enableIPv6 = n.enableIPv6 dstN.persist = n.persist @@ -706,7 +707,7 @@ func (n *network) driver(load bool) (driverapi.Driver, error) { if cap != nil { n.scope = cap.DataScope } - if c.isAgent() { + if c.isAgent() || n.dynamic { // If we are running in agent mode then all networks // in libnetwork are local scope regardless of the // backing driver. diff --git a/vendor/src/github.com/docker/libnetwork/networkdb/cluster.go b/vendor/src/github.com/docker/libnetwork/networkdb/cluster.go index e8340401e5..baf72bf014 100644 --- a/vendor/src/github.com/docker/libnetwork/networkdb/cluster.go +++ b/vendor/src/github.com/docker/libnetwork/networkdb/cluster.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/memberlist" ) -const reapInterval = 2 * time.Second +const reapInterval = 30 * time.Second type logWriter struct{} @@ -360,6 +360,10 @@ func (nDB *NetworkDB) bulkSync(nid string, nodes []string, all bool) ([]string, nodes = nDB.mRandomNodes(1, nodes) } + if len(nodes) == 0 { + return nil, nil + } + logrus.Debugf("%s: Initiating bulk sync with nodes %v", nDB.config.NodeName, nodes) var err error var networks []string diff --git a/vendor/src/github.com/docker/libnetwork/networkdb/delegate.go b/vendor/src/github.com/docker/libnetwork/networkdb/delegate.go index afe078b997..216027905f 100644 --- a/vendor/src/github.com/docker/libnetwork/networkdb/delegate.go +++ b/vendor/src/github.com/docker/libnetwork/networkdb/delegate.go @@ -130,6 +130,11 @@ func (nDB *NetworkDB) handleTableMessage(buf []byte, isBulkSync bool) { return } + // Ignore messages that this node generated. + if tEvent.NodeName == nDB.config.NodeName { + return + } + // Do not rebroadcast a bulk sync if rebroadcast := nDB.handleTableEvent(&tEvent); rebroadcast && !isBulkSync { var err error diff --git a/vendor/src/github.com/docker/libnetwork/portmapper/mapper.go b/vendor/src/github.com/docker/libnetwork/portmapper/mapper.go index d125fa8d4b..0bf7630557 100644 --- a/vendor/src/github.com/docker/libnetwork/portmapper/mapper.go +++ b/vendor/src/github.com/docker/libnetwork/portmapper/mapper.go @@ -90,7 +90,10 @@ func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart, } if useProxy { - m.userlandProxy = newProxy(proto, hostIP, allocatedHostPort, container.(*net.TCPAddr).IP, container.(*net.TCPAddr).Port) + m.userlandProxy, err = newProxy(proto, hostIP, allocatedHostPort, container.(*net.TCPAddr).IP, container.(*net.TCPAddr).Port) + if err != nil { + return nil, err + } } else { m.userlandProxy = newDummyProxy(proto, hostIP, allocatedHostPort) } @@ -107,7 +110,10 @@ func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart, } if useProxy { - m.userlandProxy = newProxy(proto, hostIP, allocatedHostPort, container.(*net.UDPAddr).IP, container.(*net.UDPAddr).Port) + m.userlandProxy, err = newProxy(proto, hostIP, allocatedHostPort, container.(*net.UDPAddr).IP, container.(*net.UDPAddr).Port) + if err != nil { + return nil, err + } } else { m.userlandProxy = newDummyProxy(proto, hostIP, allocatedHostPort) } diff --git a/vendor/src/github.com/docker/libnetwork/portmapper/mock_proxy.go b/vendor/src/github.com/docker/libnetwork/portmapper/mock_proxy.go index 29b1605889..587026f9ce 100644 --- a/vendor/src/github.com/docker/libnetwork/portmapper/mock_proxy.go +++ b/vendor/src/github.com/docker/libnetwork/portmapper/mock_proxy.go @@ -2,8 +2,8 @@ package portmapper import "net" -func newMockProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.IP, containerPort int) userlandProxy { - return &mockProxyCommand{} +func newMockProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.IP, containerPort int) (userlandProxy, error) { + return &mockProxyCommand{}, nil } type mockProxyCommand struct { diff --git a/vendor/src/github.com/docker/libnetwork/portmapper/proxy.go b/vendor/src/github.com/docker/libnetwork/portmapper/proxy.go index ddde2744c2..25a341a98f 100644 --- a/vendor/src/github.com/docker/libnetwork/portmapper/proxy.go +++ b/vendor/src/github.com/docker/libnetwork/portmapper/proxy.go @@ -1,29 +1,19 @@ package portmapper import ( - "flag" "fmt" "io" "io/ioutil" - "log" "net" "os" "os/exec" - "os/signal" "strconv" "syscall" "time" - - "github.com/docker/docker/pkg/proxy" - "github.com/docker/docker/pkg/reexec" ) const userlandProxyCommandName = "docker-proxy" -func init() { - reexec.Register(userlandProxyCommandName, execProxy) -} - type userlandProxy interface { Start() error Stop() error @@ -35,66 +25,15 @@ type proxyCommand struct { cmd *exec.Cmd } -// execProxy is the reexec function that is registered to start the userland proxies -func execProxy() { - f := os.NewFile(3, "signal-parent") - host, container := parseHostContainerAddrs() +func newProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.IP, containerPort int) (userlandProxy, error) { + cmd, err := exec.LookPath(userlandProxyCommandName) - p, err := proxy.NewProxy(host, container) if err != nil { - fmt.Fprintf(f, "1\n%s", err) - f.Close() - os.Exit(1) - } - go handleStopSignals(p) - fmt.Fprint(f, "0\n") - f.Close() - - // Run will block until the proxy stops - p.Run() -} - -// parseHostContainerAddrs parses the flags passed on reexec to create the TCP or UDP -// net.Addrs to map the host and container ports -func parseHostContainerAddrs() (host net.Addr, container net.Addr) { - var ( - proto = flag.String("proto", "tcp", "proxy protocol") - hostIP = flag.String("host-ip", "", "host ip") - hostPort = flag.Int("host-port", -1, "host port") - containerIP = flag.String("container-ip", "", "container ip") - containerPort = flag.Int("container-port", -1, "container port") - ) - - flag.Parse() - - switch *proto { - case "tcp": - host = &net.TCPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort} - container = &net.TCPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort} - case "udp": - host = &net.UDPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort} - container = &net.UDPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort} - default: - log.Fatalf("unsupported protocol %s", *proto) + return nil, err } - return host, container -} - -func handleStopSignals(p proxy.Proxy) { - s := make(chan os.Signal, 10) - signal.Notify(s, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP) - - for range s { - p.Close() - - os.Exit(0) - } -} - -func newProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.IP, containerPort int) userlandProxy { args := []string{ - userlandProxyCommandName, + cmd, "-proto", proto, "-host-ip", hostIP.String(), "-host-port", strconv.Itoa(hostPort), @@ -104,13 +43,13 @@ func newProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net. return &proxyCommand{ cmd: &exec.Cmd{ - Path: reexec.Self(), + Path: cmd, Args: args, SysProcAttr: &syscall.SysProcAttr{ Pdeathsig: syscall.SIGTERM, // send a sigterm to the proxy if the daemon process dies }, }, - } + }, nil } func (p *proxyCommand) Start() error { diff --git a/vendor/src/github.com/docker/libnetwork/sandbox_dns_unix.go b/vendor/src/github.com/docker/libnetwork/sandbox_dns_unix.go index 735708563f..6b70cb7a1b 100644 --- a/vendor/src/github.com/docker/libnetwork/sandbox_dns_unix.go +++ b/vendor/src/github.com/docker/libnetwork/sandbox_dns_unix.go @@ -275,7 +275,15 @@ func (sb *sandbox) updateDNS(ipv6Enabled bool) error { if err != nil { return err } - if err = ioutil.WriteFile(tmpHashFile.Name(), []byte(newRC.Hash), filePerm); err != nil { + if err = tmpHashFile.Chmod(filePerm); err != nil { + tmpHashFile.Close() + return err + } + _, err = tmpHashFile.Write([]byte(newRC.Hash)) + if err1 := tmpHashFile.Close(); err == nil { + err = err1 + } + if err != nil { return err } return os.Rename(tmpHashFile.Name(), hashFile) diff --git a/vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go b/vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go index 898cedd2b4..a57bb8e371 100644 --- a/vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go +++ b/vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go @@ -135,6 +135,8 @@ func (c *controller) acceptClientConnections(sock string, l net.Listener) { continue } go func() { + defer conn.Close() + err := c.processExternalKey(conn) ret := success if err != nil { diff --git a/vendor/src/github.com/docker/swarmkit/agent/agent.go b/vendor/src/github.com/docker/swarmkit/agent/agent.go index db349f1e36..2933a268d7 100644 --- a/vendor/src/github.com/docker/swarmkit/agent/agent.go +++ b/vendor/src/github.com/docker/swarmkit/agent/agent.go @@ -195,6 +195,13 @@ func (a *Agent) run(ctx context.Context) { log.G(ctx).WithError(err).Error("agent: closing session failed") } sessionq = nil + // if we're here before <-registered, do nothing for that event + registered = nil + + // Bounce the connection. + if a.config.Picker != nil { + a.config.Picker.Reset() + } case <-session.closed: log.G(ctx).Debugf("agent: rebuild session") diff --git a/vendor/src/github.com/docker/swarmkit/agent/config.go b/vendor/src/github.com/docker/swarmkit/agent/config.go index 589b56b6bd..74da752219 100644 --- a/vendor/src/github.com/docker/swarmkit/agent/config.go +++ b/vendor/src/github.com/docker/swarmkit/agent/config.go @@ -19,9 +19,15 @@ type Config struct { // updated with managers weights as observed by the agent. Managers picker.Remotes - // Conn specifies the client connection Agent will use + // Conn specifies the client connection Agent will use. Conn *grpc.ClientConn + // Picker is the picker used by Conn. + // TODO(aaronl): This is only part of the config to allow resetting the + // GRPC connection. This should be refactored to address the coupling + // between Conn and Picker. + Picker *picker.Picker + // Executor specifies the executor to use for the agent. Executor exec.Executor diff --git a/vendor/src/github.com/docker/swarmkit/agent/node.go b/vendor/src/github.com/docker/swarmkit/agent/node.go index fd50e4b740..5d637abe1e 100644 --- a/vendor/src/github.com/docker/swarmkit/agent/node.go +++ b/vendor/src/github.com/docker/swarmkit/agent/node.go @@ -375,8 +375,9 @@ func (n *Node) runAgent(ctx context.Context, db *bolt.DB, creds credentials.Tran if ctx.Err() != nil { return ctx.Err() } + picker := picker.NewPicker(n.remotes, manager.Addr) conn, err := grpc.Dial(manager.Addr, - grpc.WithPicker(picker.NewPicker(n.remotes, manager.Addr)), + grpc.WithPicker(picker), grpc.WithTransportCredentials(creds), grpc.WithBackoffMaxDelay(maxSessionFailureBackoff)) if err != nil { @@ -389,6 +390,7 @@ func (n *Node) runAgent(ctx context.Context, db *bolt.DB, creds credentials.Tran Executor: n.config.Executor, DB: db, Conn: conn, + Picker: picker, NotifyRoleChange: n.roleChangeReq, }) if err != nil { @@ -562,6 +564,7 @@ func (n *Node) initManagerConnection(ctx context.Context, ready chan<- struct{}) for { s, err := conn.WaitForStateChange(ctx, state) if err != nil { + n.setControlSocket(nil) return err } if s == grpc.Ready { diff --git a/vendor/src/github.com/docker/swarmkit/agent/session.go b/vendor/src/github.com/docker/swarmkit/agent/session.go index 39fc64e444..0375e1c5bb 100644 --- a/vendor/src/github.com/docker/swarmkit/agent/session.go +++ b/vendor/src/github.com/docker/swarmkit/agent/session.go @@ -12,6 +12,8 @@ import ( "google.golang.org/grpc/codes" ) +const dispatcherRPCTimeout = 5 * time.Second + var ( errSessionDisconnect = errors.New("agent: session disconnect") // instructed to disconnect errSessionClosed = errors.New("agent: session closed") @@ -88,16 +90,39 @@ func (s *session) start(ctx context.Context) error { description.Hostname = s.agent.config.Hostname } - stream, err := client.Session(ctx, &api.SessionRequest{ - Description: description, - }) - if err != nil { - return err - } + errChan := make(chan error, 1) + var ( + msg *api.SessionMessage + stream api.Dispatcher_SessionClient + ) + // Note: we don't defer cancellation of this context, because the + // streaming RPC is used after this function returned. We only cancel + // it in the timeout case to make sure the goroutine completes. + sessionCtx, cancelSession := context.WithCancel(ctx) - msg, err := stream.Recv() - if err != nil { - return err + // Need to run Session in a goroutine since there's no way to set a + // timeout for an individual Recv call in a stream. + go func() { + stream, err = client.Session(sessionCtx, &api.SessionRequest{ + Description: description, + }) + if err != nil { + errChan <- err + return + } + + msg, err = stream.Recv() + errChan <- err + }() + + select { + case err := <-errChan: + if err != nil { + return err + } + case <-time.After(dispatcherRPCTimeout): + cancelSession() + return errors.New("session initiation timed out") } s.sessionID = msg.SessionID @@ -115,9 +140,11 @@ func (s *session) heartbeat(ctx context.Context) error { for { select { case <-heartbeat.C: - resp, err := client.Heartbeat(ctx, &api.HeartbeatRequest{ + heartbeatCtx, cancel := context.WithTimeout(ctx, dispatcherRPCTimeout) + resp, err := client.Heartbeat(heartbeatCtx, &api.HeartbeatRequest{ SessionID: s.sessionID, }) + cancel() if err != nil { if grpc.Code(err) == codes.NotFound { err = errNodeNotRegistered diff --git a/vendor/src/github.com/docker/swarmkit/api/objects.pb.go b/vendor/src/github.com/docker/swarmkit/api/objects.pb.go index 5a9ce55423..c3be1c3124 100644 --- a/vendor/src/github.com/docker/swarmkit/api/objects.pb.go +++ b/vendor/src/github.com/docker/swarmkit/api/objects.pb.go @@ -159,6 +159,15 @@ type Task struct { // A copy of runtime state of service endpoint from Service // object to be distributed to agents as part of the task. Endpoint *Endpoint `protobuf:"bytes,12,opt,name=endpoint" json:"endpoint,omitempty"` + // LogDriver specifies the selected log driver to use for the task. Agent + // processes should always favor the value in this field. + // + // If present in the TaskSpec, this will be a copy of that value. The + // orchestrator may choose to insert a value here, which should be honored, + // such a cluster default or policy-based value. + // + // If not present, the daemon's default will be used. + LogDriver *Driver `protobuf:"bytes,13,opt,name=log_driver,json=logDriver" json:"log_driver,omitempty"` } func (m *Task) Reset() { *m = Task{} } @@ -334,6 +343,7 @@ func (m *Task) Copy() *Task { Status: *m.Status.Copy(), DesiredState: m.DesiredState, Endpoint: m.Endpoint.Copy(), + LogDriver: m.LogDriver.Copy(), } if m.Networks != nil { @@ -498,7 +508,7 @@ func (this *Task) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 16) + s := make([]string, 0, 17) s = append(s, "&api.Task{") s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") s = append(s, "Meta: "+strings.Replace(this.Meta.GoString(), `&`, ``, 1)+",\n") @@ -516,6 +526,9 @@ func (this *Task) GoString() string { if this.Endpoint != nil { s = append(s, "Endpoint: "+fmt.Sprintf("%#v", this.Endpoint)+",\n") } + if this.LogDriver != nil { + s = append(s, "LogDriver: "+fmt.Sprintf("%#v", this.LogDriver)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -962,6 +975,16 @@ func (m *Task) MarshalTo(data []byte) (int, error) { } i += n20 } + if m.LogDriver != nil { + data[i] = 0x6a + i++ + i = encodeVarintObjects(data, i, uint64(m.LogDriver.Size())) + n21, err := m.LogDriver.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n21 + } return i, nil } @@ -984,11 +1007,11 @@ func (m *NetworkAttachment) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintObjects(data, i, uint64(m.Network.Size())) - n21, err := m.Network.MarshalTo(data[i:]) + n22, err := m.Network.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n21 + i += n22 } if len(m.Addresses) > 0 { for _, s := range m.Addresses { @@ -1047,38 +1070,38 @@ func (m *Network) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintObjects(data, i, uint64(m.Meta.Size())) - n22, err := m.Meta.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n22 - data[i] = 0x1a - i++ - i = encodeVarintObjects(data, i, uint64(m.Spec.Size())) - n23, err := m.Spec.MarshalTo(data[i:]) + n23, err := m.Meta.MarshalTo(data[i:]) if err != nil { return 0, err } i += n23 + data[i] = 0x1a + i++ + i = encodeVarintObjects(data, i, uint64(m.Spec.Size())) + n24, err := m.Spec.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n24 if m.DriverState != nil { data[i] = 0x22 i++ i = encodeVarintObjects(data, i, uint64(m.DriverState.Size())) - n24, err := m.DriverState.MarshalTo(data[i:]) + n25, err := m.DriverState.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n24 + i += n25 } if m.IPAM != nil { data[i] = 0x2a i++ i = encodeVarintObjects(data, i, uint64(m.IPAM.Size())) - n25, err := m.IPAM.MarshalTo(data[i:]) + n26, err := m.IPAM.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n25 + i += n26 } return i, nil } @@ -1107,27 +1130,27 @@ func (m *Cluster) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintObjects(data, i, uint64(m.Meta.Size())) - n26, err := m.Meta.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n26 - data[i] = 0x1a - i++ - i = encodeVarintObjects(data, i, uint64(m.Spec.Size())) - n27, err := m.Spec.MarshalTo(data[i:]) + n27, err := m.Meta.MarshalTo(data[i:]) if err != nil { return 0, err } i += n27 - data[i] = 0x22 + data[i] = 0x1a i++ - i = encodeVarintObjects(data, i, uint64(m.RootCA.Size())) - n28, err := m.RootCA.MarshalTo(data[i:]) + i = encodeVarintObjects(data, i, uint64(m.Spec.Size())) + n28, err := m.Spec.MarshalTo(data[i:]) if err != nil { return 0, err } i += n28 + data[i] = 0x22 + i++ + i = encodeVarintObjects(data, i, uint64(m.RootCA.Size())) + n29, err := m.RootCA.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n29 if len(m.NetworkBootstrapKeys) > 0 { for _, msg := range m.NetworkBootstrapKeys { data[i] = 0x2a @@ -1317,6 +1340,10 @@ func (m *Task) Size() (n int) { l = m.Endpoint.Size() n += 1 + l + sovObjects(uint64(l)) } + if m.LogDriver != nil { + l = m.LogDriver.Size() + n += 1 + l + sovObjects(uint64(l)) + } return n } @@ -1484,6 +1511,7 @@ func (this *Task) String() string { `DesiredState:` + fmt.Sprintf("%v", this.DesiredState) + `,`, `Networks:` + strings.Replace(fmt.Sprintf("%v", this.Networks), "NetworkAttachment", "NetworkAttachment", 1) + `,`, `Endpoint:` + strings.Replace(fmt.Sprintf("%v", this.Endpoint), "Endpoint", "Endpoint", 1) + `,`, + `LogDriver:` + strings.Replace(fmt.Sprintf("%v", this.LogDriver), "Driver", "Driver", 1) + `,`, `}`, }, "") return s @@ -2774,6 +2802,39 @@ func (m *Task) Unmarshal(data []byte) error { return err } iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LogDriver", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowObjects + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthObjects + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LogDriver == nil { + m.LogDriver = &Driver{} + } + if err := m.LogDriver.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipObjects(data[iNdEx:]) @@ -3466,66 +3527,67 @@ var ( ) var fileDescriptorObjects = []byte{ - // 965 bytes of a gzipped FileDescriptorProto + // 981 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0xaf, 0xed, 0xad, 0xed, 0x7d, 0x4e, 0x22, 0x31, 0x54, 0xd5, 0x36, 0x84, 0xa4, 0xb8, 0x02, + 0x14, 0xaf, 0xed, 0x8d, 0xed, 0x7d, 0x8e, 0x23, 0x31, 0x54, 0xd5, 0x36, 0x84, 0xa4, 0xb8, 0x02, 0x71, 0x40, 0xae, 0x28, 0x05, 0x81, 0xa0, 0x42, 0xb6, 0x13, 0x81, 0x05, 0x81, 0x68, 0x5a, 0x85, - 0xa3, 0x35, 0xd9, 0x9d, 0x86, 0xc5, 0xf6, 0xee, 0x6a, 0x66, 0xe2, 0x2a, 0x37, 0xc4, 0x07, 0x40, - 0xe2, 0x0b, 0xf0, 0x55, 0xb8, 0x46, 0x9c, 0x38, 0x72, 0xaa, 0x68, 0x6f, 0x9c, 0xe0, 0x23, 0xf0, - 0x66, 0xf6, 0xad, 0xbd, 0x95, 0xd7, 0x51, 0x2b, 0xa1, 0x1c, 0x56, 0x9e, 0x3f, 0xbf, 0xdf, 0x6f, - 0xde, 0x7b, 0xf3, 0xde, 0x1b, 0xc3, 0x66, 0x7a, 0xf2, 0x83, 0x0c, 0x8d, 0xee, 0x65, 0x2a, 0x35, - 0x29, 0x63, 0x51, 0x1a, 0x4e, 0xa4, 0xea, 0xe9, 0x27, 0x42, 0xcd, 0x26, 0xb1, 0xe9, 0xcd, 0xdf, - 0xdf, 0xee, 0x98, 0xf3, 0x4c, 0x12, 0x60, 0xbb, 0xa3, 0x33, 0x19, 0x16, 0x93, 0x5b, 0x26, 0x9e, - 0x49, 0x6d, 0xc4, 0x2c, 0xbb, 0xbb, 0x18, 0xd1, 0xd6, 0x8d, 0xd3, 0xf4, 0x34, 0x75, 0xc3, 0xbb, - 0x76, 0x94, 0xaf, 0x76, 0x7f, 0xab, 0x81, 0x77, 0x28, 0x8d, 0x60, 0x9f, 0x42, 0x6b, 0x2e, 0x95, - 0x8e, 0xd3, 0x24, 0xa8, 0xdd, 0xae, 0xbd, 0xdb, 0xb9, 0xf7, 0x46, 0x6f, 0xf5, 0xe4, 0xde, 0x71, - 0x0e, 0x19, 0x78, 0x17, 0x4f, 0xf7, 0xae, 0xf1, 0x82, 0xc1, 0x3e, 0x03, 0x08, 0x95, 0x14, 0x46, - 0x46, 0x63, 0x61, 0x82, 0xba, 0xe3, 0xbf, 0x59, 0xc5, 0x7f, 0x54, 0x18, 0xc5, 0x7d, 0x22, 0xf4, - 0x8d, 0x65, 0x9f, 0x65, 0x51, 0xc1, 0x6e, 0xbc, 0x14, 0x9b, 0x08, 0x7d, 0xd3, 0xfd, 0xbb, 0x01, - 0xde, 0x37, 0x69, 0x24, 0xd9, 0x4d, 0xa8, 0xc7, 0x91, 0x33, 0xde, 0x1f, 0x34, 0x9f, 0x3f, 0xdd, - 0xab, 0x8f, 0xf6, 0x39, 0xae, 0xb0, 0x7b, 0xe0, 0xcd, 0xd0, 0x43, 0x32, 0x2b, 0xa8, 0x12, 0xb6, - 0x11, 0x20, 0x9f, 0x1c, 0x96, 0x7d, 0x04, 0x9e, 0x0d, 0x2b, 0x19, 0xb3, 0x53, 0xc5, 0xb1, 0x67, - 0x3e, 0x44, 0x4c, 0xc1, 0xb3, 0x78, 0x76, 0x00, 0x9d, 0x48, 0xea, 0x50, 0xc5, 0x99, 0xb1, 0x91, - 0xf4, 0x1c, 0xfd, 0xce, 0x3a, 0xfa, 0xfe, 0x12, 0xca, 0xcb, 0x3c, 0x8c, 0x48, 0x13, 0xfd, 0x34, - 0x67, 0x3a, 0xb8, 0xee, 0x14, 0x76, 0xd7, 0x1a, 0xe0, 0x50, 0x64, 0x02, 0x71, 0xd8, 0x97, 0xb0, - 0x35, 0x13, 0x89, 0x38, 0x95, 0x6a, 0x4c, 0x2a, 0x4d, 0xa7, 0xf2, 0x56, 0xa5, 0xeb, 0x39, 0x32, - 0x17, 0xe2, 0x9b, 0xb3, 0xf2, 0x14, 0xdd, 0x01, 0x61, 0x8c, 0x08, 0xbf, 0x9f, 0xc9, 0xc4, 0x04, - 0x2d, 0xa7, 0xf2, 0x76, 0xa5, 0x2d, 0xd2, 0x3c, 0x49, 0xd5, 0xa4, 0xbf, 0x00, 0xf3, 0x12, 0x91, - 0x7d, 0x01, 0x9d, 0x50, 0x2a, 0x13, 0x3f, 0x8e, 0x43, 0xbc, 0xb4, 0xa0, 0xed, 0x74, 0xf6, 0xaa, - 0x74, 0x86, 0x4b, 0x18, 0x39, 0x55, 0x66, 0x76, 0x7f, 0xaf, 0x41, 0xeb, 0xa1, 0x54, 0xf3, 0x38, - 0xfc, 0x7f, 0xaf, 0xfb, 0x93, 0x17, 0xae, 0xbb, 0xd2, 0x32, 0x3a, 0x76, 0xe5, 0xc6, 0x3f, 0x86, - 0xb6, 0x4c, 0xa2, 0x2c, 0x8d, 0x31, 0x40, 0xde, 0xfa, 0x6c, 0x39, 0x20, 0x0c, 0x5f, 0xa0, 0xbb, - 0xbf, 0xd6, 0xa1, 0x5d, 0x2c, 0xb3, 0xfb, 0x64, 0x41, 0x5e, 0x7b, 0xb7, 0x2f, 0x93, 0xb0, 0x26, - 0xd0, 0xe1, 0xf7, 0xe1, 0x7a, 0x96, 0x2a, 0xa3, 0xd1, 0xd9, 0xc6, 0xba, 0x34, 0x39, 0x42, 0xc0, - 0x30, 0x4d, 0x1e, 0xc7, 0xa7, 0x3c, 0x07, 0xb3, 0xef, 0xa0, 0x33, 0x8f, 0x95, 0x39, 0x13, 0xd3, - 0x71, 0x9c, 0x69, 0x74, 0xda, 0x72, 0xdf, 0xb9, 0xec, 0xc8, 0xde, 0x71, 0x8e, 0x1f, 0x1d, 0x0d, - 0xb6, 0x30, 0xd4, 0xb0, 0x98, 0x6a, 0x0e, 0x24, 0x35, 0xca, 0xf4, 0xf6, 0x21, 0xf8, 0x8b, 0x1d, - 0xf6, 0x1e, 0x40, 0x92, 0x67, 0xc5, 0x78, 0x71, 0x4f, 0x9b, 0x48, 0xf6, 0x29, 0x57, 0xf0, 0xba, - 0x7c, 0x02, 0x8c, 0x22, 0xc6, 0xc0, 0x13, 0x51, 0xa4, 0xdc, 0xad, 0xf9, 0xdc, 0x8d, 0xbb, 0xbf, - 0x5c, 0x07, 0xef, 0x91, 0xd0, 0x93, 0xab, 0xae, 0x6c, 0x7b, 0xe6, 0xca, 0x3d, 0xa3, 0x3b, 0x3a, - 0x4f, 0x01, 0xeb, 0x8e, 0xb7, 0x74, 0x87, 0x12, 0xc3, 0xba, 0x43, 0x80, 0xdc, 0x1d, 0x3d, 0x4d, - 0x8d, 0x2b, 0x5f, 0x8f, 0xbb, 0x31, 0xbb, 0x03, 0xad, 0x04, 0x4b, 0xd6, 0xd2, 0x9b, 0x8e, 0x0e, - 0x48, 0x6f, 0xda, 0x2a, 0x46, 0x6e, 0xd3, 0x6e, 0x21, 0x11, 0x4b, 0x45, 0x24, 0x49, 0x8a, 0xe5, - 0x87, 0x7d, 0x40, 0x53, 0xc9, 0x55, 0x26, 0x64, 0x7f, 0x09, 0x2b, 0x4a, 0xa5, 0xc4, 0x64, 0xc7, - 0xf0, 0x7a, 0x61, 0x6f, 0x59, 0xb0, 0xfd, 0x2a, 0x82, 0x8c, 0x14, 0x4a, 0x3b, 0xa5, 0xd6, 0xe4, - 0xaf, 0x6f, 0x4d, 0x2e, 0x82, 0x55, 0xad, 0x69, 0x00, 0x9b, 0xd8, 0xe7, 0x62, 0x85, 0xad, 0xde, - 0xae, 0xc8, 0x00, 0x50, 0x64, 0x6b, 0x4d, 0xb7, 0x27, 0x11, 0xc9, 0x37, 0x88, 0xe3, 0x66, 0xac, - 0x0f, 0x6d, 0xca, 0x1b, 0x1d, 0x74, 0x5c, 0xee, 0xbe, 0x64, 0x4b, 0x5a, 0xd0, 0x5e, 0x28, 0xda, - 0x8d, 0x57, 0x2a, 0xda, 0x9f, 0x6a, 0xf0, 0xda, 0x8a, 0x32, 0xfb, 0x10, 0xaf, 0x36, 0x5f, 0xbc, - 0xec, 0xf1, 0x24, 0x1e, 0x2f, 0xb0, 0x6c, 0x07, 0x7c, 0x9b, 0xe8, 0x52, 0x6b, 0x99, 0x97, 0xb0, - 0xcf, 0x97, 0x0b, 0x2c, 0x80, 0x96, 0x98, 0xc6, 0xc2, 0xee, 0x35, 0xdc, 0x5e, 0x31, 0xed, 0xfe, - 0x5c, 0x87, 0x16, 0x89, 0x5d, 0x75, 0x1b, 0xa4, 0x63, 0x57, 0xca, 0xe3, 0x01, 0x6c, 0x44, 0x2a, - 0x9e, 0xd3, 0x93, 0x23, 0xa9, 0x15, 0x6e, 0x57, 0x49, 0xec, 0x3b, 0x1c, 0x3e, 0x78, 0xee, 0x37, - 0xbf, 0xd3, 0x07, 0xe0, 0xc5, 0x99, 0x98, 0xd1, 0x73, 0x57, 0x79, 0xf2, 0xe8, 0xa8, 0x7f, 0xf8, - 0x6d, 0x96, 0xa7, 0x67, 0x1b, 0x1d, 0xf5, 0xec, 0x02, 0x77, 0xb4, 0xee, 0x3f, 0x18, 0x90, 0xe1, - 0xf4, 0x4c, 0x1b, 0xa9, 0xae, 0x3a, 0x20, 0x74, 0xec, 0x4a, 0x40, 0x86, 0xd0, 0x52, 0x69, 0x6a, - 0xc6, 0xa1, 0xb8, 0x2c, 0x16, 0x1c, 0x21, 0xc3, 0xfe, 0x60, 0xcb, 0x12, 0x6d, 0x37, 0xc8, 0xe7, - 0xbc, 0x69, 0xa9, 0x43, 0x81, 0x9d, 0xfa, 0x66, 0xd1, 0x43, 0x4f, 0x70, 0x45, 0x1b, 0x25, 0xb2, - 0xf1, 0x44, 0x9e, 0xdb, 0xff, 0x05, 0x8d, 0x75, 0x2f, 0xfa, 0x41, 0x12, 0xaa, 0x73, 0x17, 0xa8, - 0xaf, 0xe4, 0x39, 0xbf, 0x41, 0x02, 0x83, 0x82, 0x8f, 0x8b, 0x9a, 0x7d, 0x0e, 0x3b, 0x72, 0x01, - 0xb3, 0x8a, 0xe3, 0x29, 0xfe, 0xad, 0xc2, 0xd7, 0x61, 0x1c, 0x4e, 0x51, 0xd1, 0x35, 0x28, 0x8f, - 0xdf, 0x92, 0x65, 0xa9, 0xaf, 0x73, 0xc4, 0xd0, 0x02, 0x06, 0x3b, 0x17, 0xcf, 0x76, 0xaf, 0xfd, - 0x89, 0xdf, 0xbf, 0xcf, 0x76, 0x6b, 0x3f, 0x3e, 0xdf, 0xad, 0x5d, 0xe0, 0xf7, 0x07, 0x7e, 0x7f, - 0xe1, 0x77, 0xd2, 0x74, 0x7f, 0x2e, 0x3f, 0xf8, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x55, 0xec, - 0x86, 0xcc, 0x0a, 0x00, 0x00, + 0xe3, 0x6a, 0xb2, 0x3b, 0x35, 0x8b, 0xed, 0xdd, 0xd5, 0xcc, 0x24, 0x55, 0x6e, 0x88, 0x0f, 0xc0, + 0x47, 0xe0, 0xab, 0x70, 0x8d, 0x10, 0x07, 0x8e, 0x9c, 0x2a, 0xda, 0x1b, 0x27, 0xf8, 0x08, 0xbc, + 0xf9, 0xb3, 0xf6, 0x56, 0x5e, 0x87, 0x56, 0xaa, 0x72, 0x58, 0x69, 0xfe, 0xfc, 0x7e, 0xbf, 0x79, + 0xef, 0xcd, 0x7b, 0x6f, 0x07, 0xba, 0xd9, 0xc9, 0x0f, 0x3c, 0x52, 0xb2, 0x9f, 0x8b, 0x4c, 0x65, + 0x84, 0xc4, 0x59, 0x34, 0xe5, 0xa2, 0x2f, 0x1f, 0x33, 0x31, 0x9f, 0x26, 0xaa, 0x7f, 0xf6, 0xfe, + 0x76, 0x47, 0x9d, 0xe7, 0xdc, 0x01, 0xb6, 0x3b, 0x32, 0xe7, 0x51, 0x31, 0xb9, 0xa9, 0x92, 0x39, + 0x97, 0x8a, 0xcd, 0xf3, 0x3b, 0x8b, 0x91, 0xdb, 0xba, 0x3e, 0xc9, 0x26, 0x99, 0x19, 0xde, 0xd1, + 0x23, 0xbb, 0xda, 0xfb, 0xb5, 0x06, 0xde, 0x21, 0x57, 0x8c, 0x7c, 0x0a, 0xad, 0x33, 0x2e, 0x64, + 0x92, 0xa5, 0x41, 0xed, 0x56, 0xed, 0xdd, 0xce, 0xdd, 0x37, 0xfa, 0xab, 0x27, 0xf7, 0x8f, 0x2d, + 0x64, 0xe8, 0x5d, 0x3c, 0xd9, 0xbb, 0x46, 0x0b, 0x06, 0xf9, 0x0c, 0x20, 0x12, 0x9c, 0x29, 0x1e, + 0x87, 0x4c, 0x05, 0x75, 0xc3, 0x7f, 0xb3, 0x8a, 0xff, 0xb0, 0x30, 0x8a, 0xfa, 0x8e, 0x30, 0x50, + 0x9a, 0x7d, 0x9a, 0xc7, 0x05, 0xbb, 0xf1, 0x42, 0x6c, 0x47, 0x18, 0xa8, 0xde, 0xdf, 0x0d, 0xf0, + 0xbe, 0xc9, 0x62, 0x4e, 0x6e, 0x40, 0x3d, 0x89, 0x8d, 0xf1, 0xfe, 0xb0, 0xf9, 0xec, 0xc9, 0x5e, + 0x7d, 0xbc, 0x4f, 0x71, 0x85, 0xdc, 0x05, 0x6f, 0x8e, 0x1e, 0x3a, 0xb3, 0x82, 0x2a, 0x61, 0x1d, + 0x01, 0xe7, 0x93, 0xc1, 0x92, 0x8f, 0xc0, 0xd3, 0x61, 0x75, 0xc6, 0xec, 0x54, 0x71, 0xf4, 0x99, + 0x0f, 0x10, 0x53, 0xf0, 0x34, 0x9e, 0x1c, 0x40, 0x27, 0xe6, 0x32, 0x12, 0x49, 0xae, 0x74, 0x24, + 0x3d, 0x43, 0xbf, 0xbd, 0x8e, 0xbe, 0xbf, 0x84, 0xd2, 0x32, 0x0f, 0x23, 0xd2, 0x44, 0x3f, 0xd5, + 0xa9, 0x0c, 0x36, 0x8c, 0xc2, 0xee, 0x5a, 0x03, 0x0c, 0xca, 0x99, 0xe0, 0x38, 0xe4, 0x4b, 0xd8, + 0x9a, 0xb3, 0x94, 0x4d, 0xb8, 0x08, 0x9d, 0x4a, 0xd3, 0xa8, 0xbc, 0x55, 0xe9, 0xba, 0x45, 0x5a, + 0x21, 0xda, 0x9d, 0x97, 0xa7, 0xe8, 0x0e, 0x30, 0xa5, 0x58, 0xf4, 0xfd, 0x9c, 0xa7, 0x2a, 0x68, + 0x19, 0x95, 0xb7, 0x2b, 0x6d, 0xe1, 0xea, 0x71, 0x26, 0xa6, 0x83, 0x05, 0x98, 0x96, 0x88, 0xe4, + 0x0b, 0xe8, 0x44, 0x5c, 0xa8, 0xe4, 0x51, 0x12, 0xe1, 0xa5, 0x05, 0x6d, 0xa3, 0xb3, 0x57, 0xa5, + 0x33, 0x5a, 0xc2, 0x9c, 0x53, 0x65, 0x66, 0xef, 0xb7, 0x1a, 0xb4, 0x1e, 0x70, 0x71, 0x96, 0x44, + 0xaf, 0xf6, 0xba, 0x3f, 0x79, 0xee, 0xba, 0x2b, 0x2d, 0x73, 0xc7, 0xae, 0xdc, 0xf8, 0xc7, 0xd0, + 0xe6, 0x69, 0x9c, 0x67, 0x09, 0x06, 0xc8, 0x5b, 0x9f, 0x2d, 0x07, 0x0e, 0x43, 0x17, 0xe8, 0xde, + 0x2f, 0x75, 0x68, 0x17, 0xcb, 0xe4, 0x9e, 0xb3, 0xc0, 0xd6, 0xde, 0xad, 0xcb, 0x24, 0xb4, 0x09, + 0xee, 0xf0, 0x7b, 0xb0, 0x91, 0x67, 0x42, 0x49, 0x74, 0xb6, 0xb1, 0x2e, 0x4d, 0x8e, 0x10, 0x30, + 0xca, 0xd2, 0x47, 0xc9, 0x84, 0x5a, 0x30, 0xf9, 0x0e, 0x3a, 0x67, 0x89, 0x50, 0xa7, 0x6c, 0x16, + 0x26, 0xb9, 0x44, 0xa7, 0x35, 0xf7, 0x9d, 0xcb, 0x8e, 0xec, 0x1f, 0x5b, 0xfc, 0xf8, 0x68, 0xb8, + 0x85, 0xa1, 0x86, 0xc5, 0x54, 0x52, 0x70, 0x52, 0xe3, 0x5c, 0x6e, 0x1f, 0x82, 0xbf, 0xd8, 0x21, + 0xef, 0x01, 0xa4, 0x36, 0x2b, 0xc2, 0xc5, 0x3d, 0x75, 0x91, 0xec, 0xbb, 0x5c, 0xc1, 0xeb, 0xf2, + 0x1d, 0x60, 0x1c, 0x13, 0x02, 0x1e, 0x8b, 0x63, 0x61, 0x6e, 0xcd, 0xa7, 0x66, 0xdc, 0xfb, 0x7d, + 0x03, 0xbc, 0x87, 0x4c, 0x4e, 0xaf, 0xba, 0xb2, 0xf5, 0x99, 0x2b, 0xf7, 0x8c, 0xee, 0x48, 0x9b, + 0x02, 0xda, 0x1d, 0x6f, 0xe9, 0x8e, 0x4b, 0x0c, 0xed, 0x8e, 0x03, 0x58, 0x77, 0xe4, 0x2c, 0x53, + 0xa6, 0x7c, 0x3d, 0x6a, 0xc6, 0xe4, 0x36, 0xb4, 0x52, 0x2c, 0x59, 0x4d, 0x6f, 0x1a, 0x3a, 0x20, + 0xbd, 0xa9, 0xab, 0x18, 0xb9, 0x4d, 0xbd, 0x85, 0x44, 0x2c, 0x15, 0x96, 0xa6, 0x19, 0x96, 0x1f, + 0xf6, 0x01, 0xe9, 0x4a, 0xae, 0x32, 0x21, 0x07, 0x4b, 0x58, 0x51, 0x2a, 0x25, 0x26, 0x39, 0x86, + 0xd7, 0x0b, 0x7b, 0xcb, 0x82, 0xed, 0x97, 0x11, 0x24, 0x4e, 0xa1, 0xb4, 0x53, 0x6a, 0x4d, 0xfe, + 0xfa, 0xd6, 0x64, 0x22, 0x58, 0xd5, 0x9a, 0x86, 0xd0, 0xc5, 0x3e, 0x97, 0x08, 0x6c, 0xf5, 0x7a, + 0x85, 0x07, 0x80, 0x22, 0x5b, 0x6b, 0xba, 0xbd, 0x13, 0xe1, 0x74, 0xd3, 0x71, 0xcc, 0x8c, 0x0c, + 0xa0, 0xed, 0xf2, 0x46, 0x06, 0x1d, 0x93, 0xbb, 0x2f, 0xd8, 0x92, 0x16, 0xb4, 0xe7, 0x8a, 0x76, + 0xf3, 0x65, 0x8a, 0x16, 0x3b, 0x05, 0xcc, 0xb2, 0x49, 0x18, 0x8b, 0x04, 0xff, 0x7d, 0x41, 0xd7, + 0x70, 0xb7, 0xab, 0xb8, 0xfb, 0x06, 0x41, 0x7d, 0x44, 0xdb, 0x61, 0xef, 0xa7, 0x1a, 0xbc, 0xb6, + 0x62, 0x14, 0xf9, 0x10, 0xb3, 0xc2, 0x2e, 0x5e, 0xf6, 0xdf, 0x75, 0x3c, 0x5a, 0x60, 0xc9, 0x0e, + 0xf8, 0xba, 0x46, 0xb8, 0x94, 0xdc, 0x56, 0xbf, 0x4f, 0x97, 0x0b, 0x24, 0x80, 0x16, 0x9b, 0x25, + 0x4c, 0xef, 0x35, 0xcc, 0x5e, 0x31, 0xed, 0xfd, 0x5c, 0x87, 0x96, 0x13, 0xbb, 0xea, 0x0e, 0xea, + 0x8e, 0x5d, 0xa9, 0xac, 0xfb, 0xb0, 0x69, 0xc3, 0xe9, 0x52, 0xc2, 0xfb, 0xdf, 0xa0, 0x76, 0x2c, + 0xde, 0xa6, 0xc3, 0x7d, 0xf0, 0x92, 0x9c, 0xcd, 0xdd, 0x9f, 0xb2, 0xf2, 0xe4, 0xf1, 0xd1, 0xe0, + 0xf0, 0xdb, 0xdc, 0x66, 0x76, 0x1b, 0x1d, 0xf5, 0xf4, 0x02, 0x35, 0xb4, 0xde, 0x3f, 0x18, 0x90, + 0xd1, 0xec, 0x54, 0x2a, 0x2e, 0xae, 0x3a, 0x20, 0xee, 0xd8, 0x95, 0x80, 0x8c, 0xa0, 0x25, 0xb2, + 0x4c, 0x85, 0x11, 0xbb, 0x2c, 0x16, 0x14, 0x21, 0xa3, 0xc1, 0x70, 0x4b, 0x13, 0x75, 0x23, 0xb1, + 0x73, 0xda, 0xd4, 0xd4, 0x11, 0xc3, 0x26, 0x7f, 0xa3, 0x68, 0xbf, 0x27, 0xb8, 0x22, 0x95, 0x60, + 0x79, 0x38, 0xe5, 0xe7, 0xfa, 0x49, 0xd1, 0x58, 0xf7, 0x18, 0x38, 0x48, 0x23, 0x71, 0x6e, 0x02, + 0xf5, 0x15, 0x3f, 0xa7, 0xd7, 0x9d, 0xc0, 0xb0, 0xe0, 0xe3, 0xa2, 0x24, 0x9f, 0xc3, 0x0e, 0x5f, + 0xc0, 0xb4, 0x62, 0x38, 0xc3, 0x17, 0x19, 0xfe, 0x58, 0xc2, 0x68, 0x86, 0x8a, 0xa6, 0xb7, 0x79, + 0xf4, 0x26, 0x2f, 0x4b, 0x7d, 0x6d, 0x11, 0x23, 0x0d, 0x18, 0xee, 0x5c, 0x3c, 0xdd, 0xbd, 0xf6, + 0x27, 0x7e, 0xff, 0x3e, 0xdd, 0xad, 0xfd, 0xf8, 0x6c, 0xb7, 0x76, 0x81, 0xdf, 0x1f, 0xf8, 0xfd, + 0x85, 0xdf, 0x49, 0xd3, 0xbc, 0x4b, 0x3f, 0xf8, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xb9, 0x27, 0xf6, + 0x9e, 0x07, 0x0b, 0x00, 0x00, } diff --git a/vendor/src/github.com/docker/swarmkit/api/objects.proto b/vendor/src/github.com/docker/swarmkit/api/objects.proto index 56d61a4b9c..f91a0751f9 100644 --- a/vendor/src/github.com/docker/swarmkit/api/objects.proto +++ b/vendor/src/github.com/docker/swarmkit/api/objects.proto @@ -155,6 +155,16 @@ message Task { // A copy of runtime state of service endpoint from Service // object to be distributed to agents as part of the task. Endpoint endpoint = 12; + + // LogDriver specifies the selected log driver to use for the task. Agent + // processes should always favor the value in this field. + // + // If present in the TaskSpec, this will be a copy of that value. The + // orchestrator may choose to insert a value here, which should be honored, + // such a cluster default or policy-based value. + // + // If not present, the daemon's default will be used. + Driver log_driver = 13; } // NetworkAttachment specifies the network parameters of attachment to diff --git a/vendor/src/github.com/docker/swarmkit/api/specs.pb.go b/vendor/src/github.com/docker/swarmkit/api/specs.pb.go index c8f45105e8..35102669b4 100644 --- a/vendor/src/github.com/docker/swarmkit/api/specs.pb.go +++ b/vendor/src/github.com/docker/swarmkit/api/specs.pb.go @@ -308,6 +308,9 @@ type TaskSpec struct { Restart *RestartPolicy `protobuf:"bytes,4,opt,name=restart" json:"restart,omitempty"` // Placement specifies node selection constraints Placement *Placement `protobuf:"bytes,5,opt,name=placement" json:"placement,omitempty"` + // LogDriver specifies the log driver to use for the task. Any runtime will + // direct logs into the specified driver for the duration of the task. + LogDriver *Driver `protobuf:"bytes,6,opt,name=log_driver,json=logDriver" json:"log_driver,omitempty"` } func (m *TaskSpec) Reset() { *m = TaskSpec{} } @@ -500,6 +503,12 @@ type ClusterSpec struct { Dispatcher DispatcherConfig `protobuf:"bytes,5,opt,name=dispatcher" json:"dispatcher"` // CAConfig defines cluster-level certificate authority settings. CAConfig CAConfig `protobuf:"bytes,6,opt,name=ca_config,json=caConfig" json:"ca_config"` + // DefaultLogDriver specifies the log driver to use for the cluster if not + // specified for each task. + // + // If this is changed, only new tasks will pick up the new log driver. + // Existing tasks will continue to use the previous default until rescheduled. + DefaultLogDriver *Driver `protobuf:"bytes,7,opt,name=default_log_driver,json=defaultLogDriver" json:"default_log_driver,omitempty"` } func (m *ClusterSpec) Reset() { *m = ClusterSpec{} } @@ -625,6 +634,7 @@ func (m *TaskSpec) Copy() *TaskSpec { Resources: m.Resources.Copy(), Restart: m.Restart.Copy(), Placement: m.Placement.Copy(), + LogDriver: m.LogDriver.Copy(), } switch m.Runtime.(type) { @@ -749,6 +759,7 @@ func (m *ClusterSpec) Copy() *ClusterSpec { Raft: *m.Raft.Copy(), Dispatcher: *m.Dispatcher.Copy(), CAConfig: *m.CAConfig.Copy(), + DefaultLogDriver: m.DefaultLogDriver.Copy(), } return o @@ -840,7 +851,7 @@ func (this *TaskSpec) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 8) + s := make([]string, 0, 9) s = append(s, "&api.TaskSpec{") if this.Runtime != nil { s = append(s, "Runtime: "+fmt.Sprintf("%#v", this.Runtime)+",\n") @@ -854,6 +865,9 @@ func (this *TaskSpec) GoString() string { if this.Placement != nil { s = append(s, "Placement: "+fmt.Sprintf("%#v", this.Placement)+",\n") } + if this.LogDriver != nil { + s = append(s, "LogDriver: "+fmt.Sprintf("%#v", this.LogDriver)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -947,7 +961,7 @@ func (this *ClusterSpec) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 10) + s := make([]string, 0, 11) s = append(s, "&api.ClusterSpec{") s = append(s, "Annotations: "+strings.Replace(this.Annotations.GoString(), `&`, ``, 1)+",\n") s = append(s, "AcceptancePolicy: "+strings.Replace(this.AcceptancePolicy.GoString(), `&`, ``, 1)+",\n") @@ -955,6 +969,9 @@ func (this *ClusterSpec) GoString() string { s = append(s, "Raft: "+strings.Replace(this.Raft.GoString(), `&`, ``, 1)+",\n") s = append(s, "Dispatcher: "+strings.Replace(this.Dispatcher.GoString(), `&`, ``, 1)+",\n") s = append(s, "CAConfig: "+strings.Replace(this.CAConfig.GoString(), `&`, ``, 1)+",\n") + if this.DefaultLogDriver != nil { + s = append(s, "DefaultLogDriver: "+fmt.Sprintf("%#v", this.DefaultLogDriver)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1257,6 +1274,16 @@ func (m *TaskSpec) MarshalTo(data []byte) (int, error) { } i += n12 } + if m.LogDriver != nil { + data[i] = 0x32 + i++ + i = encodeVarintSpecs(data, i, uint64(m.LogDriver.Size())) + n13, err := m.LogDriver.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n13 + } return i, nil } @@ -1266,11 +1293,11 @@ func (m *TaskSpec_Container) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintSpecs(data, i, uint64(m.Container.Size())) - n13, err := m.Container.MarshalTo(data[i:]) + n14, err := m.Container.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n13 + i += n14 } return i, nil } @@ -1385,21 +1412,21 @@ func (m *ContainerSpec) MarshalTo(data []byte) (int, error) { data[i] = 0x4a i++ i = encodeVarintSpecs(data, i, uint64(m.StopGracePeriod.Size())) - n14, err := m.StopGracePeriod.MarshalTo(data[i:]) + n15, err := m.StopGracePeriod.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n14 + i += n15 } if m.PullOptions != nil { data[i] = 0x52 i++ i = encodeVarintSpecs(data, i, uint64(m.PullOptions.Size())) - n15, err := m.PullOptions.MarshalTo(data[i:]) + n16, err := m.PullOptions.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n15 + i += n16 } return i, nil } @@ -1483,20 +1510,20 @@ func (m *NetworkSpec) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintSpecs(data, i, uint64(m.Annotations.Size())) - n16, err := m.Annotations.MarshalTo(data[i:]) + n17, err := m.Annotations.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n16 + i += n17 if m.DriverConfig != nil { data[i] = 0x12 i++ i = encodeVarintSpecs(data, i, uint64(m.DriverConfig.Size())) - n17, err := m.DriverConfig.MarshalTo(data[i:]) + n18, err := m.DriverConfig.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n17 + i += n18 } if m.Ipv6Enabled { data[i] = 0x18 @@ -1522,11 +1549,11 @@ func (m *NetworkSpec) MarshalTo(data []byte) (int, error) { data[i] = 0x2a i++ i = encodeVarintSpecs(data, i, uint64(m.IPAM.Size())) - n18, err := m.IPAM.MarshalTo(data[i:]) + n19, err := m.IPAM.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n18 + i += n19 } return i, nil } @@ -1549,51 +1576,61 @@ func (m *ClusterSpec) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintSpecs(data, i, uint64(m.Annotations.Size())) - n19, err := m.Annotations.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n19 - data[i] = 0x12 - i++ - i = encodeVarintSpecs(data, i, uint64(m.AcceptancePolicy.Size())) - n20, err := m.AcceptancePolicy.MarshalTo(data[i:]) + n20, err := m.Annotations.MarshalTo(data[i:]) if err != nil { return 0, err } i += n20 - data[i] = 0x1a + data[i] = 0x12 i++ - i = encodeVarintSpecs(data, i, uint64(m.Orchestration.Size())) - n21, err := m.Orchestration.MarshalTo(data[i:]) + i = encodeVarintSpecs(data, i, uint64(m.AcceptancePolicy.Size())) + n21, err := m.AcceptancePolicy.MarshalTo(data[i:]) if err != nil { return 0, err } i += n21 - data[i] = 0x22 + data[i] = 0x1a i++ - i = encodeVarintSpecs(data, i, uint64(m.Raft.Size())) - n22, err := m.Raft.MarshalTo(data[i:]) + i = encodeVarintSpecs(data, i, uint64(m.Orchestration.Size())) + n22, err := m.Orchestration.MarshalTo(data[i:]) if err != nil { return 0, err } i += n22 - data[i] = 0x2a + data[i] = 0x22 i++ - i = encodeVarintSpecs(data, i, uint64(m.Dispatcher.Size())) - n23, err := m.Dispatcher.MarshalTo(data[i:]) + i = encodeVarintSpecs(data, i, uint64(m.Raft.Size())) + n23, err := m.Raft.MarshalTo(data[i:]) if err != nil { return 0, err } i += n23 - data[i] = 0x32 + data[i] = 0x2a i++ - i = encodeVarintSpecs(data, i, uint64(m.CAConfig.Size())) - n24, err := m.CAConfig.MarshalTo(data[i:]) + i = encodeVarintSpecs(data, i, uint64(m.Dispatcher.Size())) + n24, err := m.Dispatcher.MarshalTo(data[i:]) if err != nil { return 0, err } i += n24 + data[i] = 0x32 + i++ + i = encodeVarintSpecs(data, i, uint64(m.CAConfig.Size())) + n25, err := m.CAConfig.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n25 + if m.DefaultLogDriver != nil { + data[i] = 0x3a + i++ + i = encodeVarintSpecs(data, i, uint64(m.DefaultLogDriver.Size())) + n26, err := m.DefaultLogDriver.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n26 + } return i, nil } @@ -1736,6 +1773,10 @@ func (m *TaskSpec) Size() (n int) { l = m.Placement.Size() n += 1 + l + sovSpecs(uint64(l)) } + if m.LogDriver != nil { + l = m.LogDriver.Size() + n += 1 + l + sovSpecs(uint64(l)) + } return n } @@ -1868,6 +1909,10 @@ func (m *ClusterSpec) Size() (n int) { n += 1 + l + sovSpecs(uint64(l)) l = m.CAConfig.Size() n += 1 + l + sovSpecs(uint64(l)) + if m.DefaultLogDriver != nil { + l = m.DefaultLogDriver.Size() + n += 1 + l + sovSpecs(uint64(l)) + } return n } @@ -1971,6 +2016,7 @@ func (this *TaskSpec) String() string { `Resources:` + strings.Replace(fmt.Sprintf("%v", this.Resources), "ResourceRequirements", "ResourceRequirements", 1) + `,`, `Restart:` + strings.Replace(fmt.Sprintf("%v", this.Restart), "RestartPolicy", "RestartPolicy", 1) + `,`, `Placement:` + strings.Replace(fmt.Sprintf("%v", this.Placement), "Placement", "Placement", 1) + `,`, + `LogDriver:` + strings.Replace(fmt.Sprintf("%v", this.LogDriver), "Driver", "Driver", 1) + `,`, `}`, }, "") return s @@ -2060,6 +2106,7 @@ func (this *ClusterSpec) String() string { `Raft:` + strings.Replace(strings.Replace(this.Raft.String(), "RaftConfig", "RaftConfig", 1), `&`, ``, 1) + `,`, `Dispatcher:` + strings.Replace(strings.Replace(this.Dispatcher.String(), "DispatcherConfig", "DispatcherConfig", 1), `&`, ``, 1) + `,`, `CAConfig:` + strings.Replace(strings.Replace(this.CAConfig.String(), "CAConfig", "CAConfig", 1), `&`, ``, 1) + `,`, + `DefaultLogDriver:` + strings.Replace(fmt.Sprintf("%v", this.DefaultLogDriver), "Driver", "Driver", 1) + `,`, `}`, }, "") return s @@ -2867,6 +2914,39 @@ func (m *TaskSpec) Unmarshal(data []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LogDriver", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSpecs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthSpecs + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LogDriver == nil { + m.LogDriver = &Driver{} + } + if err := m.LogDriver.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipSpecs(data[iNdEx:]) @@ -3894,6 +3974,39 @@ func (m *ClusterSpec) Unmarshal(data []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DefaultLogDriver", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSpecs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthSpecs + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DefaultLogDriver == nil { + m.DefaultLogDriver = &Driver{} + } + if err := m.DefaultLogDriver.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipSpecs(data[iNdEx:]) @@ -4021,85 +4134,88 @@ var ( ) var fileDescriptorSpecs = []byte{ - // 1279 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x56, 0xcf, 0x72, 0x1b, 0xc5, - 0x13, 0xb6, 0xec, 0xb5, 0x2c, 0xf7, 0xda, 0x89, 0x33, 0x95, 0x5f, 0xa2, 0x28, 0xf9, 0xd9, 0x8e, - 0x08, 0x10, 0xa8, 0x42, 0x06, 0x41, 0x25, 0xe1, 0x5f, 0xc1, 0x5a, 0x16, 0x8e, 0x09, 0x76, 0xb6, - 0xc6, 0x49, 0x38, 0xba, 0x46, 0xab, 0x89, 0xbc, 0xe5, 0xd5, 0xce, 0x32, 0x3b, 0x52, 0xca, 0x37, - 0x8e, 0x29, 0x0e, 0xdc, 0xe0, 0x40, 0x15, 0x27, 0xde, 0x81, 0x67, 0xc8, 0x91, 0x1b, 0x9c, 0x52, - 0x24, 0x4f, 0x40, 0x15, 0x2f, 0x40, 0xcf, 0xec, 0x48, 0x5a, 0x91, 0x75, 0xc2, 0xc1, 0x87, 0xad, - 0x9a, 0x3f, 0xdf, 0xf7, 0xf5, 0x4c, 0x77, 0x4f, 0xf7, 0x82, 0x9b, 0x26, 0x3c, 0x48, 0x1b, 0x89, - 0x14, 0x4a, 0x10, 0xd2, 0x15, 0xc1, 0x11, 0x97, 0x8d, 0xf4, 0x11, 0x93, 0xfd, 0xa3, 0x50, 0x35, - 0x86, 0xef, 0xd5, 0x5c, 0x75, 0x9c, 0x70, 0x0b, 0xa8, 0x9d, 0xef, 0x89, 0x9e, 0x30, 0xc3, 0x0d, - 0x3d, 0xb2, 0xab, 0x17, 0xbb, 0x03, 0xc9, 0x54, 0x28, 0xe2, 0x8d, 0xd1, 0x20, 0xdb, 0xa8, 0x7f, - 0xef, 0x40, 0x65, 0x4f, 0x74, 0xf9, 0x3e, 0xda, 0x20, 0xdb, 0xe0, 0xb2, 0x38, 0x16, 0xca, 0x00, - 0xd2, 0x6a, 0x69, 0xbd, 0x74, 0xdd, 0x6d, 0xae, 0x35, 0x5e, 0x34, 0xd9, 0xf0, 0x26, 0xb0, 0x4d, - 0xe7, 0xc9, 0xd3, 0xb5, 0x19, 0x9a, 0x67, 0x92, 0x77, 0xc1, 0x91, 0x22, 0xe2, 0xd5, 0x59, 0x54, - 0x38, 0xd3, 0xbc, 0x52, 0xa4, 0xa0, 0x8d, 0x52, 0xc4, 0x50, 0x83, 0x44, 0xd3, 0xd0, 0xe7, 0xfd, - 0x0e, 0x97, 0xe9, 0x61, 0x98, 0x54, 0xe7, 0x0c, 0xef, 0xcd, 0x93, 0x78, 0xfa, 0xb0, 0x8d, 0xdd, - 0x31, 0x9c, 0xe6, 0xa8, 0x64, 0x17, 0x96, 0xd8, 0x90, 0x85, 0x11, 0xeb, 0x84, 0x51, 0xa8, 0x8e, - 0xab, 0x8e, 0x91, 0x7a, 0xeb, 0xa5, 0x52, 0x5e, 0x8e, 0x40, 0xa7, 0xe8, 0xf5, 0x2e, 0xc0, 0xc4, - 0x10, 0x79, 0x03, 0x16, 0xfc, 0xf6, 0xde, 0xd6, 0xce, 0xde, 0xf6, 0xca, 0x4c, 0xed, 0xd2, 0x77, - 0x3f, 0xaf, 0xff, 0x4f, 0x6b, 0x4c, 0x00, 0x3e, 0x8f, 0xbb, 0x61, 0xdc, 0x23, 0xd7, 0xa1, 0xe2, - 0xb5, 0x5a, 0x6d, 0xff, 0x5e, 0x7b, 0x6b, 0xa5, 0x54, 0xab, 0x21, 0xf0, 0xc2, 0x34, 0xd0, 0x0b, - 0x02, 0x9e, 0x28, 0xde, 0xad, 0x39, 0x8f, 0x7f, 0x59, 0x9d, 0xa9, 0x3f, 0x2e, 0xc1, 0x52, 0xfe, - 0x10, 0x68, 0xa8, 0xec, 0xb5, 0xee, 0xed, 0x3c, 0x68, 0xa3, 0x9d, 0x31, 0x3d, 0x8f, 0xf0, 0x02, - 0x15, 0x0e, 0x39, 0xb9, 0x06, 0xf3, 0xbe, 0x77, 0x7f, 0xbf, 0x8d, 0x56, 0xc6, 0xc7, 0xc9, 0xc3, - 0x7c, 0x36, 0x48, 0x0d, 0x6a, 0x8b, 0x7a, 0x3b, 0x7b, 0x2b, 0xb3, 0xc5, 0xa8, 0x2d, 0xc9, 0xc2, - 0xd8, 0x1e, 0xe5, 0x57, 0x07, 0xdc, 0x7d, 0x2e, 0x87, 0x61, 0x70, 0xca, 0x39, 0x71, 0x03, 0x1c, - 0xc5, 0xd2, 0x23, 0x93, 0x13, 0x6e, 0x71, 0x4e, 0xdc, 0xc3, 0x7d, 0x6d, 0xd4, 0xd2, 0x0d, 0x5e, - 0x67, 0x86, 0xe4, 0x49, 0x14, 0x06, 0x0c, 0xfd, 0x65, 0x32, 0xc3, 0x6d, 0xbe, 0x5e, 0xc4, 0xa6, - 0x63, 0x94, 0x3d, 0xff, 0xed, 0x19, 0x9a, 0xa3, 0x92, 0x8f, 0xa1, 0xdc, 0x8b, 0x44, 0x87, 0x45, - 0x26, 0x27, 0xdc, 0xe6, 0xd5, 0x22, 0x91, 0x6d, 0x83, 0x98, 0x08, 0x58, 0x0a, 0xb9, 0x05, 0xe5, - 0x41, 0xd2, 0x45, 0x9d, 0x6a, 0xd9, 0x90, 0xd7, 0x8b, 0xc8, 0xf7, 0x0d, 0xa2, 0x25, 0xe2, 0x87, - 0x61, 0x8f, 0x5a, 0x3c, 0xd9, 0x87, 0x4a, 0xcc, 0xd5, 0x23, 0x21, 0x8f, 0xd2, 0xea, 0xc2, 0xfa, - 0x1c, 0x72, 0x6f, 0x16, 0x71, 0x73, 0x3e, 0x6f, 0xec, 0x65, 0x78, 0x4f, 0x29, 0x16, 0x1c, 0xf6, - 0x79, 0xac, 0xac, 0xe4, 0x58, 0x88, 0x7c, 0x02, 0x15, 0x4c, 0xb5, 0x44, 0x84, 0xb1, 0xaa, 0x56, - 0x4e, 0x3e, 0x50, 0xdb, 0x62, 0xb4, 0x2a, 0x1d, 0x33, 0x6a, 0x77, 0xe0, 0xe2, 0x09, 0x26, 0xc8, - 0x05, 0x28, 0x2b, 0x26, 0x7b, 0x5c, 0x99, 0x48, 0x2f, 0x52, 0x3b, 0x23, 0x55, 0x58, 0x60, 0x51, - 0xc8, 0x52, 0x9e, 0x62, 0x00, 0xe7, 0x70, 0x63, 0x34, 0xdd, 0x2c, 0x83, 0xd3, 0xc7, 0x7c, 0xaa, - 0x6f, 0xc0, 0xb9, 0x17, 0x22, 0x40, 0x6a, 0x50, 0xb1, 0x11, 0xc8, 0x52, 0xc7, 0xa1, 0xe3, 0x79, - 0xfd, 0x2c, 0x2c, 0x4f, 0x79, 0xbb, 0xfe, 0xd3, 0x2c, 0x54, 0x46, 0x29, 0x40, 0x3c, 0x58, 0x0c, - 0x44, 0xac, 0x30, 0x31, 0xb9, 0xb4, 0x59, 0x57, 0x18, 0xb0, 0xd6, 0x08, 0xa4, 0x59, 0x18, 0xb0, - 0x09, 0x8b, 0x7c, 0x01, 0x8b, 0x92, 0xa7, 0x62, 0x20, 0x03, 0x73, 0x6a, 0x2d, 0x71, 0xbd, 0x38, - 0x71, 0x32, 0x10, 0xe5, 0xdf, 0x0c, 0x42, 0xc9, 0xb5, 0x37, 0x52, 0x3a, 0xa1, 0x62, 0xe2, 0x2c, - 0xe0, 0x04, 0x1d, 0xa1, 0x5e, 0x96, 0x39, 0x34, 0x83, 0xf8, 0x02, 0x6f, 0x77, 0x4c, 0x47, 0x0c, - 0x24, 0x2f, 0x26, 0x11, 0x0b, 0x8c, 0x6a, 0x75, 0xde, 0xd0, 0xff, 0x5f, 0x44, 0xf7, 0x47, 0x20, - 0x3a, 0xc1, 0x6f, 0x2e, 0xa2, 0xe5, 0x41, 0xac, 0xc2, 0x3e, 0xaf, 0xff, 0xe8, 0xc0, 0xf2, 0xd4, - 0x5d, 0xc9, 0x79, 0x98, 0x0f, 0xfb, 0xac, 0xc7, 0x6d, 0xa4, 0xb2, 0x09, 0x69, 0x43, 0x19, 0x9f, - 0x35, 0x8f, 0xb2, 0x38, 0xb9, 0xcd, 0x77, 0x5e, 0xe9, 0xb4, 0xc6, 0x57, 0x06, 0xdf, 0x8e, 0x95, - 0x3c, 0xa6, 0x96, 0xac, 0xe3, 0x1d, 0x88, 0x7e, 0x9f, 0xc5, 0xfa, 0xc9, 0x99, 0x78, 0xdb, 0x29, - 0x21, 0xe0, 0x60, 0x4a, 0xa4, 0xe8, 0x0a, 0xbd, 0x6c, 0xc6, 0x64, 0x05, 0xe6, 0x78, 0x3c, 0xc4, - 0xeb, 0xe9, 0x25, 0x3d, 0xd4, 0x2b, 0xdd, 0x50, 0x9a, 0xc7, 0x82, 0x2b, 0x38, 0xd4, 0x3c, 0xac, - 0x45, 0x12, 0xdf, 0x80, 0x5e, 0x32, 0x63, 0x72, 0x13, 0xca, 0x7d, 0x81, 0x17, 0x4c, 0x31, 0x89, - 0xf5, 0x61, 0x2f, 0x15, 0x1d, 0x76, 0x57, 0x23, 0x6c, 0x49, 0xb0, 0x70, 0x72, 0x1b, 0xce, 0xa5, - 0x4a, 0x24, 0x07, 0x3d, 0x89, 0xae, 0x3a, 0x48, 0xb8, 0x0c, 0x45, 0xb7, 0xba, 0x78, 0x72, 0x65, - 0xd9, 0xb2, 0x5d, 0x8f, 0x9e, 0xd5, 0xb4, 0x6d, 0xcd, 0xf2, 0x0d, 0x89, 0xf8, 0xb0, 0x94, 0x0c, - 0xa2, 0xe8, 0x40, 0x24, 0x59, 0x81, 0x03, 0x23, 0xf2, 0x1f, 0xbc, 0xe6, 0x23, 0xeb, 0x6e, 0x46, - 0xa2, 0x6e, 0x32, 0x99, 0xd4, 0x3e, 0x04, 0x37, 0xe7, 0x51, 0xed, 0x89, 0x23, 0x7e, 0x6c, 0x83, - 0xa4, 0x87, 0x3a, 0x70, 0x43, 0x16, 0x0d, 0xb2, 0xf6, 0x88, 0x81, 0x33, 0x93, 0x8f, 0x66, 0x6f, - 0x95, 0x6a, 0x4d, 0x70, 0x73, 0xb2, 0xe4, 0x35, 0x58, 0x96, 0xbc, 0x17, 0xa6, 0x28, 0x73, 0xc0, - 0x06, 0xea, 0xb0, 0xfa, 0xb9, 0x21, 0x2c, 0x8d, 0x16, 0x3d, 0x5c, 0xab, 0xff, 0x8d, 0xbd, 0x23, - 0xff, 0xce, 0x49, 0x2b, 0x7b, 0x90, 0xc6, 0xe2, 0x99, 0xe6, 0xc6, 0xab, 0xea, 0x82, 0x49, 0xff, - 0x68, 0xa0, 0x2d, 0xee, 0xea, 0x9e, 0x6c, 0xc8, 0xe4, 0x03, 0x98, 0x4f, 0x84, 0x54, 0xa3, 0x2c, - 0x5a, 0x2d, 0x4c, 0x59, 0x04, 0xd8, 0xca, 0x94, 0x81, 0xeb, 0x87, 0x70, 0x66, 0x5a, 0x0d, 0x5b, - 0xcf, 0xdc, 0x83, 0x1d, 0x1f, 0xbb, 0xd8, 0x65, 0x6c, 0x3c, 0x17, 0xa7, 0x37, 0x1f, 0x84, 0x52, - 0x0d, 0x58, 0xb4, 0xe3, 0x93, 0xb7, 0xb1, 0x41, 0xed, 0xed, 0x53, 0x8a, 0x6d, 0x6c, 0x0d, 0x71, - 0x97, 0xa7, 0x71, 0x7a, 0x0b, 0xc3, 0xde, 0xa5, 0xa2, 0x33, 0x6e, 0x53, 0x3f, 0xcc, 0x82, 0x6b, - 0x6b, 0xd8, 0xe9, 0xb6, 0xa9, 0xcf, 0x60, 0xb9, 0x2b, 0xb1, 0xb5, 0xca, 0x83, 0xc0, 0x5c, 0xcd, - 0x16, 0x8e, 0x5a, 0x61, 0x56, 0x19, 0x20, 0x5d, 0xca, 0x08, 0xb6, 0x82, 0x5e, 0x85, 0xa5, 0x30, - 0x19, 0xde, 0x38, 0xe0, 0x31, 0xeb, 0x44, 0xb6, 0x63, 0x55, 0xa8, 0xab, 0xd7, 0xda, 0xd9, 0x92, - 0xae, 0x8a, 0xe8, 0x7c, 0x2e, 0x63, 0xdb, 0x8b, 0x2a, 0x74, 0x3c, 0x27, 0x9f, 0x82, 0x13, 0x26, - 0xac, 0x6f, 0x4b, 0x45, 0xe1, 0x0d, 0x76, 0x7c, 0x6f, 0xd7, 0xa6, 0xc8, 0x66, 0xe5, 0xf9, 0xd3, - 0x35, 0x47, 0x2f, 0x50, 0x43, 0xab, 0xff, 0x3e, 0x07, 0x6e, 0x2b, 0x1a, 0xa4, 0xca, 0x16, 0x89, - 0x53, 0xf3, 0xcb, 0xd7, 0x70, 0x8e, 0x99, 0x9f, 0x16, 0x16, 0xeb, 0x17, 0x67, 0xaa, 0x9c, 0xf5, - 0xcd, 0xb5, 0x42, 0xb9, 0x31, 0x38, 0xab, 0x88, 0x56, 0x73, 0x85, 0xfd, 0x6b, 0x1d, 0xfb, 0xe3, - 0xb2, 0x90, 0xc1, 0x21, 0x96, 0xcb, 0xec, 0x89, 0xda, 0x16, 0x5f, 0xf8, 0xf3, 0x77, 0x37, 0x0f, - 0xcc, 0xfc, 0x6d, 0x75, 0xa7, 0x35, 0xb0, 0x5d, 0x3b, 0x92, 0x3d, 0x1c, 0xd5, 0xeb, 0xc2, 0xec, - 0xa5, 0xb8, 0x3f, 0x25, 0x61, 0x18, 0xe4, 0x4b, 0x80, 0x6e, 0x98, 0x26, 0x4c, 0xa1, 0x9c, 0xb4, - 0x51, 0x28, 0xbc, 0xe0, 0xd6, 0x18, 0x35, 0xa5, 0x92, 0x63, 0x93, 0x3b, 0xd8, 0xc3, 0xd8, 0x28, - 0x8f, 0xca, 0x27, 0x57, 0xa7, 0x96, 0x67, 0x25, 0x56, 0xb4, 0x04, 0x46, 0xb4, 0x32, 0x5a, 0xa1, - 0x95, 0x80, 0xd9, 0xbd, 0x2b, 0x4f, 0x9e, 0xad, 0xce, 0xfc, 0x81, 0xdf, 0x5f, 0xcf, 0x56, 0x4b, - 0xdf, 0x3e, 0x5f, 0x2d, 0x3d, 0xc1, 0xef, 0x37, 0xfc, 0xfe, 0xc4, 0xaf, 0x53, 0x36, 0xbf, 0xf3, - 0xef, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0x3b, 0x66, 0xa6, 0x7e, 0x2d, 0x0c, 0x00, 0x00, + // 1320 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0xcd, 0x72, 0x1b, 0x45, + 0x17, 0xf5, 0xcf, 0x58, 0x96, 0xee, 0xd8, 0x89, 0xd2, 0x95, 0x2f, 0x51, 0x94, 0x7c, 0xb6, 0x23, + 0x02, 0x04, 0xaa, 0x90, 0x41, 0x50, 0xf9, 0xe1, 0xa7, 0x40, 0x96, 0x84, 0x63, 0x12, 0x3b, 0x53, + 0xed, 0x24, 0x2c, 0x55, 0xed, 0x99, 0x8e, 0x3c, 0xe5, 0xd1, 0xcc, 0xd0, 0xd3, 0xa3, 0x94, 0x77, + 0x2c, 0x53, 0x2c, 0xd8, 0xc1, 0x8e, 0x05, 0xc5, 0x3b, 0xf0, 0x0c, 0x59, 0xb2, 0xa1, 0x8a, 0x55, + 0x8a, 0xe4, 0x09, 0xa8, 0xe2, 0x05, 0xb8, 0xdd, 0xd3, 0x92, 0x46, 0x64, 0x9c, 0xb0, 0xc8, 0x62, + 0xaa, 0xba, 0x7b, 0xce, 0x39, 0xdd, 0x73, 0xef, 0xe9, 0x7b, 0x25, 0xb0, 0x93, 0x98, 0xbb, 0x49, + 0x33, 0x16, 0x91, 0x8c, 0x08, 0xf1, 0x22, 0xf7, 0x88, 0x8b, 0x66, 0xf2, 0x88, 0x89, 0xe1, 0x91, + 0x2f, 0x9b, 0xa3, 0x0f, 0xea, 0xb6, 0x3c, 0x8e, 0xb9, 0x01, 0xd4, 0xcf, 0x0e, 0xa2, 0x41, 0xa4, + 0x87, 0x9b, 0x6a, 0x64, 0x56, 0xcf, 0x7b, 0xa9, 0x60, 0xd2, 0x8f, 0xc2, 0xcd, 0xf1, 0x20, 0x7b, + 0xd1, 0xf8, 0xde, 0x82, 0xf2, 0x5e, 0xe4, 0xf1, 0x7d, 0xdc, 0x83, 0x6c, 0x83, 0xcd, 0xc2, 0x30, + 0x92, 0x1a, 0x90, 0xd4, 0xe6, 0x37, 0xe6, 0xaf, 0xda, 0xad, 0xf5, 0xe6, 0x8b, 0x5b, 0x36, 0xdb, + 0x53, 0xd8, 0x96, 0xf5, 0xe4, 0xe9, 0xfa, 0x1c, 0xcd, 0x33, 0xc9, 0xfb, 0x60, 0x89, 0x28, 0xe0, + 0xb5, 0x05, 0x54, 0x38, 0xd5, 0xba, 0x54, 0xa4, 0xa0, 0x36, 0xa5, 0x88, 0xa1, 0x1a, 0x89, 0x5b, + 0xc3, 0x90, 0x0f, 0x0f, 0xb8, 0x48, 0x0e, 0xfd, 0xb8, 0xb6, 0xa8, 0x79, 0x6f, 0x9f, 0xc4, 0x53, + 0x87, 0x6d, 0xee, 0x4e, 0xe0, 0x34, 0x47, 0x25, 0xbb, 0xb0, 0xc2, 0x46, 0xcc, 0x0f, 0xd8, 0x81, + 0x1f, 0xf8, 0xf2, 0xb8, 0x66, 0x69, 0xa9, 0x77, 0x5e, 0x2a, 0xd5, 0xce, 0x11, 0xe8, 0x0c, 0xbd, + 0xe1, 0x01, 0x4c, 0x37, 0x22, 0x6f, 0xc1, 0xb2, 0xd3, 0xdb, 0xeb, 0xee, 0xec, 0x6d, 0x57, 0xe7, + 0xea, 0x17, 0xbe, 0xfb, 0x69, 0xe3, 0x7f, 0x4a, 0x63, 0x0a, 0x70, 0x78, 0xe8, 0xf9, 0xe1, 0x80, + 0x5c, 0x85, 0x72, 0xbb, 0xd3, 0xe9, 0x39, 0xf7, 0x7a, 0xdd, 0xea, 0x7c, 0xbd, 0x8e, 0xc0, 0x73, + 0xb3, 0xc0, 0xb6, 0xeb, 0xf2, 0x58, 0x72, 0xaf, 0x6e, 0x3d, 0xfe, 0x65, 0x6d, 0xae, 0xf1, 0x78, + 0x1e, 0x56, 0xf2, 0x87, 0xc0, 0x8d, 0x4a, 0xed, 0xce, 0xbd, 0x9d, 0x07, 0x3d, 0xdc, 0x67, 0x42, + 0xcf, 0x23, 0xda, 0xae, 0xf4, 0x47, 0x9c, 0x5c, 0x81, 0x25, 0xa7, 0x7d, 0x7f, 0xbf, 0x87, 0xbb, + 0x4c, 0x8e, 0x93, 0x87, 0x39, 0x2c, 0x4d, 0x34, 0xaa, 0x4b, 0xdb, 0x3b, 0x7b, 0xd5, 0x85, 0x62, + 0x54, 0x57, 0x30, 0x3f, 0x34, 0x47, 0xf9, 0xd5, 0x02, 0x7b, 0x9f, 0x8b, 0x91, 0xef, 0xbe, 0x66, + 0x4f, 0x5c, 0x03, 0x4b, 0xb2, 0xe4, 0x48, 0x7b, 0xc2, 0x2e, 0xf6, 0xc4, 0x3d, 0x7c, 0xaf, 0x36, + 0x35, 0x74, 0x8d, 0x57, 0xce, 0x10, 0x3c, 0x0e, 0x7c, 0x97, 0x61, 0xbc, 0xb4, 0x33, 0xec, 0xd6, + 0x9b, 0x45, 0x6c, 0x3a, 0x41, 0x99, 0xf3, 0xdf, 0x9a, 0xa3, 0x39, 0x2a, 0xf9, 0x04, 0x4a, 0x83, + 0x20, 0x3a, 0x60, 0x81, 0xf6, 0x84, 0xdd, 0xba, 0x5c, 0x24, 0xb2, 0xad, 0x11, 0x53, 0x01, 0x43, + 0x21, 0x37, 0xa0, 0x94, 0xc6, 0x1e, 0xea, 0xd4, 0x4a, 0x9a, 0xbc, 0x51, 0x44, 0xbe, 0xaf, 0x11, + 0x9d, 0x28, 0x7c, 0xe8, 0x0f, 0xa8, 0xc1, 0x93, 0x7d, 0x28, 0x87, 0x5c, 0x3e, 0x8a, 0xc4, 0x51, + 0x52, 0x5b, 0xde, 0x58, 0x44, 0xee, 0xf5, 0x22, 0x6e, 0x2e, 0xe6, 0xcd, 0xbd, 0x0c, 0xdf, 0x96, + 0x92, 0xb9, 0x87, 0x43, 0x1e, 0x4a, 0x23, 0x39, 0x11, 0x22, 0x9f, 0x42, 0x19, 0xad, 0x16, 0x47, + 0x7e, 0x28, 0x6b, 0xe5, 0x93, 0x0f, 0xd4, 0x33, 0x18, 0xa5, 0x4a, 0x27, 0x8c, 0xfa, 0x6d, 0x38, + 0x7f, 0xc2, 0x16, 0xe4, 0x1c, 0x94, 0x24, 0x13, 0x03, 0x2e, 0x75, 0xa6, 0x2b, 0xd4, 0xcc, 0x48, + 0x0d, 0x96, 0x59, 0xe0, 0xb3, 0x84, 0x27, 0x98, 0xc0, 0x45, 0x7c, 0x31, 0x9e, 0x6e, 0x95, 0xc0, + 0x1a, 0xa2, 0x9f, 0x1a, 0x9b, 0x70, 0xe6, 0x85, 0x0c, 0x90, 0x3a, 0x94, 0x4d, 0x06, 0x32, 0xeb, + 0x58, 0x74, 0x32, 0x6f, 0x9c, 0x86, 0xd5, 0x99, 0x68, 0x37, 0x7e, 0x5f, 0x80, 0xf2, 0xd8, 0x02, + 0xa4, 0x0d, 0x15, 0x37, 0x0a, 0x25, 0x1a, 0x93, 0x0b, 0xe3, 0xba, 0xc2, 0x84, 0x75, 0xc6, 0x20, + 0xc5, 0xc2, 0x84, 0x4d, 0x59, 0xe4, 0x4b, 0xa8, 0x08, 0x9e, 0x44, 0xa9, 0x70, 0xf5, 0xa9, 0x95, + 0xc4, 0xd5, 0x62, 0xe3, 0x64, 0x20, 0xca, 0xbf, 0x49, 0x7d, 0xc1, 0x55, 0x34, 0x12, 0x3a, 0xa5, + 0xa2, 0x71, 0x96, 0x71, 0x82, 0x81, 0x90, 0x2f, 0x73, 0x0e, 0xcd, 0x20, 0x4e, 0x84, 0x5f, 0x77, + 0x4c, 0xc7, 0x0c, 0x24, 0x57, 0xe2, 0x80, 0xb9, 0x5a, 0xb5, 0xb6, 0xa4, 0xe9, 0xff, 0x2f, 0xa2, + 0x3b, 0x63, 0x10, 0x9d, 0xe2, 0xc9, 0x4d, 0x80, 0x20, 0x1a, 0xf4, 0x3d, 0x81, 0x77, 0x5d, 0x18, + 0xe7, 0xd5, 0x8b, 0xd8, 0x5d, 0x8d, 0xa0, 0x15, 0x44, 0x67, 0xc3, 0xad, 0x0a, 0x1e, 0x3a, 0x0d, + 0xa5, 0x3f, 0xe4, 0x8d, 0x1f, 0x2d, 0x58, 0x9d, 0x09, 0x13, 0x39, 0x0b, 0x4b, 0xfe, 0x90, 0x0d, + 0xb8, 0x49, 0x72, 0x36, 0x21, 0x3d, 0x28, 0x61, 0x45, 0xe0, 0x41, 0x96, 0x62, 0xbb, 0xf5, 0xde, + 0x2b, 0xe3, 0xdd, 0xbc, 0xa3, 0xf1, 0xbd, 0x50, 0x8a, 0x63, 0x6a, 0xc8, 0xca, 0x2a, 0x6e, 0x34, + 0x1c, 0xb2, 0x50, 0xdd, 0x56, 0x6d, 0x15, 0x33, 0x25, 0x04, 0x2c, 0x74, 0x53, 0x82, 0x51, 0x54, + 0xcb, 0x7a, 0x4c, 0xaa, 0xb0, 0xc8, 0xc3, 0x11, 0x46, 0x46, 0x2d, 0xa9, 0xa1, 0x5a, 0xf1, 0xfc, + 0xec, 0x6b, 0x71, 0x05, 0x87, 0x8a, 0x87, 0x65, 0x4c, 0xe0, 0xf5, 0x51, 0x4b, 0x7a, 0x4c, 0xae, + 0x43, 0x69, 0x18, 0xe1, 0x07, 0x26, 0xe8, 0x7f, 0x75, 0xd8, 0x0b, 0x45, 0x87, 0xdd, 0x55, 0x08, + 0x53, 0x4d, 0x0c, 0x9c, 0xdc, 0x82, 0x33, 0x89, 0x8c, 0xe2, 0xfe, 0x40, 0x60, 0x94, 0xfb, 0x31, + 0x17, 0x7e, 0xe4, 0xd5, 0x2a, 0x27, 0x17, 0xa5, 0xae, 0x69, 0x98, 0xf4, 0xb4, 0xa2, 0x6d, 0x2b, + 0x96, 0xa3, 0x49, 0xc4, 0x81, 0x95, 0x38, 0x0d, 0x82, 0x7e, 0x14, 0x67, 0xb5, 0x11, 0xb4, 0xc8, + 0x7f, 0x88, 0x9a, 0x83, 0xac, 0xbb, 0x19, 0x89, 0xda, 0xf1, 0x74, 0x52, 0xbf, 0x09, 0x76, 0x2e, + 0xa2, 0x2a, 0x12, 0x47, 0xfc, 0xd8, 0x24, 0x49, 0x0d, 0x55, 0xe2, 0x46, 0x2c, 0x48, 0xb3, 0xce, + 0x8a, 0x89, 0xd3, 0x93, 0x8f, 0x17, 0x6e, 0xcc, 0xd7, 0x5b, 0x60, 0xe7, 0x64, 0xc9, 0x1b, 0xb0, + 0x2a, 0xf8, 0xc0, 0x4f, 0x50, 0xa6, 0xcf, 0x52, 0x79, 0x58, 0xfb, 0x42, 0x13, 0x56, 0xc6, 0x8b, + 0x6d, 0x5c, 0x6b, 0xfc, 0x8d, 0x6d, 0x27, 0x5f, 0x22, 0x48, 0x27, 0xbb, 0xcb, 0x7a, 0xc7, 0x53, + 0xad, 0xcd, 0x57, 0x95, 0x14, 0x7d, 0x73, 0x82, 0x54, 0xed, 0xb8, 0xab, 0xda, 0xb9, 0x26, 0x93, + 0x8f, 0x60, 0x29, 0x8e, 0x84, 0x1c, 0xbb, 0x68, 0xad, 0xd0, 0xed, 0x08, 0x30, 0x45, 0x2d, 0x03, + 0x37, 0x0e, 0xe1, 0xd4, 0xac, 0x1a, 0x76, 0xad, 0xc5, 0x07, 0x3b, 0x0e, 0x36, 0xc0, 0x8b, 0xd8, + 0xb3, 0xce, 0xcf, 0xbe, 0x7c, 0xe0, 0x0b, 0x99, 0xb2, 0x60, 0xc7, 0x21, 0xef, 0x62, 0x6f, 0xdb, + 0xdb, 0xa7, 0x14, 0x3b, 0xe0, 0x3a, 0xe2, 0x2e, 0xce, 0xe2, 0xd4, 0x2b, 0x4c, 0xbb, 0x47, 0xa3, + 0x83, 0x49, 0x87, 0xfb, 0x61, 0x01, 0x6c, 0x53, 0xfe, 0x5e, 0x6f, 0x87, 0xfb, 0x1c, 0x56, 0xb3, + 0x9b, 0xda, 0x77, 0xf5, 0xa7, 0x99, 0x9a, 0xf3, 0xb2, 0x0b, 0xbb, 0x92, 0x11, 0x4c, 0xf1, 0xbd, + 0x0c, 0x2b, 0x7e, 0x3c, 0xba, 0xd6, 0xe7, 0x21, 0x3b, 0x08, 0x4c, 0xb3, 0x2b, 0x53, 0x5b, 0xad, + 0xf5, 0xb2, 0x25, 0x55, 0x50, 0x31, 0xf8, 0x5c, 0x84, 0xa6, 0x8d, 0x95, 0xe9, 0x64, 0x4e, 0x3e, + 0x03, 0xcb, 0x8f, 0xd9, 0xd0, 0x54, 0x99, 0xc2, 0x2f, 0xd8, 0x71, 0xda, 0xbb, 0xc6, 0x22, 0x5b, + 0xe5, 0xe7, 0x4f, 0xd7, 0x2d, 0xb5, 0x40, 0x35, 0xad, 0xf1, 0x33, 0x76, 0xfe, 0x4e, 0x90, 0x26, + 0xd2, 0x14, 0x89, 0xd7, 0x16, 0x97, 0xaf, 0xe1, 0x0c, 0xd3, 0xbf, 0x77, 0x58, 0xa8, 0x6e, 0x9c, + 0x2e, 0x90, 0x26, 0x36, 0x57, 0x0a, 0xe5, 0x26, 0xe0, 0xac, 0x98, 0x1a, 0xcd, 0x2a, 0xfb, 0xd7, + 0x3a, 0xb6, 0xd6, 0xd5, 0x48, 0xb8, 0x87, 0x58, 0x69, 0xb3, 0x2b, 0x6a, 0x7e, 0x1d, 0x14, 0xfe, + 0x6e, 0xbc, 0x9b, 0x07, 0x66, 0xf1, 0x36, 0xba, 0xb3, 0x1a, 0xd8, 0xe9, 0x2d, 0xc1, 0x1e, 0x8e, + 0x4b, 0x7d, 0xa1, 0x7b, 0x29, 0xbe, 0x9f, 0x91, 0xd0, 0x0c, 0xf2, 0x15, 0x80, 0xe7, 0x27, 0x31, + 0x93, 0x28, 0x27, 0x4c, 0x16, 0x0a, 0x3f, 0xb0, 0x3b, 0x41, 0xcd, 0xa8, 0xe4, 0xd8, 0xe4, 0x36, + 0xb6, 0x3f, 0x36, 0xf6, 0x51, 0xe9, 0xe4, 0xea, 0xd4, 0x69, 0x1b, 0x89, 0xaa, 0x92, 0xc0, 0x8c, + 0x96, 0xc7, 0x2b, 0xb4, 0xec, 0x32, 0xe3, 0xab, 0x5b, 0x40, 0x3c, 0xfe, 0x90, 0xa5, 0x81, 0xec, + 0xe7, 0xda, 0xc9, 0xf2, 0x2b, 0xdd, 0x59, 0x35, 0xac, 0x3b, 0x93, 0xae, 0x72, 0xe9, 0xc9, 0xb3, + 0xb5, 0xb9, 0x3f, 0xf0, 0xf9, 0xeb, 0xd9, 0xda, 0xfc, 0xb7, 0xcf, 0xd7, 0xe6, 0x9f, 0xe0, 0xf3, + 0x1b, 0x3e, 0x7f, 0xe2, 0x73, 0x50, 0xd2, 0xff, 0x29, 0x3e, 0xfc, 0x27, 0x00, 0x00, 0xff, 0xff, + 0xde, 0xdd, 0x4d, 0x58, 0xb2, 0x0c, 0x00, 0x00, } diff --git a/vendor/src/github.com/docker/swarmkit/api/specs.proto b/vendor/src/github.com/docker/swarmkit/api/specs.proto index b012ec6611..4b4e58769a 100644 --- a/vendor/src/github.com/docker/swarmkit/api/specs.proto +++ b/vendor/src/github.com/docker/swarmkit/api/specs.proto @@ -114,6 +114,10 @@ message TaskSpec { // Placement specifies node selection constraints Placement placement = 5; + + // LogDriver specifies the log driver to use for the task. Any runtime will + // direct logs into the specified driver for the duration of the task. + Driver log_driver = 6; } // Container specifies runtime parameters for a container. @@ -243,4 +247,11 @@ message ClusterSpec { // CAConfig defines cluster-level certificate authority settings. CAConfig ca_config = 6 [(gogoproto.nullable) = false, (gogoproto.customname) = "CAConfig"]; + + // DefaultLogDriver specifies the log driver to use for the cluster if not + // specified for each task. + // + // If this is changed, only new tasks will pick up the new log driver. + // Existing tasks will continue to use the previous default until rescheduled. + Driver default_log_driver = 7; } diff --git a/vendor/src/github.com/docker/swarmkit/api/types.pb.go b/vendor/src/github.com/docker/swarmkit/api/types.pb.go index 065a58c217..c3ea0d2b09 100644 --- a/vendor/src/github.com/docker/swarmkit/api/types.pb.go +++ b/vendor/src/github.com/docker/swarmkit/api/types.pb.go @@ -146,6 +146,8 @@ import docker_swarmkit_v1 "github.com/docker/swarmkit/api/timestamp" import docker_swarmkit_v11 "github.com/docker/swarmkit/api/duration" import _ "github.com/gogo/protobuf/gogoproto" +import os "os" + import strings "strings" import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" import sort "sort" @@ -310,15 +312,18 @@ type Mount_MountType int32 const ( MountTypeBind Mount_MountType = 0 MountTypeVolume Mount_MountType = 1 + MountTypeTmpfs Mount_MountType = 2 ) var Mount_MountType_name = map[int32]string{ 0: "BIND", 1: "VOLUME", + 2: "TMPFS", } var Mount_MountType_value = map[string]int32{ "BIND": 0, "VOLUME": 1, + "TMPFS": 2, } func (x Mount_MountType) String() string { @@ -640,17 +645,26 @@ func (*Image) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{1 type Mount struct { // Type defines the nature of the mount. Type Mount_MountType `protobuf:"varint,1,opt,name=type,proto3,enum=docker.swarmkit.v1.Mount_MountType" json:"type,omitempty"` - // Source path to mount + // Source specifies the name of the mount. Depending on mount type, this + // may be a volume name or a host path, or even ignored. Source string `protobuf:"bytes,2,opt,name=source,proto3" json:"source,omitempty"` // Target path in container Target string `protobuf:"bytes,3,opt,name=target,proto3" json:"target,omitempty"` - // Writable should be set to true if the mount should be writable from the - // container. - Writable bool `protobuf:"varint,4,opt,name=writable,proto3" json:"writable,omitempty"` + // ReadOnly should be set to true if the mount should not be writable. + ReadOnly bool `protobuf:"varint,4,opt,name=readonly,proto3" json:"readonly,omitempty"` // BindOptions configures properties of a bind mount type. + // + // For mounts of type bind, the source must be an absolute host path. BindOptions *Mount_BindOptions `protobuf:"bytes,5,opt,name=bind_options,json=bindOptions" json:"bind_options,omitempty"` // VolumeOptions configures the properties specific to a volume mount type. + // + // For mounts of type volume, the source will be used as the volume name. VolumeOptions *Mount_VolumeOptions `protobuf:"bytes,6,opt,name=volume_options,json=volumeOptions" json:"volume_options,omitempty"` + // TmpfsOptions allows one to set options for mounting a temporary + // filesystem. + // + // The source field will be ignored when using mounts of type tmpfs. + TmpfsOptions *Mount_TmpfsOptions `protobuf:"bytes,7,opt,name=tmpfs_options,json=tmpfsOptions" json:"tmpfs_options,omitempty"` } func (m *Mount) Reset() { *m = Mount{} } @@ -669,8 +683,8 @@ func (*Mount_BindOptions) Descriptor() ([]byte, []int) { return fileDescriptorTy // VolumeOptions contains parameters for mounting the volume. type Mount_VolumeOptions struct { - // populate volume with data from target - Populate bool `protobuf:"varint,1,opt,name=populate,proto3" json:"populate,omitempty"` + // nocopy prevents automatic copying of data to the volume with data from target + NoCopy bool `protobuf:"varint,1,opt,name=nocopy,proto3" json:"nocopy,omitempty"` // labels to apply to the volume if creating Labels map[string]string `protobuf:"bytes,2,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // DriverConfig specifies the options that may be passed to the driver @@ -684,6 +698,24 @@ func (m *Mount_VolumeOptions) Reset() { *m = Mount_VolumeOpti func (*Mount_VolumeOptions) ProtoMessage() {} func (*Mount_VolumeOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11, 1} } +type Mount_TmpfsOptions struct { + // Size sets the size of the tmpfs, in bytes. + // + // This will be converted to an operating system specific value + // depending on the host. For example, on linux, it will be convered to + // use a 'k', 'm' or 'g' syntax. BSD, though not widely supported with + // docker, uses a straight byte value. + // + // Percentages are not supported. + SizeBytes int64 `protobuf:"varint,1,opt,name=size_bytes,json=sizeBytes,proto3" json:"size_bytes,omitempty"` + // Mode of the tmpfs upon creation + Mode os.FileMode `protobuf:"varint,2,opt,name=mode,proto3,customtype=os.FileMode" json:"mode"` +} + +func (m *Mount_TmpfsOptions) Reset() { *m = Mount_TmpfsOptions{} } +func (*Mount_TmpfsOptions) ProtoMessage() {} +func (*Mount_TmpfsOptions) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11, 2} } + type RestartPolicy struct { Condition RestartPolicy_RestartCondition `protobuf:"varint,1,opt,name=condition,proto3,enum=docker.swarmkit.v1.RestartPolicy_RestartCondition" json:"condition,omitempty"` // Delay between restart attempts @@ -955,7 +987,7 @@ type AcceptancePolicy_RoleAdmissionPolicy struct { Autoaccept bool `protobuf:"varint,2,opt,name=autoaccept,proto3" json:"autoaccept,omitempty"` // Secret represents a user-provided string that is necessary for new // nodes to join the cluster - Secret *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret `protobuf:"bytes,3,opt,name=secret" json:"secret,omitempty"` + Secret *AcceptancePolicy_RoleAdmissionPolicy_Secret `protobuf:"bytes,3,opt,name=secret" json:"secret,omitempty"` } func (m *AcceptancePolicy_RoleAdmissionPolicy) Reset() { *m = AcceptancePolicy_RoleAdmissionPolicy{} } @@ -964,18 +996,18 @@ func (*AcceptancePolicy_RoleAdmissionPolicy) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23, 0} } -type AcceptancePolicy_RoleAdmissionPolicy_HashedSecret struct { - // The actual hashed content +type AcceptancePolicy_RoleAdmissionPolicy_Secret struct { + // The actual content (possibly hashed) Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` - // The type of hash we are using + // The type of hash we are using, or "plaintext" Alg string `protobuf:"bytes,2,opt,name=alg,proto3" json:"alg,omitempty"` } -func (m *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) Reset() { - *m = AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{} +func (m *AcceptancePolicy_RoleAdmissionPolicy_Secret) Reset() { + *m = AcceptancePolicy_RoleAdmissionPolicy_Secret{} } -func (*AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) ProtoMessage() {} -func (*AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) Descriptor() ([]byte, []int) { +func (*AcceptancePolicy_RoleAdmissionPolicy_Secret) ProtoMessage() {} +func (*AcceptancePolicy_RoleAdmissionPolicy_Secret) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23, 0, 0} } @@ -1133,6 +1165,7 @@ func init() { proto.RegisterType((*Mount)(nil), "docker.swarmkit.v1.Mount") proto.RegisterType((*Mount_BindOptions)(nil), "docker.swarmkit.v1.Mount.BindOptions") proto.RegisterType((*Mount_VolumeOptions)(nil), "docker.swarmkit.v1.Mount.VolumeOptions") + proto.RegisterType((*Mount_TmpfsOptions)(nil), "docker.swarmkit.v1.Mount.TmpfsOptions") proto.RegisterType((*RestartPolicy)(nil), "docker.swarmkit.v1.RestartPolicy") proto.RegisterType((*UpdateConfig)(nil), "docker.swarmkit.v1.UpdateConfig") proto.RegisterType((*ContainerStatus)(nil), "docker.swarmkit.v1.ContainerStatus") @@ -1146,7 +1179,7 @@ func init() { proto.RegisterType((*IssuanceStatus)(nil), "docker.swarmkit.v1.IssuanceStatus") proto.RegisterType((*AcceptancePolicy)(nil), "docker.swarmkit.v1.AcceptancePolicy") proto.RegisterType((*AcceptancePolicy_RoleAdmissionPolicy)(nil), "docker.swarmkit.v1.AcceptancePolicy.RoleAdmissionPolicy") - proto.RegisterType((*AcceptancePolicy_RoleAdmissionPolicy_HashedSecret)(nil), "docker.swarmkit.v1.AcceptancePolicy.RoleAdmissionPolicy.HashedSecret") + proto.RegisterType((*AcceptancePolicy_RoleAdmissionPolicy_Secret)(nil), "docker.swarmkit.v1.AcceptancePolicy.RoleAdmissionPolicy.Secret") proto.RegisterType((*ExternalCA)(nil), "docker.swarmkit.v1.ExternalCA") proto.RegisterType((*CAConfig)(nil), "docker.swarmkit.v1.CAConfig") proto.RegisterType((*OrchestrationConfig)(nil), "docker.swarmkit.v1.OrchestrationConfig") @@ -1343,9 +1376,10 @@ func (m *Mount) Copy() *Mount { Type: m.Type, Source: m.Source, Target: m.Target, - Writable: m.Writable, + ReadOnly: m.ReadOnly, BindOptions: m.BindOptions.Copy(), VolumeOptions: m.VolumeOptions.Copy(), + TmpfsOptions: m.TmpfsOptions.Copy(), } return o @@ -1369,7 +1403,7 @@ func (m *Mount_VolumeOptions) Copy() *Mount_VolumeOptions { } o := &Mount_VolumeOptions{ - Populate: m.Populate, + NoCopy: m.NoCopy, DriverConfig: m.DriverConfig.Copy(), } @@ -1383,6 +1417,19 @@ func (m *Mount_VolumeOptions) Copy() *Mount_VolumeOptions { return o } +func (m *Mount_TmpfsOptions) Copy() *Mount_TmpfsOptions { + if m == nil { + return nil + } + + o := &Mount_TmpfsOptions{ + SizeBytes: m.SizeBytes, + Mode: m.Mode, + } + + return o +} + func (m *RestartPolicy) Copy() *RestartPolicy { if m == nil { return nil @@ -1594,12 +1641,12 @@ func (m *AcceptancePolicy_RoleAdmissionPolicy) Copy() *AcceptancePolicy_RoleAdmi return o } -func (m *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) Copy() *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret { +func (m *AcceptancePolicy_RoleAdmissionPolicy_Secret) Copy() *AcceptancePolicy_RoleAdmissionPolicy_Secret { if m == nil { return nil } - o := &AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{ + o := &AcceptancePolicy_RoleAdmissionPolicy_Secret{ Data: m.Data, Alg: m.Alg, } @@ -1926,18 +1973,21 @@ func (this *Mount) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 10) + s := make([]string, 0, 11) s = append(s, "&api.Mount{") s = append(s, "Type: "+fmt.Sprintf("%#v", this.Type)+",\n") s = append(s, "Source: "+fmt.Sprintf("%#v", this.Source)+",\n") s = append(s, "Target: "+fmt.Sprintf("%#v", this.Target)+",\n") - s = append(s, "Writable: "+fmt.Sprintf("%#v", this.Writable)+",\n") + s = append(s, "ReadOnly: "+fmt.Sprintf("%#v", this.ReadOnly)+",\n") if this.BindOptions != nil { s = append(s, "BindOptions: "+fmt.Sprintf("%#v", this.BindOptions)+",\n") } if this.VolumeOptions != nil { s = append(s, "VolumeOptions: "+fmt.Sprintf("%#v", this.VolumeOptions)+",\n") } + if this.TmpfsOptions != nil { + s = append(s, "TmpfsOptions: "+fmt.Sprintf("%#v", this.TmpfsOptions)+",\n") + } s = append(s, "}") return strings.Join(s, "") } @@ -1957,7 +2007,7 @@ func (this *Mount_VolumeOptions) GoString() string { } s := make([]string, 0, 7) s = append(s, "&api.Mount_VolumeOptions{") - s = append(s, "Populate: "+fmt.Sprintf("%#v", this.Populate)+",\n") + s = append(s, "NoCopy: "+fmt.Sprintf("%#v", this.NoCopy)+",\n") keysForLabels := make([]string, 0, len(this.Labels)) for k, _ := range this.Labels { keysForLabels = append(keysForLabels, k) @@ -1977,6 +2027,17 @@ func (this *Mount_VolumeOptions) GoString() string { s = append(s, "}") return strings.Join(s, "") } +func (this *Mount_TmpfsOptions) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 6) + s = append(s, "&api.Mount_TmpfsOptions{") + s = append(s, "SizeBytes: "+fmt.Sprintf("%#v", this.SizeBytes)+",\n") + s = append(s, "Mode: "+fmt.Sprintf("%#v", this.Mode)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} func (this *RestartPolicy) GoString() string { if this == nil { return "nil" @@ -2181,12 +2242,12 @@ func (this *AcceptancePolicy_RoleAdmissionPolicy) GoString() string { s = append(s, "}") return strings.Join(s, "") } -func (this *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) GoString() string { +func (this *AcceptancePolicy_RoleAdmissionPolicy_Secret) GoString() string { if this == nil { return "nil" } s := make([]string, 0, 6) - s = append(s, "&api.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{") + s = append(s, "&api.AcceptancePolicy_RoleAdmissionPolicy_Secret{") s = append(s, "Data: "+fmt.Sprintf("%#v", this.Data)+",\n") s = append(s, "Alg: "+fmt.Sprintf("%#v", this.Alg)+",\n") s = append(s, "}") @@ -2775,10 +2836,10 @@ func (m *Mount) MarshalTo(data []byte) (int, error) { i = encodeVarintTypes(data, i, uint64(len(m.Target))) i += copy(data[i:], m.Target) } - if m.Writable { + if m.ReadOnly { data[i] = 0x20 i++ - if m.Writable { + if m.ReadOnly { data[i] = 1 } else { data[i] = 0 @@ -2805,6 +2866,16 @@ func (m *Mount) MarshalTo(data []byte) (int, error) { } i += n7 } + if m.TmpfsOptions != nil { + data[i] = 0x3a + i++ + i = encodeVarintTypes(data, i, uint64(m.TmpfsOptions.Size())) + n8, err := m.TmpfsOptions.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n8 + } return i, nil } @@ -2846,10 +2917,10 @@ func (m *Mount_VolumeOptions) MarshalTo(data []byte) (int, error) { _ = i var l int _ = l - if m.Populate { + if m.NoCopy { data[i] = 0x8 i++ - if m.Populate { + if m.NoCopy { data[i] = 1 } else { data[i] = 0 @@ -2877,11 +2948,39 @@ func (m *Mount_VolumeOptions) MarshalTo(data []byte) (int, error) { data[i] = 0x1a i++ i = encodeVarintTypes(data, i, uint64(m.DriverConfig.Size())) - n8, err := m.DriverConfig.MarshalTo(data[i:]) + n9, err := m.DriverConfig.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n8 + i += n9 + } + return i, nil +} + +func (m *Mount_TmpfsOptions) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *Mount_TmpfsOptions) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.SizeBytes != 0 { + data[i] = 0x8 + i++ + i = encodeVarintTypes(data, i, uint64(m.SizeBytes)) + } + if m.Mode != 0 { + data[i] = 0x10 + i++ + i = encodeVarintTypes(data, i, uint64(m.Mode)) } return i, nil } @@ -2910,11 +3009,11 @@ func (m *RestartPolicy) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintTypes(data, i, uint64(m.Delay.Size())) - n9, err := m.Delay.MarshalTo(data[i:]) + n10, err := m.Delay.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n9 + i += n10 } if m.MaxAttempts != 0 { data[i] = 0x18 @@ -2925,11 +3024,11 @@ func (m *RestartPolicy) MarshalTo(data []byte) (int, error) { data[i] = 0x22 i++ i = encodeVarintTypes(data, i, uint64(m.Window.Size())) - n10, err := m.Window.MarshalTo(data[i:]) + n11, err := m.Window.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n10 + i += n11 } return i, nil } @@ -2957,11 +3056,11 @@ func (m *UpdateConfig) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintTypes(data, i, uint64(m.Delay.Size())) - n11, err := m.Delay.MarshalTo(data[i:]) + n12, err := m.Delay.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n11 + i += n12 return i, nil } @@ -3018,11 +3117,11 @@ func (m *TaskStatus) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintTypes(data, i, uint64(m.Timestamp.Size())) - n12, err := m.Timestamp.MarshalTo(data[i:]) + n13, err := m.Timestamp.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n12 + i += n13 } if m.State != 0 { data[i] = 0x10 @@ -3042,11 +3141,11 @@ func (m *TaskStatus) MarshalTo(data []byte) (int, error) { i += copy(data[i:], m.Err) } if m.RuntimeStatus != nil { - nn13, err := m.RuntimeStatus.MarshalTo(data[i:]) + nn14, err := m.RuntimeStatus.MarshalTo(data[i:]) if err != nil { return 0, err } - i += nn13 + i += nn14 } return i, nil } @@ -3057,11 +3156,11 @@ func (m *TaskStatus_Container) MarshalTo(data []byte) (int, error) { data[i] = 0x2a i++ i = encodeVarintTypes(data, i, uint64(m.Container.Size())) - n14, err := m.Container.MarshalTo(data[i:]) + n15, err := m.Container.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n14 + i += n15 } return i, nil } @@ -3222,11 +3321,11 @@ func (m *IPAMOptions) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintTypes(data, i, uint64(m.Driver.Size())) - n15, err := m.Driver.MarshalTo(data[i:]) + n16, err := m.Driver.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n15 + i += n16 } if len(m.Configs) > 0 { for _, msg := range m.Configs { @@ -3292,11 +3391,11 @@ func (m *WeightedPeer) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintTypes(data, i, uint64(m.Peer.Size())) - n16, err := m.Peer.MarshalTo(data[i:]) + n17, err := m.Peer.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n16 + i += n17 } if m.Weight != 0 { data[i] = 0x10 @@ -3399,16 +3498,16 @@ func (m *AcceptancePolicy_RoleAdmissionPolicy) MarshalTo(data []byte) (int, erro data[i] = 0x1a i++ i = encodeVarintTypes(data, i, uint64(m.Secret.Size())) - n17, err := m.Secret.MarshalTo(data[i:]) + n18, err := m.Secret.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n17 + i += n18 } return i, nil } -func (m *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) Marshal() (data []byte, err error) { +func (m *AcceptancePolicy_RoleAdmissionPolicy_Secret) Marshal() (data []byte, err error) { size := m.Size() data = make([]byte, size) n, err := m.MarshalTo(data) @@ -3418,7 +3517,7 @@ func (m *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) Marshal() (data []by return data[:n], nil } -func (m *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) MarshalTo(data []byte) (int, error) { +func (m *AcceptancePolicy_RoleAdmissionPolicy_Secret) MarshalTo(data []byte) (int, error) { var i int _ = i var l int @@ -3503,11 +3602,11 @@ func (m *CAConfig) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintTypes(data, i, uint64(m.NodeCertExpiry.Size())) - n18, err := m.NodeCertExpiry.MarshalTo(data[i:]) + n19, err := m.NodeCertExpiry.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n18 + i += n19 } if len(m.ExternalCAs) > 0 { for _, msg := range m.ExternalCAs { @@ -3566,11 +3665,11 @@ func (m *DispatcherConfig) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintTypes(data, i, uint64(m.HeartbeatPeriod.Size())) - n19, err := m.HeartbeatPeriod.MarshalTo(data[i:]) + n20, err := m.HeartbeatPeriod.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n19 + i += n20 } return i, nil } @@ -3716,11 +3815,11 @@ func (m *Certificate) MarshalTo(data []byte) (int, error) { data[i] = 0x1a i++ i = encodeVarintTypes(data, i, uint64(m.Status.Size())) - n20, err := m.Status.MarshalTo(data[i:]) + n21, err := m.Status.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n20 + i += n21 if len(m.Certificate) > 0 { data[i] = 0x22 i++ @@ -4028,7 +4127,7 @@ func (m *Mount) Size() (n int) { if l > 0 { n += 1 + l + sovTypes(uint64(l)) } - if m.Writable { + if m.ReadOnly { n += 2 } if m.BindOptions != nil { @@ -4039,6 +4138,10 @@ func (m *Mount) Size() (n int) { l = m.VolumeOptions.Size() n += 1 + l + sovTypes(uint64(l)) } + if m.TmpfsOptions != nil { + l = m.TmpfsOptions.Size() + n += 1 + l + sovTypes(uint64(l)) + } return n } @@ -4054,7 +4157,7 @@ func (m *Mount_BindOptions) Size() (n int) { func (m *Mount_VolumeOptions) Size() (n int) { var l int _ = l - if m.Populate { + if m.NoCopy { n += 2 } if len(m.Labels) > 0 { @@ -4072,6 +4175,18 @@ func (m *Mount_VolumeOptions) Size() (n int) { return n } +func (m *Mount_TmpfsOptions) Size() (n int) { + var l int + _ = l + if m.SizeBytes != 0 { + n += 1 + sovTypes(uint64(m.SizeBytes)) + } + if m.Mode != 0 { + n += 1 + sovTypes(uint64(m.Mode)) + } + return n +} + func (m *RestartPolicy) Size() (n int) { var l int _ = l @@ -4302,7 +4417,7 @@ func (m *AcceptancePolicy_RoleAdmissionPolicy) Size() (n int) { return n } -func (m *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) Size() (n int) { +func (m *AcceptancePolicy_RoleAdmissionPolicy_Secret) Size() (n int) { var l int _ = l l = len(m.Data) @@ -4649,9 +4764,10 @@ func (this *Mount) String() string { `Type:` + fmt.Sprintf("%v", this.Type) + `,`, `Source:` + fmt.Sprintf("%v", this.Source) + `,`, `Target:` + fmt.Sprintf("%v", this.Target) + `,`, - `Writable:` + fmt.Sprintf("%v", this.Writable) + `,`, + `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, `BindOptions:` + strings.Replace(fmt.Sprintf("%v", this.BindOptions), "Mount_BindOptions", "Mount_BindOptions", 1) + `,`, `VolumeOptions:` + strings.Replace(fmt.Sprintf("%v", this.VolumeOptions), "Mount_VolumeOptions", "Mount_VolumeOptions", 1) + `,`, + `TmpfsOptions:` + strings.Replace(fmt.Sprintf("%v", this.TmpfsOptions), "Mount_TmpfsOptions", "Mount_TmpfsOptions", 1) + `,`, `}`, }, "") return s @@ -4681,13 +4797,24 @@ func (this *Mount_VolumeOptions) String() string { } mapStringForLabels += "}" s := strings.Join([]string{`&Mount_VolumeOptions{`, - `Populate:` + fmt.Sprintf("%v", this.Populate) + `,`, + `NoCopy:` + fmt.Sprintf("%v", this.NoCopy) + `,`, `Labels:` + mapStringForLabels + `,`, `DriverConfig:` + strings.Replace(fmt.Sprintf("%v", this.DriverConfig), "Driver", "Driver", 1) + `,`, `}`, }, "") return s } +func (this *Mount_TmpfsOptions) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Mount_TmpfsOptions{`, + `SizeBytes:` + fmt.Sprintf("%v", this.SizeBytes) + `,`, + `Mode:` + fmt.Sprintf("%v", this.Mode) + `,`, + `}`, + }, "") + return s +} func (this *RestartPolicy) String() string { if this == nil { return "nil" @@ -4867,16 +4994,16 @@ func (this *AcceptancePolicy_RoleAdmissionPolicy) String() string { s := strings.Join([]string{`&AcceptancePolicy_RoleAdmissionPolicy{`, `Role:` + fmt.Sprintf("%v", this.Role) + `,`, `Autoaccept:` + fmt.Sprintf("%v", this.Autoaccept) + `,`, - `Secret:` + strings.Replace(fmt.Sprintf("%v", this.Secret), "AcceptancePolicy_RoleAdmissionPolicy_HashedSecret", "AcceptancePolicy_RoleAdmissionPolicy_HashedSecret", 1) + `,`, + `Secret:` + strings.Replace(fmt.Sprintf("%v", this.Secret), "AcceptancePolicy_RoleAdmissionPolicy_Secret", "AcceptancePolicy_RoleAdmissionPolicy_Secret", 1) + `,`, `}`, }, "") return s } -func (this *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) String() string { +func (this *AcceptancePolicy_RoleAdmissionPolicy_Secret) String() string { if this == nil { return "nil" } - s := strings.Join([]string{`&AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{`, + s := strings.Join([]string{`&AcceptancePolicy_RoleAdmissionPolicy_Secret{`, `Data:` + fmt.Sprintf("%v", this.Data) + `,`, `Alg:` + fmt.Sprintf("%v", this.Alg) + `,`, `}`, @@ -6501,7 +6628,7 @@ func (m *Mount) Unmarshal(data []byte) error { iNdEx = postIndex case 4: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Writable", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ReadOnly", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -6518,7 +6645,7 @@ func (m *Mount) Unmarshal(data []byte) error { break } } - m.Writable = bool(v != 0) + m.ReadOnly = bool(v != 0) case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field BindOptions", wireType) @@ -6585,6 +6712,39 @@ func (m *Mount) Unmarshal(data []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TmpfsOptions", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.TmpfsOptions == nil { + m.TmpfsOptions = &Mount_TmpfsOptions{} + } + if err := m.TmpfsOptions.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(data[iNdEx:]) @@ -6706,7 +6866,7 @@ func (m *Mount_VolumeOptions) Unmarshal(data []byte) error { switch fieldNum { case 1: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Populate", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field NoCopy", wireType) } var v int for shift := uint(0); ; shift += 7 { @@ -6723,7 +6883,7 @@ func (m *Mount_VolumeOptions) Unmarshal(data []byte) error { break } } - m.Populate = bool(v != 0) + m.NoCopy = bool(v != 0) case 2: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) @@ -6889,6 +7049,94 @@ func (m *Mount_VolumeOptions) Unmarshal(data []byte) error { } return nil } +func (m *Mount_TmpfsOptions) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TmpfsOptions: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TmpfsOptions: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SizeBytes", wireType) + } + m.SizeBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.SizeBytes |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType) + } + m.Mode = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.Mode |= (os.FileMode(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *RestartPolicy) Unmarshal(data []byte) error { l := len(data) iNdEx := 0 @@ -8642,7 +8890,7 @@ func (m *AcceptancePolicy_RoleAdmissionPolicy) Unmarshal(data []byte) error { return io.ErrUnexpectedEOF } if m.Secret == nil { - m.Secret = &AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{} + m.Secret = &AcceptancePolicy_RoleAdmissionPolicy_Secret{} } if err := m.Secret.Unmarshal(data[iNdEx:postIndex]); err != nil { return err @@ -8669,7 +8917,7 @@ func (m *AcceptancePolicy_RoleAdmissionPolicy) Unmarshal(data []byte) error { } return nil } -func (m *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) Unmarshal(data []byte) error { +func (m *AcceptancePolicy_RoleAdmissionPolicy_Secret) Unmarshal(data []byte) error { l := len(data) iNdEx := 0 for iNdEx < l { @@ -8692,10 +8940,10 @@ func (m *AcceptancePolicy_RoleAdmissionPolicy_HashedSecret) Unmarshal(data []byt fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: HashedSecret: wiretype end group for non-group") + return fmt.Errorf("proto: Secret: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: HashedSecret: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: Secret: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -10200,195 +10448,201 @@ var ( ) var fileDescriptorTypes = []byte{ - // 3030 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0x4d, 0x6c, 0x1b, 0xc7, - 0xf5, 0x17, 0x3f, 0x45, 0x0e, 0x29, 0x89, 0x5e, 0x3b, 0x8e, 0xcc, 0xe8, 0x2f, 0xfb, 0xbf, 0x89, - 0x1b, 0xe7, 0xa3, 0x4c, 0xac, 0xa4, 0x85, 0x9b, 0xa0, 0x4d, 0x96, 0x1f, 0xb2, 0x58, 0x4b, 0x14, - 0x31, 0x94, 0x64, 0x04, 0x45, 0x4b, 0xac, 0x96, 0x23, 0x71, 0xa3, 0xe5, 0x2e, 0xbb, 0xbb, 0x94, - 0x4c, 0x14, 0x05, 0x9c, 0x5e, 0x5a, 0xe4, 0xd4, 0x7b, 0x11, 0x04, 0x45, 0x8b, 0xde, 0x7a, 0x2e, - 0xd0, 0x93, 0x8f, 0x3e, 0xb6, 0x28, 0x50, 0xe4, 0x14, 0x34, 0xe9, 0xa1, 0xd7, 0x02, 0x2d, 0x9a, - 0x43, 0x7b, 0xe8, 0x7b, 0xf3, 0xb1, 0xfc, 0xf0, 0x5a, 0x71, 0x9a, 0x1c, 0x08, 0xee, 0xbc, 0xf9, - 0xbd, 0x37, 0xf3, 0xde, 0xbc, 0x79, 0x1f, 0x43, 0x0a, 0xe1, 0x78, 0xc8, 0x82, 0xca, 0xd0, 0xf7, - 0x42, 0x4f, 0xd3, 0x7a, 0x9e, 0x75, 0xc2, 0xfc, 0x4a, 0x70, 0x66, 0xfa, 0x83, 0x13, 0x3b, 0xac, - 0x9c, 0xde, 0x2c, 0x5f, 0x09, 0xed, 0x01, 0x0b, 0x42, 0x73, 0x30, 0x7c, 0x25, 0xfa, 0x12, 0xf0, - 0xf2, 0xd3, 0xbd, 0x91, 0x6f, 0x86, 0xb6, 0xe7, 0xbe, 0xa2, 0x3e, 0xe4, 0xc4, 0xa5, 0x63, 0xef, - 0xd8, 0xe3, 0x9f, 0xaf, 0xe0, 0x97, 0xa0, 0xea, 0x57, 0xc9, 0xe2, 0x01, 0xf3, 0x03, 0x80, 0x69, - 0x97, 0x48, 0xc6, 0x76, 0x7b, 0xec, 0xde, 0x6a, 0xe2, 0x5a, 0xe2, 0x46, 0x9a, 0x8a, 0x81, 0xfe, - 0xcb, 0x04, 0x29, 0x18, 0xae, 0xeb, 0x85, 0x5c, 0x56, 0xa0, 0x69, 0x24, 0xed, 0x9a, 0x03, 0xc6, - 0x41, 0x79, 0xca, 0xbf, 0xb5, 0x1a, 0xc9, 0x3a, 0xe6, 0x21, 0x73, 0x82, 0xd5, 0xe4, 0xb5, 0xd4, - 0x8d, 0xc2, 0xc6, 0x4b, 0x95, 0x47, 0xf7, 0x5c, 0x99, 0x12, 0x52, 0xd9, 0xe6, 0xe8, 0x86, 0x1b, - 0xfa, 0x63, 0x2a, 0x59, 0xcb, 0xdf, 0x22, 0x85, 0x29, 0xb2, 0x56, 0x22, 0xa9, 0x13, 0x36, 0x96, - 0xcb, 0xe0, 0x27, 0xee, 0xef, 0xd4, 0x74, 0x46, 0x0c, 0x16, 0x41, 0x9a, 0x18, 0xbc, 0x91, 0xbc, - 0x95, 0xd0, 0xdf, 0x21, 0x79, 0xca, 0x02, 0x6f, 0xe4, 0x5b, 0x2c, 0xd0, 0x5e, 0x20, 0x79, 0xd7, - 0x74, 0xbd, 0xae, 0x35, 0x1c, 0x05, 0x9c, 0x3d, 0x55, 0x2d, 0x7e, 0xfa, 0xf1, 0xd5, 0x5c, 0x0b, - 0x88, 0xb5, 0xf6, 0x7e, 0x40, 0x73, 0x38, 0x5d, 0x83, 0x59, 0xed, 0xff, 0x49, 0x71, 0xc0, 0x06, - 0x9e, 0x3f, 0xee, 0x1e, 0x8e, 0x43, 0x16, 0x70, 0xc1, 0x29, 0x5a, 0x10, 0xb4, 0x2a, 0x92, 0xf4, - 0x9f, 0x27, 0xc8, 0x25, 0x25, 0x9b, 0xb2, 0x1f, 0x8e, 0x6c, 0x9f, 0x0d, 0x98, 0x1b, 0x06, 0xda, - 0x37, 0x40, 0x67, 0x7b, 0x60, 0x87, 0x62, 0x8d, 0xc2, 0xc6, 0xff, 0xc5, 0xe9, 0x1c, 0xed, 0x8a, - 0x4a, 0xb0, 0x66, 0x90, 0xa2, 0xcf, 0x02, 0xe6, 0x9f, 0x0a, 0x4b, 0xf0, 0x25, 0x3f, 0x97, 0x79, - 0x86, 0x45, 0xdf, 0x24, 0xb9, 0xb6, 0x63, 0x86, 0x47, 0x9e, 0x3f, 0xd0, 0x74, 0x52, 0x34, 0x7d, - 0xab, 0x6f, 0x87, 0xcc, 0x0a, 0x47, 0xbe, 0x3a, 0x95, 0x19, 0x9a, 0x76, 0x99, 0x24, 0x3d, 0xb1, - 0x50, 0xbe, 0x9a, 0x05, 0x4b, 0x24, 0x77, 0x3b, 0x14, 0x28, 0xfa, 0x9b, 0xe4, 0x42, 0xdb, 0x19, - 0x1d, 0xdb, 0x6e, 0x9d, 0x05, 0x96, 0x6f, 0x0f, 0x51, 0x3a, 0x1e, 0x2f, 0x3a, 0x9f, 0x3a, 0x5e, - 0xfc, 0x8e, 0x8e, 0x3c, 0x39, 0x39, 0x72, 0xfd, 0xa7, 0x49, 0x72, 0xa1, 0xe1, 0x02, 0x33, 0x9b, - 0xe6, 0xbe, 0x4e, 0x96, 0x19, 0x27, 0x76, 0x4f, 0x85, 0x53, 0x49, 0x39, 0x4b, 0x82, 0xaa, 0x3c, - 0xad, 0x39, 0xe7, 0x2f, 0x37, 0xe3, 0xd4, 0x7f, 0x44, 0x7a, 0x9c, 0xd7, 0x68, 0x0d, 0xb2, 0x38, - 0xe4, 0x4a, 0x04, 0xab, 0x29, 0x2e, 0xeb, 0x7a, 0x9c, 0xac, 0x47, 0xf4, 0xac, 0xa6, 0x1f, 0x7e, - 0x7c, 0x75, 0x81, 0x2a, 0xde, 0x2f, 0xe3, 0x7c, 0x7f, 0x4d, 0x90, 0x95, 0x96, 0xd7, 0x9b, 0xb1, - 0x43, 0x99, 0xe4, 0xfa, 0x5e, 0x10, 0x4e, 0x5d, 0x94, 0x68, 0xac, 0xdd, 0x22, 0xb9, 0xa1, 0x3c, - 0x3e, 0x79, 0xfa, 0x6b, 0xf1, 0x5b, 0x16, 0x18, 0x1a, 0xa1, 0xb5, 0x37, 0x49, 0xde, 0x57, 0x3e, - 0x01, 0xda, 0x3e, 0x81, 0xe3, 0x4c, 0xf0, 0xda, 0xb7, 0x49, 0x56, 0x1c, 0xc2, 0x6a, 0x9a, 0x73, - 0x5e, 0x7f, 0x22, 0x9b, 0x53, 0xc9, 0xa4, 0x7f, 0x94, 0x20, 0x25, 0x6a, 0x1e, 0x85, 0x3b, 0x6c, - 0x70, 0xc8, 0xfc, 0x0e, 0x5c, 0x64, 0xb8, 0x3f, 0x97, 0xe1, 0x1c, 0x99, 0xd9, 0x63, 0x3e, 0x57, - 0x32, 0x47, 0xe5, 0x48, 0xdb, 0x47, 0x27, 0x37, 0xad, 0xbe, 0x79, 0x68, 0x3b, 0x76, 0x38, 0xe6, - 0x6a, 0x2e, 0xc7, 0x9f, 0xf2, 0xbc, 0x4c, 0xd8, 0xfc, 0x84, 0x91, 0xce, 0x88, 0xd1, 0x56, 0xc9, - 0x22, 0xc4, 0xba, 0xc0, 0x3c, 0x66, 0x5c, 0xfb, 0x3c, 0x55, 0x43, 0x70, 0xe5, 0xe2, 0x34, 0x9f, - 0x56, 0x20, 0x8b, 0xfb, 0xad, 0x3b, 0xad, 0xdd, 0xbb, 0xad, 0xd2, 0x82, 0xb6, 0x42, 0x0a, 0xfb, - 0x2d, 0xda, 0x30, 0x6a, 0x5b, 0x46, 0x75, 0xbb, 0x51, 0x4a, 0x68, 0x4b, 0x10, 0x2e, 0xa2, 0x61, - 0x52, 0xff, 0x30, 0x41, 0x08, 0x1e, 0xa0, 0x54, 0xea, 0x0d, 0x92, 0x81, 0x78, 0x1a, 0x8a, 0x83, - 0x5b, 0xde, 0x78, 0x2e, 0x6e, 0xd7, 0x13, 0x78, 0x05, 0xff, 0x18, 0x15, 0x2c, 0xd3, 0x3b, 0x4c, - 0xce, 0xef, 0x30, 0xc3, 0x91, 0xb3, 0x5b, 0xcb, 0x91, 0x74, 0x1d, 0xbf, 0x12, 0x5a, 0x9e, 0x64, - 0x60, 0x4f, 0xf5, 0x77, 0x4a, 0x49, 0x70, 0xbe, 0x62, 0xbd, 0xd9, 0xa9, 0xed, 0xb6, 0x5a, 0x8d, - 0xda, 0x5e, 0xa3, 0x5e, 0x4a, 0xe9, 0xd7, 0x49, 0xa6, 0x39, 0x00, 0x29, 0xda, 0x1a, 0x7a, 0xc0, - 0x11, 0xf3, 0x99, 0x6b, 0x29, 0xc7, 0x9a, 0x10, 0xf4, 0x7f, 0x2d, 0x92, 0xcc, 0x8e, 0x37, 0x72, - 0x43, 0x6d, 0x63, 0xea, 0x16, 0x2f, 0x6f, 0xac, 0xc7, 0xa9, 0xc0, 0x81, 0x95, 0x3d, 0x40, 0xc9, - 0x5b, 0x0e, 0x87, 0x29, 0x7c, 0x45, 0x6e, 0x5d, 0x8e, 0x90, 0x1e, 0x9a, 0xfe, 0x31, 0x0b, 0xa5, - 0xd1, 0xe5, 0x08, 0x7d, 0xfc, 0xcc, 0xb7, 0x43, 0xf3, 0xd0, 0x11, 0x2e, 0x95, 0xa3, 0xd1, 0x58, - 0xdb, 0x22, 0xc5, 0x43, 0x48, 0x1f, 0x5d, 0x6f, 0x28, 0xa2, 0x5c, 0xe6, 0xf1, 0x2e, 0x27, 0xf6, - 0x51, 0x05, 0xf4, 0xae, 0x00, 0xd3, 0xc2, 0xe1, 0x64, 0xa0, 0xb5, 0xc8, 0xf2, 0xa9, 0xe7, 0x8c, - 0x06, 0x2c, 0x92, 0x95, 0xe5, 0xb2, 0x9e, 0x7f, 0xbc, 0xac, 0x03, 0x8e, 0x57, 0xd2, 0x96, 0x4e, - 0xa7, 0x87, 0xe5, 0x9f, 0xa4, 0x48, 0x61, 0x6a, 0x31, 0xad, 0x43, 0x0a, 0x90, 0x08, 0x87, 0xe6, - 0x31, 0x0f, 0xae, 0xd2, 0x60, 0x37, 0x9f, 0x68, 0xa3, 0x95, 0xf6, 0x84, 0x91, 0x4e, 0x4b, 0xd1, - 0x3f, 0x48, 0x92, 0xc2, 0xd4, 0xa4, 0xf6, 0x22, 0xc9, 0xd1, 0x36, 0x6d, 0x1e, 0x18, 0x7b, 0x8d, - 0xd2, 0x42, 0x79, 0xed, 0xfd, 0x0f, 0xae, 0xad, 0x72, 0x69, 0xd3, 0x02, 0xda, 0xbe, 0x7d, 0x8a, - 0xfe, 0x71, 0x83, 0x2c, 0x2a, 0x68, 0xa2, 0xfc, 0x0c, 0x40, 0x9f, 0x9e, 0x87, 0x4e, 0x21, 0x69, - 0x67, 0xcb, 0xa0, 0xe0, 0x22, 0xc9, 0x78, 0x24, 0xed, 0xf4, 0x4d, 0x9f, 0xf5, 0xb4, 0xaf, 0x91, - 0xac, 0x04, 0xa6, 0xca, 0x65, 0x00, 0x5e, 0x9e, 0x07, 0x4e, 0x70, 0xb4, 0xb3, 0x6d, 0x1c, 0x34, - 0x4a, 0xe9, 0x78, 0x1c, 0xed, 0x38, 0xe6, 0x29, 0xd3, 0x9e, 0x03, 0x67, 0xe6, 0xb0, 0x4c, 0xf9, - 0x0a, 0xc0, 0x9e, 0x7a, 0x44, 0x1c, 0xa2, 0xca, 0xab, 0x3f, 0xfb, 0xd5, 0xfa, 0xc2, 0xef, 0x7f, - 0xbd, 0x5e, 0x9a, 0x9f, 0x2e, 0xff, 0x33, 0x41, 0x96, 0x66, 0x4e, 0x09, 0x9d, 0x69, 0xe8, 0x0d, - 0x47, 0x8e, 0xba, 0x77, 0xe0, 0x4c, 0x6a, 0xac, 0xdd, 0x99, 0xcb, 0x16, 0xaf, 0x3d, 0xe1, 0xd1, - 0xc7, 0xe6, 0x8b, 0xb7, 0xc8, 0x52, 0x0f, 0xec, 0xc7, 0xfc, 0xae, 0xe5, 0xb9, 0x47, 0xf6, 0xb1, - 0x8c, 0xa3, 0xe5, 0x38, 0x99, 0x75, 0x0e, 0xa4, 0x45, 0xc1, 0x50, 0xe3, 0xf8, 0x2f, 0x93, 0x29, - 0xee, 0x92, 0x34, 0xde, 0x37, 0xed, 0x19, 0x92, 0xae, 0x36, 0x5b, 0x75, 0x70, 0x85, 0x0b, 0x60, - 0xbd, 0x25, 0xbe, 0x75, 0x9c, 0x40, 0xdf, 0xd2, 0xae, 0x92, 0xec, 0xc1, 0xee, 0xf6, 0xfe, 0x0e, - 0x1e, 0xff, 0x45, 0x98, 0x5e, 0x89, 0xa6, 0x85, 0x72, 0xe5, 0x0b, 0xd2, 0xac, 0xf9, 0x68, 0x42, - 0xff, 0x77, 0x92, 0x2c, 0x51, 0xac, 0x02, 0xfd, 0xb0, 0xed, 0x39, 0xb6, 0x35, 0xd6, 0xda, 0x24, - 0x0f, 0xfa, 0xf5, 0xec, 0x29, 0xa7, 0xde, 0x78, 0x4c, 0xaa, 0x98, 0x70, 0xa9, 0x51, 0x4d, 0x71, - 0xd2, 0x89, 0x10, 0x08, 0x29, 0x99, 0x1e, 0x73, 0xcc, 0xf1, 0x79, 0x39, 0xab, 0x2e, 0x2b, 0x4e, - 0x2a, 0xa0, 0xbc, 0xbe, 0x32, 0xef, 0x75, 0xcd, 0x30, 0x64, 0x83, 0x61, 0x28, 0x72, 0x56, 0x1a, - 0xea, 0x2b, 0xf3, 0x9e, 0x21, 0x49, 0xda, 0xeb, 0x24, 0x7b, 0x06, 0x6a, 0x7b, 0x67, 0x32, 0x2d, - 0x9d, 0x2f, 0x57, 0x62, 0xf5, 0xf7, 0x31, 0x1b, 0xcd, 0x6d, 0x16, 0xcd, 0xda, 0xda, 0x6d, 0x35, - 0x94, 0x59, 0xe5, 0xfc, 0xae, 0xdb, 0xf2, 0x5c, 0x74, 0x59, 0xb2, 0xdb, 0xea, 0x6e, 0x1a, 0xcd, - 0xed, 0x7d, 0x8a, 0xa6, 0xbd, 0x04, 0x90, 0x52, 0x04, 0xd9, 0x34, 0x6d, 0x07, 0x4b, 0xa5, 0x2b, - 0x24, 0x65, 0xb4, 0x20, 0x06, 0x97, 0x4b, 0x30, 0x5d, 0x8c, 0xa6, 0x0d, 0x77, 0x3c, 0xf1, 0xe6, - 0xf9, 0x75, 0xf5, 0x77, 0x49, 0x71, 0x7f, 0xd8, 0x03, 0x4f, 0x15, 0x1e, 0xa2, 0x5d, 0x83, 0x90, - 0x62, 0xfa, 0xa6, 0xe3, 0x30, 0xc7, 0x0e, 0x06, 0xb2, 0x9a, 0x9e, 0x26, 0x41, 0x09, 0xf0, 0xe4, - 0xb6, 0x94, 0x95, 0x8a, 0x60, 0xd0, 0x7f, 0x4c, 0x56, 0x60, 0x95, 0xd0, 0x84, 0x94, 0xac, 0x92, - 0xf0, 0x06, 0x29, 0x5a, 0x8a, 0xd4, 0xb5, 0x7b, 0xc2, 0x15, 0xab, 0x2b, 0x50, 0xe8, 0x15, 0x22, - 0x68, 0xb3, 0x4e, 0x0b, 0x11, 0xa8, 0xd9, 0x43, 0x3d, 0x87, 0x00, 0xc5, 0xe5, 0x33, 0xd5, 0x45, - 0x80, 0xa6, 0xda, 0x00, 0x41, 0x1a, 0x58, 0x31, 0xcf, 0xee, 0xd9, 0x21, 0x5c, 0x8f, 0x9e, 0x48, - 0xb3, 0x19, 0x9a, 0x43, 0x42, 0x0d, 0xc6, 0xfa, 0x7b, 0x49, 0x42, 0xf6, 0xcc, 0xe0, 0x44, 0x2e, - 0x0d, 0x05, 0x49, 0xd4, 0x7e, 0x9c, 0x57, 0x06, 0xef, 0x29, 0x10, 0x9d, 0xe0, 0xb5, 0xd7, 0x54, - 0x9e, 0x15, 0xd5, 0x41, 0x3c, 0xa3, 0x5c, 0x2b, 0x2e, 0xc1, 0xce, 0x96, 0x00, 0x78, 0x11, 0x99, - 0xef, 0x73, 0x2f, 0x82, 0x8b, 0x08, 0x9f, 0xd0, 0x95, 0xe4, 0x23, 0x9d, 0x65, 0x06, 0x7a, 0x36, - 0x6e, 0x91, 0x39, 0x83, 0x6e, 0x2d, 0xd0, 0x09, 0x5f, 0xb5, 0x44, 0x96, 0x7d, 0xb8, 0x66, 0xb0, - 0xeb, 0x6e, 0xc0, 0xa7, 0xf5, 0x3f, 0x81, 0x0d, 0x9a, 0x6d, 0x63, 0x47, 0x9e, 0x76, 0x9d, 0x64, - 0x8f, 0xcc, 0x81, 0xed, 0x8c, 0xe5, 0x35, 0x7b, 0x39, 0x6e, 0x89, 0x09, 0xbe, 0x62, 0xf4, 0x7a, - 0x50, 0x94, 0x05, 0x9b, 0x9c, 0x87, 0x4a, 0x5e, 0x9e, 0x7c, 0x47, 0x87, 0x2e, 0x24, 0x59, 0x95, - 0x7c, 0xf9, 0x08, 0x83, 0x89, 0x6f, 0xba, 0x91, 0xb6, 0x62, 0x80, 0x56, 0x80, 0x48, 0xca, 0xce, - 0xc0, 0x83, 0x84, 0xbe, 0x6a, 0x08, 0x89, 0x37, 0x27, 0x7a, 0x05, 0xd6, 0x03, 0x95, 0x31, 0x5a, - 0x7e, 0xde, 0x7e, 0xa8, 0x84, 0x8b, 0x30, 0x19, 0x71, 0x97, 0xdf, 0xe4, 0x21, 0x65, 0x32, 0xf5, - 0x85, 0x22, 0xdd, 0xab, 0x64, 0x69, 0x46, 0xcf, 0x47, 0xaa, 0x9e, 0x66, 0xfb, 0xe0, 0xf5, 0x52, - 0x5a, 0x7e, 0x7d, 0xb3, 0x94, 0xd5, 0xff, 0x01, 0x45, 0x58, 0xdb, 0xe3, 0xd7, 0x0a, 0xad, 0x1a, - 0xdf, 0x65, 0xe6, 0x78, 0xcf, 0x6a, 0x79, 0x8e, 0xf4, 0x99, 0xd8, 0x22, 0x60, 0x22, 0x05, 0x13, - 0x34, 0x87, 0xd3, 0x88, 0x11, 0xc2, 0x6b, 0x41, 0xd4, 0x2f, 0xdd, 0x21, 0xe0, 0xb8, 0x59, 0x97, - 0x28, 0x11, 0x24, 0xe4, 0xc4, 0x16, 0x66, 0x38, 0x3a, 0x84, 0x6b, 0xda, 0x67, 0x3d, 0x81, 0x49, - 0x73, 0xcc, 0x52, 0x44, 0x45, 0x98, 0x5e, 0x87, 0x26, 0x4c, 0xc9, 0x5c, 0x25, 0xa9, 0xbd, 0x5a, - 0x1b, 0xe2, 0xce, 0x0a, 0x44, 0x8d, 0x82, 0x22, 0x03, 0x09, 0x67, 0xf6, 0xeb, 0x6d, 0x08, 0x37, - 0x33, 0x33, 0x40, 0x2a, 0xa7, 0x31, 0x9c, 0xe8, 0xbf, 0x48, 0x90, 0xac, 0xc8, 0x32, 0xb1, 0x1a, - 0x1b, 0x64, 0x51, 0x55, 0x3d, 0x22, 0xf5, 0x3d, 0xff, 0xf8, 0x34, 0x55, 0x91, 0x59, 0x4f, 0x9c, - 0xa3, 0xe2, 0x2b, 0xbf, 0x41, 0x8a, 0xd3, 0x13, 0x5f, 0xe8, 0x14, 0x7f, 0x44, 0x0a, 0xe8, 0x28, - 0x2a, 0x47, 0x6f, 0x90, 0xac, 0xc8, 0x84, 0xf2, 0xaa, 0x9f, 0x97, 0x33, 0x25, 0x12, 0x22, 0xdd, - 0xa2, 0xc8, 0xb3, 0xaa, 0x3d, 0x5b, 0x3f, 0xdf, 0x1d, 0xa9, 0x82, 0xeb, 0x6f, 0x91, 0x74, 0x9b, - 0x81, 0x84, 0x67, 0xc9, 0xa2, 0x0b, 0xa1, 0x67, 0x12, 0xd9, 0x08, 0x84, 0xab, 0x2c, 0x16, 0xe0, - 0x10, 0xb1, 0xb2, 0x38, 0x05, 0xf1, 0x0c, 0x8c, 0x67, 0x82, 0xbf, 0xa9, 0x0e, 0x15, 0xbf, 0xf5, - 0x3d, 0x52, 0xbc, 0xcb, 0xec, 0xe3, 0x7e, 0x08, 0x27, 0x86, 0x82, 0x5e, 0x26, 0xe9, 0x21, 0x8b, - 0x36, 0xbf, 0x1a, 0xeb, 0x3a, 0x30, 0x4f, 0x39, 0x0a, 0x2f, 0xe4, 0x19, 0xe7, 0x96, 0x8f, 0x02, - 0x72, 0xa4, 0xff, 0x36, 0x49, 0x96, 0x9b, 0x41, 0x30, 0x32, 0xa1, 0xe0, 0x96, 0x51, 0xf0, 0x3b, - 0xb3, 0x0d, 0xc3, 0x8d, 0x58, 0x0d, 0x67, 0x58, 0x66, 0x9b, 0x06, 0x19, 0xb9, 0x92, 0x51, 0xe4, - 0xd2, 0x1f, 0x26, 0x54, 0xb7, 0x70, 0x7d, 0xea, 0xde, 0x94, 0x57, 0xc1, 0x89, 0x2e, 0x4d, 0x4b, - 0x62, 0xfb, 0xee, 0x89, 0xeb, 0x9d, 0xb9, 0x90, 0x68, 0xa1, 0x7b, 0x68, 0x35, 0xee, 0x82, 0xa7, - 0x5d, 0x06, 0x90, 0x36, 0x03, 0xa2, 0xcc, 0x65, 0x67, 0x28, 0xa9, 0xdd, 0x68, 0xd5, 0x9b, 0xad, - 0xdb, 0x90, 0xde, 0x1e, 0x95, 0xd4, 0x66, 0x90, 0xce, 0xdc, 0x63, 0x30, 0x77, 0xb6, 0xd9, 0xe9, - 0xec, 0xf3, 0x52, 0xf1, 0x69, 0x40, 0x5d, 0x9c, 0x41, 0xe1, 0x00, 0xea, 0x44, 0x00, 0x61, 0x26, - 0x05, 0x50, 0x3a, 0x06, 0x84, 0xc9, 0x14, 0x02, 0x88, 0xf0, 0xf0, 0xbf, 0x25, 0x49, 0xc9, 0xb0, - 0x2c, 0x36, 0x0c, 0x71, 0x5e, 0x56, 0x27, 0x7b, 0x58, 0xed, 0xc1, 0x97, 0xcd, 0xf0, 0xf5, 0x04, - 0xdd, 0xe2, 0x56, 0xec, 0x8b, 0xd1, 0x1c, 0x5f, 0x85, 0x7a, 0x0e, 0x33, 0x7a, 0x03, 0x3b, 0xc0, - 0x57, 0x04, 0x41, 0xa3, 0x91, 0xa4, 0xf2, 0x7f, 0x12, 0xe4, 0x62, 0x0c, 0x42, 0x7b, 0x95, 0xa4, - 0x7d, 0x20, 0xcb, 0xe3, 0x59, 0x7b, 0x5c, 0x3f, 0x87, 0xac, 0x94, 0x23, 0xb5, 0x75, 0x42, 0xcc, - 0x51, 0xe8, 0x99, 0x7c, 0x7d, 0x7e, 0x30, 0x39, 0x3a, 0x45, 0xd1, 0xbe, 0x0f, 0xd1, 0x9a, 0x59, - 0xbe, 0x6c, 0x89, 0x0a, 0x1b, 0x8d, 0xff, 0x75, 0xf7, 0x95, 0x2d, 0x13, 0x23, 0x4a, 0x87, 0x0b, - 0xa3, 0x52, 0x68, 0xf9, 0x75, 0x52, 0x9c, 0xa6, 0xa3, 0x77, 0x43, 0x79, 0x61, 0x72, 0x05, 0x8a, - 0x94, 0x7f, 0xa3, 0xd3, 0x98, 0xce, 0xb1, 0x72, 0x1a, 0xf8, 0xd4, 0x3f, 0x84, 0xbc, 0xd4, 0xb8, - 0x17, 0x32, 0xdf, 0x35, 0x9d, 0x9a, 0xa1, 0x35, 0xa6, 0xa2, 0xa5, 0xd0, 0xfc, 0x85, 0xd8, 0x8e, - 0x3f, 0xe2, 0xa8, 0xd4, 0x8c, 0x98, 0x78, 0x09, 0x95, 0xc2, 0xc8, 0x77, 0xe4, 0xeb, 0x11, 0xaf, - 0x14, 0xf6, 0xe9, 0x36, 0x45, 0x1a, 0x3e, 0xbd, 0xa8, 0xe8, 0x94, 0x7a, 0xfc, 0xb3, 0xdf, 0xd4, - 0x02, 0x5f, 0x7d, 0x84, 0x7a, 0x99, 0x90, 0xc9, 0xae, 0xe1, 0xd8, 0x32, 0xb5, 0xcd, 0x4e, 0x67, - 0x1b, 0xae, 0x0a, 0xaf, 0x9c, 0x27, 0x53, 0x9c, 0xac, 0xff, 0x26, 0x41, 0x72, 0x35, 0x43, 0x66, - 0x98, 0x4d, 0x52, 0xe2, 0x71, 0xc5, 0x62, 0x7e, 0xd8, 0x65, 0xf7, 0x86, 0xb6, 0x3f, 0x96, 0xa1, - 0xe1, 0xfc, 0x12, 0x74, 0x19, 0xb9, 0x6a, 0xc0, 0xd4, 0xe0, 0x3c, 0x1a, 0x25, 0x45, 0x26, 0x55, - 0xec, 0x5a, 0xa6, 0x0a, 0xd4, 0xeb, 0xe7, 0x9b, 0x42, 0x94, 0x67, 0x93, 0x31, 0x34, 0xbd, 0x4a, - 0x48, 0xcd, 0x0c, 0xf4, 0x03, 0x72, 0x71, 0xd7, 0xb7, 0xfa, 0x50, 0x28, 0x89, 0x45, 0xe5, 0x96, - 0xdf, 0x22, 0x6b, 0x21, 0x14, 0x44, 0xdd, 0xbe, 0x1d, 0x84, 0xf8, 0x68, 0x09, 0xbe, 0xc1, 0x5c, - 0x9c, 0xef, 0xf2, 0xc7, 0x45, 0xf1, 0xd8, 0x49, 0xaf, 0x20, 0x66, 0x4b, 0x40, 0xa8, 0x42, 0x6c, - 0x23, 0x40, 0xff, 0x1e, 0x29, 0xd5, 0xed, 0x60, 0x68, 0x86, 0x20, 0x5b, 0xf6, 0x33, 0xda, 0x6d, - 0x52, 0xea, 0x33, 0xa8, 0x67, 0x0f, 0x99, 0x09, 0x39, 0x91, 0xf9, 0xb6, 0xd7, 0x7b, 0x22, 0x3b, - 0xac, 0x44, 0x5c, 0x6d, 0xce, 0xa4, 0x7f, 0x06, 0x19, 0x1c, 0x5f, 0x73, 0xa4, 0xdc, 0x97, 0xc8, - 0x85, 0xc0, 0x35, 0x87, 0x41, 0xdf, 0x0b, 0xbb, 0xb6, 0x1b, 0xe2, 0xf3, 0xa5, 0x23, 0x6b, 0xe1, - 0x92, 0x9a, 0x68, 0x4a, 0x3a, 0xc4, 0x66, 0xed, 0x84, 0xb1, 0x61, 0xd7, 0x73, 0x7a, 0x5d, 0x35, - 0x29, 0x9e, 0x2c, 0x01, 0x8d, 0x33, 0xbb, 0x4e, 0xaf, 0xa3, 0xe8, 0x5a, 0x95, 0xac, 0x3b, 0xde, - 0x71, 0x17, 0x34, 0xf3, 0xe1, 0xde, 0x77, 0x8f, 0x3c, 0xbf, 0x1b, 0x38, 0xde, 0x19, 0x7c, 0x38, - 0xf0, 0xc7, 0x7c, 0xd5, 0x68, 0x94, 0x01, 0xd5, 0x10, 0xa0, 0x4d, 0xcf, 0xef, 0xc0, 0xdc, 0xa6, - 0x42, 0x60, 0x9a, 0x9f, 0xa8, 0x1d, 0xda, 0xd6, 0x89, 0x4a, 0xf3, 0x11, 0x75, 0x0f, 0x88, 0x10, - 0xe9, 0x96, 0x98, 0xc3, 0x2c, 0x6e, 0x64, 0x8e, 0xca, 0x70, 0x54, 0x51, 0x11, 0x11, 0xa4, 0x7f, - 0x9d, 0xe4, 0xdb, 0x8e, 0x69, 0xf1, 0x87, 0x61, 0xac, 0xfe, 0x21, 0x85, 0xe1, 0xc9, 0x81, 0xd6, - 0x22, 0xbc, 0xe5, 0xe9, 0x34, 0x49, 0x7f, 0x0f, 0x92, 0x3e, 0xf5, 0xbc, 0x10, 0x2e, 0xe9, 0x35, - 0x92, 0xb5, 0xcc, 0xae, 0x72, 0xf7, 0x62, 0x35, 0x0f, 0x6e, 0x91, 0xa9, 0x19, 0x77, 0xd8, 0x98, - 0x66, 0x2c, 0x13, 0xfe, 0x30, 0xfd, 0x01, 0x02, 0x9d, 0x94, 0x9b, 0xa3, 0x28, 0xd2, 0x1f, 0x78, - 0x31, 0x50, 0x28, 0x30, 0xe3, 0x3f, 0x44, 0xb8, 0xa2, 0x04, 0x75, 0xfb, 0x10, 0x38, 0x44, 0xb1, - 0x58, 0x5d, 0x06, 0x24, 0x11, 0x48, 0x0c, 0x27, 0x94, 0x08, 0x34, 0x7e, 0xeb, 0x7f, 0x4e, 0x90, - 0x02, 0x0e, 0xec, 0x23, 0xdb, 0xc2, 0x3c, 0xf3, 0xc5, 0x63, 0x24, 0x04, 0x06, 0x2b, 0xf0, 0xe5, - 0xa6, 0x78, 0x60, 0xa8, 0x75, 0x28, 0x45, 0x9a, 0xf6, 0x36, 0x84, 0x47, 0x9e, 0xe7, 0x64, 0x78, - 0xd4, 0x3f, 0x3f, 0x23, 0xca, 0x2e, 0x47, 0xf2, 0x71, 0x23, 0x4e, 0x76, 0xc7, 0x8f, 0xa6, 0x48, - 0xa7, 0x49, 0xf8, 0xa8, 0x6d, 0xb9, 0xfc, 0x34, 0xe4, 0xa3, 0x76, 0xad, 0x45, 0x81, 0xa2, 0xff, - 0x31, 0x41, 0x96, 0x1a, 0xae, 0xe5, 0x8f, 0x79, 0x48, 0x41, 0x0b, 0xae, 0x91, 0x3c, 0x14, 0xd3, - 0xc1, 0x38, 0x80, 0x8e, 0x53, 0xbd, 0x99, 0x45, 0x04, 0xad, 0x49, 0xf2, 0x10, 0x3c, 0x3d, 0xdf, - 0x0e, 0xfb, 0x03, 0x59, 0x55, 0xc6, 0x87, 0xb1, 0x69, 0x99, 0x15, 0x43, 0xb1, 0xd0, 0x09, 0xb7, - 0x0a, 0x5c, 0x29, 0xbe, 0x59, 0x1e, 0xb8, 0xa0, 0xff, 0x75, 0xa0, 0xd5, 0x81, 0x7a, 0xb1, 0x8b, - 0x1d, 0x04, 0xd7, 0x03, 0x5a, 0x41, 0x49, 0xc3, 0xae, 0x48, 0xd7, 0x49, 0x3e, 0x12, 0x86, 0x2f, - 0x95, 0x46, 0xa3, 0xd3, 0xbd, 0xb9, 0x71, 0xab, 0x7b, 0xbb, 0xb6, 0x03, 0x61, 0x4c, 0xe4, 0xd0, - 0xdf, 0x81, 0x4e, 0x3b, 0xa6, 0x0b, 0x5d, 0x8e, 0xea, 0xf9, 0xc0, 0x2b, 0x7c, 0xb8, 0x6a, 0xaa, - 0x28, 0x4a, 0x0b, 0xaf, 0xc0, 0xdb, 0x87, 0x45, 0x11, 0x4e, 0xc5, 0x17, 0x45, 0x53, 0x2f, 0xb6, - 0xa9, 0x73, 0x5f, 0x6c, 0xd3, 0x5f, 0xc9, 0x8b, 0xed, 0x8b, 0x9f, 0xa5, 0x48, 0x3e, 0xea, 0xe1, - 0xd0, 0x65, 0xb0, 0x46, 0x59, 0x10, 0xdd, 0x75, 0x44, 0x6f, 0xf1, 0xea, 0x24, 0x6f, 0x6c, 0x6f, - 0xef, 0xd6, 0x0c, 0x7c, 0xf0, 0x7c, 0x5b, 0x14, 0x31, 0x11, 0xc0, 0x80, 0x4b, 0x8b, 0x87, 0xde, - 0xd3, 0xf4, 0x49, 0x11, 0x73, 0x5f, 0xf6, 0xf0, 0x11, 0x4a, 0x55, 0x30, 0xcf, 0x91, 0x9c, 0xd1, - 0xe9, 0x34, 0x6f, 0xb7, 0x40, 0xd2, 0x83, 0x44, 0xf9, 0x29, 0x00, 0x5d, 0x98, 0x88, 0x82, 0xe4, - 0x7b, 0xec, 0x82, 0x24, 0x44, 0xd5, 0x6a, 0x8d, 0x36, 0xae, 0x77, 0x3f, 0x39, 0x8f, 0xe2, 0xa9, - 0x9b, 0x3f, 0x88, 0xe5, 0xdb, 0xb4, 0xd1, 0x36, 0x28, 0xae, 0xf8, 0x20, 0x39, 0xb7, 0xaf, 0xb6, - 0xcf, 0xa0, 0xab, 0xc7, 0x35, 0xd7, 0xd5, 0xeb, 0xed, 0xfd, 0x54, 0x59, 0x03, 0xcc, 0xf2, 0xa4, - 0x71, 0x05, 0xfb, 0x8e, 0x71, 0xb5, 0xce, 0x9e, 0x41, 0xf7, 0xb8, 0x98, 0xd4, 0xdc, 0x6a, 0x1d, - 0x7c, 0x4e, 0x40, 0x29, 0xa0, 0x1d, 0xdd, 0x6f, 0xb5, 0xb8, 0x76, 0xe9, 0x39, 0xed, 0xe8, 0xc8, - 0x75, 0x11, 0x73, 0x1d, 0x52, 0xd8, 0xee, 0x4e, 0x7b, 0xbb, 0xb1, 0xd7, 0x28, 0x3d, 0x48, 0xcf, - 0x6d, 0xa8, 0xe6, 0x0d, 0x86, 0x0e, 0x0b, 0x85, 0x7a, 0x9d, 0xad, 0xfd, 0x3d, 0xfe, 0xb8, 0x7c, - 0x3f, 0x33, 0xbf, 0x60, 0x7f, 0x14, 0xf6, 0xb0, 0x6c, 0xbc, 0x16, 0xd5, 0x71, 0x0f, 0x32, 0x22, - 0x65, 0x46, 0x18, 0x51, 0xc4, 0xa1, 0x1c, 0xda, 0xf8, 0xae, 0x78, 0x87, 0xbe, 0x9f, 0x9d, 0x93, - 0x43, 0xd9, 0xbb, 0x10, 0x05, 0xa1, 0xd4, 0x8b, 0x9e, 0xa4, 0xa2, 0xa9, 0x17, 0x7f, 0x40, 0x72, - 0x2a, 0x60, 0x80, 0x75, 0xb2, 0x77, 0x77, 0xe9, 0x9d, 0x06, 0x85, 0xa3, 0xe7, 0xd6, 0x51, 0x33, - 0x77, 0x3d, 0x1f, 0xbc, 0x0b, 0xb6, 0xb1, 0xb8, 0x63, 0xb4, 0x8c, 0xdb, 0x00, 0x90, 0x6f, 0x5e, - 0x0a, 0x20, 0xbd, 0xbe, 0x5c, 0x92, 0x0b, 0x44, 0x32, 0xab, 0x6b, 0x0f, 0x3f, 0x59, 0x5f, 0xf8, - 0x08, 0x7e, 0x7f, 0xff, 0x64, 0x3d, 0x71, 0xff, 0xd3, 0xf5, 0xc4, 0x43, 0xf8, 0xfd, 0x01, 0x7e, - 0x7f, 0x81, 0xdf, 0x61, 0x96, 0xd7, 0x2f, 0xaf, 0xfd, 0x37, 0x00, 0x00, 0xff, 0xff, 0x2c, 0xf4, - 0xf4, 0x16, 0x49, 0x1d, 0x00, 0x00, + // 3132 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0xcb, 0x6f, 0x1b, 0xd7, + 0xd5, 0x37, 0x9f, 0x22, 0x0f, 0x29, 0x89, 0x1e, 0x3b, 0x8e, 0xcc, 0x28, 0xb2, 0xbf, 0x49, 0x9c, + 0x38, 0x8f, 0x8f, 0x89, 0x95, 0x7c, 0x1f, 0xdc, 0x04, 0xad, 0x33, 0x7c, 0xc8, 0x62, 0x2d, 0x91, + 0xc4, 0x25, 0x25, 0x23, 0x28, 0x50, 0x62, 0x34, 0xbc, 0x12, 0x27, 0x1a, 0xce, 0xb0, 0x33, 0x43, + 0xc9, 0x6c, 0x51, 0xc0, 0xe9, 0xa6, 0x45, 0x56, 0xdd, 0x17, 0x41, 0x50, 0xb4, 0xe8, 0xae, 0xeb, + 0x02, 0x5d, 0x79, 0xe9, 0x65, 0x8a, 0x02, 0x45, 0xd0, 0x02, 0x41, 0x93, 0xfe, 0x03, 0x01, 0xba, + 0xc8, 0xa2, 0x5d, 0xf4, 0xdc, 0xc7, 0x0c, 0x87, 0xf4, 0x58, 0x71, 0x9a, 0x2c, 0x08, 0xce, 0x3d, + 0xe7, 0x77, 0xce, 0xbd, 0xf7, 0xdc, 0x73, 0xcf, 0xe3, 0x42, 0xc1, 0x9f, 0x8e, 0xa9, 0x57, 0x19, + 0xbb, 0x8e, 0xef, 0x28, 0xca, 0xc0, 0x31, 0x8e, 0xa9, 0x5b, 0xf1, 0x4e, 0x75, 0x77, 0x74, 0x6c, + 0xfa, 0x95, 0x93, 0x1b, 0xe5, 0xcb, 0xbe, 0x39, 0xa2, 0x9e, 0xaf, 0x8f, 0xc6, 0xaf, 0x85, 0x5f, + 0x02, 0x5e, 0x7e, 0x7a, 0x30, 0x71, 0x75, 0xdf, 0x74, 0xec, 0xd7, 0x82, 0x0f, 0xc9, 0xb8, 0x78, + 0xe4, 0x1c, 0x39, 0xfc, 0xf3, 0x35, 0xf6, 0x25, 0xa8, 0xea, 0x15, 0x58, 0xda, 0xa7, 0xae, 0x87, + 0x30, 0xe5, 0x22, 0x64, 0x4c, 0x7b, 0x40, 0xef, 0xad, 0x25, 0xae, 0x26, 0xae, 0xa7, 0x89, 0x18, + 0xa8, 0xbf, 0x4e, 0x40, 0x41, 0xb3, 0x6d, 0xc7, 0xe7, 0xba, 0x3c, 0x45, 0x81, 0xb4, 0xad, 0x8f, + 0x28, 0x07, 0xe5, 0x09, 0xff, 0x56, 0x6a, 0x90, 0xb5, 0xf4, 0x03, 0x6a, 0x79, 0x6b, 0xc9, 0xab, + 0xa9, 0xeb, 0x85, 0xcd, 0x57, 0x2a, 0x8f, 0xae, 0xb9, 0x12, 0x51, 0x52, 0xd9, 0xe1, 0xe8, 0x86, + 0xed, 0xbb, 0x53, 0x22, 0x45, 0xcb, 0xdf, 0x81, 0x42, 0x84, 0xac, 0x94, 0x20, 0x75, 0x4c, 0xa7, + 0x72, 0x1a, 0xf6, 0xc9, 0xd6, 0x77, 0xa2, 0x5b, 0x13, 0x8a, 0x93, 0x30, 0x9a, 0x18, 0xbc, 0x95, + 0xbc, 0x99, 0x50, 0xdf, 0x85, 0x3c, 0xa1, 0x9e, 0x33, 0x71, 0x0d, 0xea, 0x29, 0x2f, 0x41, 0xde, + 0xd6, 0x6d, 0xa7, 0x6f, 0x8c, 0x27, 0x1e, 0x17, 0x4f, 0x55, 0x8b, 0x9f, 0x7f, 0x7a, 0x25, 0xd7, + 0x42, 0x62, 0xad, 0xb3, 0xe7, 0x91, 0x1c, 0x63, 0xd7, 0x90, 0xab, 0xfc, 0x0f, 0x14, 0x47, 0x74, + 0xe4, 0xb8, 0xd3, 0xfe, 0xc1, 0xd4, 0xa7, 0x1e, 0x57, 0x9c, 0x22, 0x05, 0x41, 0xab, 0x32, 0x92, + 0xfa, 0xcb, 0x04, 0x5c, 0x0c, 0x74, 0x13, 0xfa, 0xa3, 0x89, 0xe9, 0xd2, 0x11, 0xb5, 0x7d, 0x4f, + 0xf9, 0x3f, 0xdc, 0xb3, 0x39, 0x32, 0x7d, 0x31, 0x47, 0x61, 0xf3, 0xd9, 0xb8, 0x3d, 0x87, 0xab, + 0x22, 0x12, 0xac, 0x68, 0x50, 0x74, 0xa9, 0x47, 0xdd, 0x13, 0x61, 0x09, 0x3e, 0xe5, 0x57, 0x0a, + 0xcf, 0x89, 0xa8, 0x5b, 0x90, 0xeb, 0x58, 0xba, 0x7f, 0xe8, 0xb8, 0x23, 0x45, 0x85, 0xa2, 0xee, + 0x1a, 0x43, 0xd3, 0xa7, 0x86, 0x3f, 0x71, 0x83, 0x53, 0x99, 0xa3, 0x29, 0x97, 0x20, 0xe9, 0x88, + 0x89, 0xf2, 0xd5, 0x2c, 0x5a, 0x22, 0xd9, 0xee, 0x12, 0xa4, 0xa8, 0x6f, 0xc3, 0xf9, 0x8e, 0x35, + 0x39, 0x32, 0xed, 0x3a, 0xf5, 0x0c, 0xd7, 0x1c, 0x33, 0xed, 0xec, 0x78, 0x99, 0xf3, 0x05, 0xc7, + 0xcb, 0xbe, 0xc3, 0x23, 0x4f, 0xce, 0x8e, 0x5c, 0xfd, 0x79, 0x12, 0xce, 0x37, 0x6c, 0x14, 0xa6, + 0x51, 0xe9, 0x6b, 0xb0, 0x42, 0x39, 0xb1, 0x7f, 0x22, 0x9c, 0x4a, 0xea, 0x59, 0x16, 0xd4, 0xc0, + 0xd3, 0x9a, 0x0b, 0xfe, 0x72, 0x23, 0x6e, 0xfb, 0x8f, 0x68, 0x8f, 0xf3, 0x1a, 0xa5, 0x01, 0x4b, + 0x63, 0xbe, 0x09, 0x6f, 0x2d, 0xc5, 0x75, 0x5d, 0x8b, 0xd3, 0xf5, 0xc8, 0x3e, 0xab, 0xe9, 0x87, + 0x9f, 0x5e, 0x39, 0x47, 0x02, 0xd9, 0x6f, 0xe2, 0x7c, 0xff, 0x48, 0xc0, 0x6a, 0xcb, 0x19, 0xcc, + 0xd9, 0xa1, 0x0c, 0xb9, 0xa1, 0xe3, 0xf9, 0x91, 0x8b, 0x12, 0x8e, 0x95, 0x9b, 0x90, 0x1b, 0xcb, + 0xe3, 0x93, 0xa7, 0xbf, 0x1e, 0xbf, 0x64, 0x81, 0x21, 0x21, 0x5a, 0x79, 0x1b, 0xf2, 0x6e, 0xe0, + 0x13, 0xb8, 0xdb, 0x27, 0x70, 0x9c, 0x19, 0x5e, 0xf9, 0x2e, 0x64, 0xc5, 0x21, 0xac, 0xa5, 0xb9, + 0xe4, 0xb5, 0x27, 0xb2, 0x39, 0x91, 0x42, 0xea, 0x27, 0x09, 0x28, 0x11, 0xfd, 0xd0, 0xdf, 0xa5, + 0xa3, 0x03, 0xea, 0x76, 0xf1, 0x22, 0xe3, 0xfd, 0xb9, 0x84, 0xe7, 0x48, 0xf5, 0x01, 0x75, 0xf9, + 0x26, 0x73, 0x44, 0x8e, 0x94, 0x3d, 0xe6, 0xe4, 0xba, 0x31, 0xd4, 0x0f, 0x4c, 0xcb, 0xf4, 0xa7, + 0x7c, 0x9b, 0x2b, 0xf1, 0xa7, 0xbc, 0xa8, 0x13, 0x17, 0x3f, 0x13, 0x24, 0x73, 0x6a, 0x94, 0x35, + 0x58, 0xc2, 0x58, 0xe7, 0xe9, 0x47, 0x94, 0xef, 0x3e, 0x4f, 0x82, 0x21, 0xba, 0x72, 0x31, 0x2a, + 0xa7, 0x14, 0x60, 0x69, 0xaf, 0x75, 0xa7, 0xd5, 0xbe, 0xdb, 0x2a, 0x9d, 0x53, 0x56, 0xa1, 0xb0, + 0xd7, 0x22, 0x0d, 0xad, 0xb6, 0xad, 0x55, 0x77, 0x1a, 0xa5, 0x84, 0xb2, 0x8c, 0xe1, 0x22, 0x1c, + 0x26, 0xd5, 0x8f, 0x12, 0x00, 0xec, 0x00, 0xe5, 0xa6, 0xde, 0x82, 0x0c, 0xc6, 0x53, 0x5f, 0x1c, + 0xdc, 0xca, 0xe6, 0xf3, 0x71, 0xab, 0x9e, 0xc1, 0x2b, 0xec, 0x8f, 0x12, 0x21, 0x12, 0x5d, 0x61, + 0x72, 0x71, 0x85, 0x19, 0x8e, 0x9c, 0x5f, 0x5a, 0x0e, 0xd2, 0x75, 0xf6, 0x95, 0x50, 0xf2, 0x90, + 0xc1, 0x35, 0xd5, 0xdf, 0x2d, 0x25, 0xd1, 0xf9, 0x8a, 0xf5, 0x66, 0xb7, 0xd6, 0x6e, 0xb5, 0x1a, + 0xb5, 0x5e, 0xa3, 0x5e, 0x4a, 0xa9, 0xd7, 0x20, 0xd3, 0x1c, 0xa1, 0x16, 0x65, 0x9d, 0x79, 0xc0, + 0x21, 0x75, 0xa9, 0x6d, 0x04, 0x8e, 0x35, 0x23, 0xa8, 0x1f, 0xa3, 0x92, 0x5d, 0x67, 0x62, 0xfb, + 0xca, 0x66, 0xe4, 0x16, 0xaf, 0x6c, 0x6e, 0xc4, 0x6d, 0x81, 0x03, 0x2b, 0x3d, 0x44, 0xc9, 0x5b, + 0x8e, 0x87, 0x29, 0x7c, 0x45, 0x2e, 0x5d, 0x8e, 0x18, 0xdd, 0xd7, 0xdd, 0x23, 0xea, 0x4b, 0xa3, + 0xcb, 0x91, 0x72, 0x1d, 0x72, 0x78, 0x3a, 0x03, 0xc7, 0xb6, 0xa6, 0xdc, 0xa5, 0x72, 0x22, 0xcc, + 0xe2, 0x39, 0x0c, 0xda, 0x48, 0x23, 0x21, 0x57, 0xd9, 0x86, 0xe2, 0x01, 0x26, 0x93, 0xbe, 0x33, + 0x16, 0x31, 0x2f, 0xf3, 0x78, 0x07, 0x14, 0xab, 0xaa, 0x22, 0xba, 0x2d, 0xc0, 0xa4, 0x70, 0x30, + 0x1b, 0x28, 0x2d, 0x58, 0x39, 0x71, 0xac, 0xc9, 0x88, 0x86, 0xba, 0xb2, 0x5c, 0xd7, 0x8b, 0x8f, + 0xd7, 0xb5, 0xcf, 0xf1, 0x81, 0xb6, 0xe5, 0x93, 0xe8, 0x50, 0xb9, 0x03, 0xcb, 0xfe, 0x68, 0x7c, + 0xe8, 0x85, 0xea, 0x96, 0xb8, 0xba, 0x17, 0xce, 0x30, 0x18, 0x83, 0x07, 0xda, 0x8a, 0x7e, 0x64, + 0x54, 0xfe, 0x59, 0x0a, 0x0a, 0x91, 0x95, 0x2b, 0x5d, 0x28, 0x60, 0x8e, 0x1d, 0xeb, 0x47, 0x3c, + 0x6e, 0xcb, 0xb3, 0xb8, 0xf1, 0x44, 0xbb, 0xae, 0x74, 0x66, 0x82, 0x24, 0xaa, 0x45, 0xfd, 0x30, + 0x09, 0x85, 0x08, 0x53, 0x79, 0x19, 0x72, 0xa4, 0x43, 0x9a, 0xfb, 0x5a, 0xaf, 0x51, 0x3a, 0x57, + 0x5e, 0xff, 0xe0, 0xc3, 0xab, 0x6b, 0x5c, 0x5b, 0x54, 0x41, 0xc7, 0x35, 0x4f, 0x98, 0xeb, 0x5d, + 0x87, 0xa5, 0x00, 0x9a, 0x28, 0x3f, 0x83, 0xd0, 0xa7, 0x17, 0xa1, 0x11, 0x24, 0xe9, 0x6e, 0x6b, + 0x04, 0xbd, 0x2f, 0x19, 0x8f, 0x24, 0xdd, 0xa1, 0xee, 0xd2, 0x81, 0xf2, 0x02, 0x64, 0x25, 0x30, + 0x55, 0x2e, 0x23, 0xf0, 0xd2, 0x22, 0x70, 0x86, 0x23, 0xdd, 0x1d, 0x6d, 0xbf, 0x51, 0x4a, 0xc7, + 0xe3, 0x48, 0xd7, 0xd2, 0x4f, 0xa8, 0xf2, 0x3c, 0xde, 0x13, 0x0e, 0xcb, 0x94, 0x2f, 0x23, 0xec, + 0xa9, 0x47, 0xd4, 0x31, 0x54, 0x79, 0xed, 0x17, 0xbf, 0xd9, 0x38, 0xf7, 0xc7, 0xdf, 0x6e, 0x94, + 0x16, 0xd9, 0xe5, 0x7f, 0x27, 0x60, 0x79, 0xee, 0xc8, 0x31, 0x45, 0x66, 0x6d, 0xc7, 0x70, 0xc6, + 0x22, 0x9c, 0xe7, 0xaa, 0x80, 0x5e, 0x9a, 0x6d, 0x39, 0x35, 0xa4, 0x10, 0xc9, 0x41, 0x3f, 0x98, + 0x4f, 0x48, 0x6f, 0x3c, 0xa1, 0x3f, 0xc5, 0xa6, 0xa4, 0x5b, 0xb0, 0x3c, 0x40, 0x3b, 0x52, 0xb7, + 0x6f, 0x38, 0xf6, 0xa1, 0x79, 0x24, 0x43, 0x75, 0x39, 0x4e, 0x67, 0x9d, 0x03, 0x49, 0x51, 0x08, + 0xd4, 0x38, 0xfe, 0x1b, 0x24, 0xa3, 0xf2, 0x3e, 0x14, 0xa3, 0x1e, 0xaa, 0x3c, 0x0b, 0xe0, 0x99, + 0x3f, 0xa6, 0xb2, 0xbe, 0xe1, 0xd5, 0x10, 0xc9, 0x33, 0x0a, 0xaf, 0x6e, 0x94, 0x17, 0x21, 0x3d, + 0xc2, 0x50, 0xc6, 0xf5, 0x64, 0xaa, 0x17, 0x58, 0x4e, 0xfc, 0xeb, 0xa7, 0x57, 0x0a, 0x8e, 0x57, + 0xd9, 0x32, 0x2d, 0xba, 0x8b, 0x2c, 0xc2, 0x01, 0xea, 0x09, 0xa4, 0x59, 0xa8, 0x50, 0x9e, 0x81, + 0x74, 0xb5, 0xd9, 0xaa, 0xa3, 0xab, 0x9d, 0xc7, 0xd3, 0x59, 0xe6, 0x26, 0x61, 0x0c, 0xe6, 0xbb, + 0xca, 0x15, 0xc8, 0xee, 0xb7, 0x77, 0xf6, 0x76, 0x99, 0x7b, 0x5d, 0x40, 0xf6, 0x6a, 0xc8, 0x16, + 0x46, 0xc3, 0xd5, 0x64, 0x7a, 0xbb, 0x9d, 0xad, 0x2e, 0x3a, 0x95, 0x82, 0xfc, 0x95, 0x90, 0xcf, + 0xd7, 0x5c, 0x3e, 0x2f, 0x4f, 0x35, 0x1f, 0xd2, 0xd5, 0x7f, 0x25, 0x61, 0x99, 0xb0, 0xfa, 0xd6, + 0xf5, 0x3b, 0x8e, 0x65, 0x1a, 0x53, 0xa5, 0x03, 0x79, 0x34, 0xeb, 0xc0, 0x8c, 0xdc, 0xa9, 0xcd, + 0xc7, 0x24, 0xc1, 0x99, 0x54, 0x30, 0xaa, 0x05, 0x92, 0x64, 0xa6, 0x04, 0x83, 0x65, 0x66, 0x40, + 0x2d, 0x7d, 0x7a, 0x56, 0x36, 0xae, 0xcb, 0x5a, 0x9a, 0x08, 0x28, 0xaf, 0x1c, 0xf5, 0x7b, 0x7d, + 0xdd, 0xf7, 0xe9, 0x68, 0xec, 0x8b, 0x6c, 0x9c, 0xc6, 0xca, 0x51, 0xbf, 0xa7, 0x49, 0x92, 0xf2, + 0x26, 0x64, 0x4f, 0xd1, 0x2a, 0xce, 0xa9, 0x4c, 0xb8, 0x67, 0xeb, 0x95, 0x58, 0xf5, 0x03, 0x96, + 0x67, 0x17, 0x16, 0xcb, 0xac, 0xde, 0x6a, 0xb7, 0x1a, 0x81, 0xd5, 0x25, 0xbf, 0x6d, 0xb7, 0x1c, + 0x9b, 0xdd, 0x18, 0x68, 0xb7, 0xfa, 0x5b, 0x5a, 0x73, 0x67, 0x8f, 0x30, 0xcb, 0x5f, 0x44, 0x48, + 0x29, 0x84, 0x6c, 0xe9, 0xa6, 0xc5, 0x8a, 0xc0, 0xcb, 0x90, 0xd2, 0x5a, 0x98, 0x5d, 0xca, 0x25, + 0x64, 0x17, 0x43, 0xb6, 0x66, 0x4f, 0x67, 0x97, 0x69, 0x71, 0x5e, 0xf5, 0x3d, 0x28, 0xee, 0x8d, + 0x07, 0x18, 0x10, 0x84, 0x63, 0x2a, 0x57, 0x31, 0xa2, 0xe9, 0xae, 0x6e, 0x59, 0xd4, 0x32, 0xbd, + 0x91, 0xec, 0x13, 0xa2, 0x24, 0x2c, 0x6e, 0x9e, 0xdc, 0x96, 0xb2, 0x06, 0x13, 0x02, 0xea, 0x4f, + 0x61, 0x15, 0x67, 0xf1, 0x75, 0x2c, 0x36, 0x82, 0xf2, 0x62, 0x13, 0x8a, 0x46, 0x40, 0xea, 0x9b, + 0x03, 0x71, 0x03, 0xaa, 0xab, 0x78, 0x7f, 0x0b, 0x21, 0xb4, 0x59, 0x27, 0x85, 0x10, 0xd4, 0x1c, + 0xb0, 0x7d, 0x8e, 0x11, 0x2a, 0x1c, 0x7a, 0x09, 0xa1, 0xa9, 0x0e, 0x42, 0x18, 0x0d, 0xad, 0x98, + 0xa7, 0xf7, 0x4c, 0x1f, 0x6f, 0xe5, 0x40, 0x14, 0x10, 0x19, 0x92, 0x63, 0x84, 0x1a, 0x73, 0xf0, + 0xf7, 0x93, 0x00, 0x3d, 0xdd, 0x3b, 0x96, 0x53, 0x63, 0xa9, 0x15, 0x36, 0x56, 0x67, 0x15, 0xf8, + 0xbd, 0x00, 0x44, 0x66, 0x78, 0xe5, 0x8d, 0xa0, 0x82, 0x10, 0x75, 0x4f, 0xbc, 0xa0, 0x9c, 0x2b, + 0xae, 0x74, 0x98, 0x2f, 0x6e, 0xd8, 0xfd, 0xa7, 0xae, 0xcb, 0xbd, 0x08, 0xef, 0x3f, 0x7e, 0x62, + 0xbf, 0x95, 0x0f, 0xf7, 0x2c, 0xb3, 0xe9, 0x73, 0x71, 0x93, 0x2c, 0x18, 0x74, 0xfb, 0x1c, 0x99, + 0xc9, 0x55, 0x4b, 0xb0, 0xe2, 0xe2, 0x35, 0xc3, 0x55, 0xf7, 0x3d, 0xce, 0x56, 0xff, 0x8c, 0x36, + 0x68, 0x76, 0xb4, 0x5d, 0x79, 0xda, 0x75, 0xc8, 0x1e, 0xea, 0x23, 0xd3, 0x9a, 0xca, 0x6b, 0xf6, + 0x6a, 0xdc, 0x14, 0x33, 0x7c, 0x45, 0x1b, 0x0c, 0xb0, 0xdc, 0xf4, 0xb6, 0xb8, 0x0c, 0x91, 0xb2, + 0xbc, 0xac, 0x98, 0x1c, 0xd8, 0x58, 0x3e, 0x04, 0x65, 0x05, 0x1f, 0xb1, 0x18, 0xe6, 0xea, 0x76, + 0xb8, 0x5b, 0x31, 0x60, 0x56, 0xc0, 0x40, 0x4e, 0x4f, 0xf5, 0xa9, 0xdc, 0x6f, 0x30, 0xc4, 0x22, + 0x22, 0x27, 0xba, 0x20, 0x3a, 0xc0, 0x2d, 0xb3, 0x20, 0xfd, 0x55, 0xeb, 0x21, 0x12, 0x2e, 0xa2, + 0x73, 0x28, 0x5d, 0x7e, 0x9b, 0x87, 0x94, 0x19, 0xeb, 0x6b, 0x55, 0xfb, 0xaf, 0xc3, 0xf2, 0xdc, + 0x3e, 0x1f, 0xa9, 0xe7, 0x9a, 0x9d, 0xfd, 0x37, 0x4b, 0x69, 0xf9, 0xf5, 0xff, 0xa5, 0xac, 0xfa, + 0x4f, 0x2c, 0x2f, 0x3b, 0x0e, 0xbf, 0x56, 0xcc, 0xaa, 0xf1, 0xfd, 0x73, 0x8e, 0x77, 0xe3, 0x86, + 0x63, 0x49, 0x9f, 0x89, 0x2d, 0x68, 0x66, 0x5a, 0x58, 0x7d, 0xc0, 0xe1, 0x24, 0x14, 0xc4, 0xe8, + 0x5b, 0x10, 0x95, 0x59, 0x7f, 0x8c, 0x38, 0x6e, 0xd6, 0x65, 0x02, 0x82, 0xc4, 0x24, 0x59, 0x73, + 0x36, 0x9e, 0x1c, 0xe0, 0x35, 0x1d, 0xd2, 0x81, 0xc0, 0xa4, 0x39, 0x66, 0x39, 0xa4, 0x32, 0x98, + 0x5a, 0xc7, 0xf6, 0x32, 0xd0, 0xb9, 0x06, 0xa9, 0x5e, 0xad, 0x83, 0x71, 0x67, 0x15, 0xa3, 0x46, + 0x21, 0x20, 0x23, 0x89, 0x71, 0xf6, 0xea, 0x1d, 0x0c, 0x37, 0x73, 0x1c, 0x24, 0x95, 0xd3, 0x2c, + 0x9c, 0xa8, 0xbf, 0x4a, 0x40, 0x56, 0x24, 0xb7, 0xd8, 0x1d, 0x6b, 0xb0, 0x14, 0x94, 0x5c, 0x22, + 0xe3, 0xbe, 0xf8, 0xf8, 0xec, 0x58, 0x91, 0xc9, 0x4c, 0x9c, 0x63, 0x20, 0x57, 0x7e, 0x0b, 0x8a, + 0x51, 0xc6, 0xd7, 0x3a, 0xc5, 0x9f, 0x40, 0x81, 0x39, 0x4a, 0x90, 0x25, 0x37, 0x21, 0x2b, 0x12, + 0xb0, 0xbc, 0xea, 0x67, 0xa5, 0x6a, 0x89, 0xc4, 0x48, 0xb7, 0x24, 0xd2, 0x7b, 0xd0, 0x78, 0x6e, + 0x9c, 0xed, 0x8e, 0x24, 0x80, 0xab, 0xb7, 0x20, 0xdd, 0xa1, 0xa8, 0xe1, 0x39, 0x58, 0xb2, 0x31, + 0xf4, 0xcc, 0x22, 0x9b, 0xac, 0x4c, 0x06, 0x14, 0x23, 0x56, 0x96, 0xb1, 0x30, 0x9e, 0xa1, 0xf1, + 0x74, 0xf4, 0xb7, 0xa0, 0xf7, 0x66, 0xdf, 0x6a, 0x0f, 0x8a, 0x77, 0xa9, 0x79, 0x34, 0xf4, 0xf1, + 0xc4, 0x98, 0xa2, 0x57, 0x21, 0x3d, 0xa6, 0xe1, 0xe2, 0xd7, 0x62, 0x5d, 0x07, 0xf9, 0x84, 0xa3, + 0xd8, 0x85, 0x3c, 0xe5, 0xd2, 0xf2, 0xb9, 0x43, 0x8e, 0xd4, 0xdf, 0x27, 0x61, 0xa5, 0xe9, 0x79, + 0x13, 0x1d, 0x5b, 0x09, 0x19, 0x05, 0xbf, 0x37, 0xdf, 0x0a, 0x5d, 0x8f, 0xdd, 0xe1, 0x9c, 0xc8, + 0x7c, 0x3b, 0x24, 0x23, 0x57, 0x32, 0x8c, 0x5c, 0xea, 0xc3, 0x44, 0xd0, 0x07, 0x5d, 0x8b, 0xdc, + 0x9b, 0xf2, 0x1a, 0x3a, 0xd1, 0xc5, 0xa8, 0x26, 0xba, 0x67, 0x1f, 0xdb, 0xce, 0xa9, 0x8d, 0x89, + 0x16, 0xfb, 0xa2, 0x56, 0xe3, 0x2e, 0x7a, 0xda, 0x25, 0x04, 0x29, 0x73, 0x20, 0x42, 0x6d, 0x7a, + 0xca, 0x34, 0x75, 0x1a, 0xad, 0x7a, 0xb3, 0x75, 0x1b, 0xd3, 0xdb, 0xa3, 0x9a, 0x3a, 0x14, 0xd3, + 0x99, 0x7d, 0x84, 0xe6, 0xce, 0x36, 0xbb, 0xdd, 0x3d, 0x5e, 0xa9, 0x3e, 0x8d, 0xa8, 0x0b, 0x73, + 0x28, 0x36, 0xc0, 0x32, 0x15, 0x41, 0x2c, 0x93, 0x22, 0x28, 0x1d, 0x03, 0x62, 0xc9, 0x14, 0x03, + 0x88, 0xf0, 0xf0, 0xbf, 0x25, 0xa1, 0xa4, 0x19, 0x06, 0x1d, 0xfb, 0x8c, 0x2f, 0xab, 0x93, 0x1e, + 0xde, 0x64, 0xf6, 0x65, 0xf2, 0x6a, 0x8b, 0xb9, 0xc5, 0xcd, 0xd8, 0xb7, 0xb0, 0x05, 0xb9, 0x0a, + 0x71, 0x2c, 0xaa, 0x0d, 0x46, 0xa6, 0xc7, 0xde, 0x47, 0x04, 0x8d, 0x84, 0x9a, 0xca, 0x5f, 0x24, + 0xe0, 0x42, 0x0c, 0x42, 0x79, 0x1d, 0xd2, 0x2e, 0x92, 0xe5, 0xf1, 0xac, 0x3f, 0xae, 0x53, 0x65, + 0xa2, 0x84, 0x23, 0x95, 0x0d, 0x00, 0x7d, 0xe2, 0x3b, 0x3a, 0x9f, 0x9f, 0x1f, 0x4c, 0x8e, 0x44, + 0x28, 0xca, 0x5d, 0x8c, 0xd6, 0xd4, 0x70, 0x65, 0xb3, 0x57, 0xd8, 0xbc, 0xf5, 0xdf, 0xae, 0xbe, + 0xd2, 0xe5, 0x6a, 0x88, 0x54, 0x57, 0xae, 0x60, 0x9f, 0xc0, 0xbf, 0x98, 0x47, 0x63, 0x49, 0xa1, + 0xf3, 0x45, 0x17, 0x09, 0xff, 0x66, 0x8e, 0xa2, 0x5b, 0x47, 0x81, 0xa3, 0xe0, 0xa7, 0xfa, 0x11, + 0xe6, 0xa2, 0xc6, 0x3d, 0x9f, 0xba, 0xb6, 0x6e, 0xd5, 0x34, 0xa5, 0x11, 0x89, 0x90, 0x62, 0xb7, + 0x2f, 0xc5, 0xbe, 0x5f, 0x84, 0x12, 0x95, 0x9a, 0x16, 0x13, 0x23, 0xb1, 0x3a, 0x98, 0xb8, 0x96, + 0x7c, 0x0b, 0xe3, 0xd5, 0xc1, 0x1e, 0xd9, 0x21, 0x8c, 0xc6, 0x1e, 0x92, 0x82, 0x88, 0x94, 0x7a, + 0xfc, 0x23, 0x66, 0x64, 0x82, 0x6f, 0x3f, 0x2a, 0xbd, 0x0a, 0x30, 0x5b, 0x35, 0x1e, 0x55, 0xa6, + 0xb6, 0xd5, 0xed, 0xee, 0xe0, 0xf5, 0xe0, 0xc5, 0xf4, 0x8c, 0xc5, 0xc9, 0xea, 0xef, 0x12, 0x90, + 0xab, 0x69, 0x32, 0xab, 0x6c, 0x41, 0x89, 0xc7, 0x12, 0x83, 0xba, 0x7e, 0x9f, 0xde, 0x1b, 0x9b, + 0xee, 0x54, 0x86, 0x83, 0xb3, 0xcb, 0xce, 0x15, 0x26, 0x55, 0x43, 0xa1, 0x06, 0x97, 0x51, 0x08, + 0x14, 0xa9, 0xdc, 0x62, 0xdf, 0xd0, 0x83, 0xe0, 0xbc, 0x71, 0xb6, 0x29, 0x44, 0x49, 0x36, 0x1b, + 0x63, 0xd3, 0x1e, 0x28, 0xa9, 0xe9, 0x9e, 0xba, 0x0f, 0x17, 0xda, 0xae, 0x31, 0xc4, 0xe2, 0x48, + 0x4c, 0x2a, 0x97, 0x7c, 0x0b, 0xd6, 0x7d, 0x2c, 0x82, 0xfa, 0x43, 0xd3, 0xf3, 0xd9, 0x13, 0x2c, + 0xfa, 0x06, 0xb5, 0x19, 0xbf, 0xcf, 0x9f, 0x4a, 0x65, 0xb3, 0x72, 0x99, 0x61, 0xb6, 0x05, 0x84, + 0x04, 0x88, 0x1d, 0x06, 0x50, 0x7f, 0x00, 0xa5, 0xba, 0xe9, 0x8d, 0x75, 0x1f, 0x75, 0xcb, 0xd6, + 0x49, 0xb9, 0x0d, 0xa5, 0x21, 0xc5, 0x1a, 0xf6, 0x80, 0xea, 0x98, 0x07, 0xa9, 0x6b, 0x3a, 0x83, + 0x27, 0xb2, 0xc3, 0x6a, 0x28, 0xd5, 0xe1, 0x42, 0xea, 0x97, 0x98, 0xb5, 0xd9, 0xdb, 0x94, 0xd4, + 0xfb, 0x0a, 0x9c, 0xf7, 0x6c, 0x7d, 0xec, 0x0d, 0x1d, 0xbf, 0x6f, 0xda, 0x3e, 0x7b, 0x8c, 0xb5, + 0x64, 0xfd, 0x5b, 0x0a, 0x18, 0x4d, 0x49, 0xc7, 0x78, 0xac, 0x1c, 0x53, 0x3a, 0xee, 0x3b, 0xd6, + 0xa0, 0x1f, 0x30, 0xc5, 0x03, 0x2c, 0xa2, 0x19, 0xa7, 0x6d, 0x0d, 0xba, 0x01, 0x5d, 0xa9, 0xc2, + 0x86, 0xe5, 0x1c, 0xf5, 0x71, 0x67, 0x2e, 0xde, 0xf5, 0xfe, 0xa1, 0xe3, 0xf6, 0x3d, 0xcb, 0x39, + 0xc5, 0x0f, 0x0b, 0xff, 0xa8, 0x1b, 0x34, 0x17, 0x65, 0x44, 0x35, 0x04, 0x68, 0xcb, 0x71, 0xbb, + 0xc8, 0xdb, 0x0a, 0x10, 0x2c, 0xb5, 0xcf, 0xb6, 0xed, 0x9b, 0xc6, 0x71, 0x90, 0xda, 0x43, 0x6a, + 0x0f, 0x89, 0x18, 0xdd, 0x96, 0xa9, 0x45, 0x0d, 0x6e, 0x64, 0x8e, 0xca, 0x70, 0x54, 0x31, 0x20, + 0x32, 0x90, 0xfa, 0xbf, 0x90, 0xef, 0x58, 0xba, 0xc1, 0x9f, 0xb9, 0x59, 0xc5, 0x8f, 0x69, 0x8b, + 0x9d, 0x1c, 0xee, 0x5a, 0x84, 0xb4, 0x3c, 0x89, 0x92, 0xd4, 0xf7, 0x31, 0xd1, 0x13, 0xc7, 0xf1, + 0xf1, 0x92, 0x5e, 0x85, 0xac, 0xa1, 0xf7, 0x03, 0x77, 0x2f, 0x56, 0xf3, 0xe8, 0x16, 0x99, 0x9a, + 0x76, 0x87, 0x4e, 0x49, 0xc6, 0xd0, 0xf1, 0x8f, 0xa5, 0x3c, 0x44, 0x30, 0x27, 0xe5, 0xe6, 0x28, + 0x8a, 0x94, 0x87, 0x5e, 0x8c, 0x14, 0x82, 0xc2, 0xec, 0x1f, 0xa3, 0x5a, 0x51, 0x82, 0xfa, 0x43, + 0xdd, 0x1b, 0x8a, 0x02, 0xb1, 0xba, 0x82, 0x48, 0x10, 0xc8, 0x6d, 0xa4, 0x12, 0x10, 0x68, 0xf6, + 0xad, 0xfe, 0x25, 0x01, 0x05, 0x36, 0x30, 0x0f, 0x4d, 0x83, 0xe5, 0x96, 0xaf, 0x1f, 0x17, 0x31, + 0x30, 0x18, 0x9e, 0x2b, 0x17, 0xc5, 0x03, 0x43, 0xad, 0x4b, 0x08, 0xa3, 0x29, 0xef, 0x60, 0x48, + 0xe4, 0xb9, 0x4d, 0x86, 0x44, 0xf5, 0xab, 0xb3, 0xa0, 0xec, 0x6c, 0xa4, 0x1c, 0x37, 0xe2, 0x6c, + 0x75, 0xfc, 0x68, 0x8a, 0x24, 0x4a, 0x62, 0x4f, 0xf4, 0x86, 0xcd, 0x4f, 0x43, 0x3e, 0xd1, 0xd7, + 0x5a, 0x04, 0x29, 0xea, 0x9f, 0x12, 0xb0, 0xdc, 0xb0, 0x0d, 0x77, 0xca, 0x43, 0x0a, 0xb3, 0xe0, + 0x3a, 0xe4, 0xb1, 0x80, 0xf6, 0xa6, 0x1e, 0x76, 0x99, 0xc1, 0x0b, 0x60, 0x48, 0x50, 0x9a, 0x90, + 0xc7, 0xe0, 0xe9, 0xb8, 0xa6, 0x3f, 0x1c, 0xc9, 0x4a, 0x32, 0x3e, 0x8c, 0x45, 0x75, 0x56, 0xb4, + 0x40, 0x84, 0xcc, 0xa4, 0x83, 0xc0, 0x95, 0xe2, 0x8b, 0xe5, 0x81, 0x0b, 0x7b, 0x5e, 0x0b, 0xdb, + 0x1b, 0xac, 0x11, 0xfb, 0xac, 0x6b, 0xe0, 0xfb, 0xc0, 0xf6, 0x4f, 0xd2, 0x58, 0x27, 0xa4, 0xaa, + 0x90, 0x0f, 0x95, 0xb1, 0x77, 0x57, 0xad, 0xd1, 0xed, 0xdf, 0xd8, 0xbc, 0xd9, 0xbf, 0x5d, 0xdb, + 0xc5, 0x30, 0x26, 0xf2, 0xe6, 0x1f, 0x70, 0x4f, 0xbb, 0xba, 0x8d, 0x9d, 0x4d, 0xd0, 0xe7, 0xa1, + 0x57, 0xb8, 0x78, 0xd5, 0x82, 0x42, 0x28, 0x2d, 0xbc, 0x82, 0xdd, 0x3e, 0x56, 0x08, 0x31, 0x56, + 0x7c, 0x21, 0x14, 0x79, 0x7f, 0x4e, 0x9d, 0xf9, 0xfe, 0x9c, 0xfe, 0x56, 0xde, 0x9f, 0x5f, 0xfe, + 0x32, 0x05, 0xf9, 0xb0, 0x6f, 0x63, 0x2e, 0xc3, 0xea, 0x92, 0x73, 0xa2, 0xa3, 0x0e, 0xe9, 0x2d, + 0x5e, 0x91, 0xe4, 0xb5, 0x9d, 0x9d, 0x76, 0x4d, 0x63, 0xcf, 0xb7, 0xef, 0x88, 0xc2, 0x25, 0x04, + 0x68, 0x78, 0x69, 0xd9, 0xa1, 0x0f, 0x14, 0x75, 0x56, 0xb8, 0xdc, 0x97, 0x7d, 0x7b, 0x88, 0x0a, + 0xaa, 0x96, 0xe7, 0x21, 0xa7, 0x75, 0xbb, 0xcd, 0xdb, 0x2d, 0xd4, 0xf4, 0x20, 0x51, 0x7e, 0x0a, + 0x41, 0xe7, 0x67, 0xaa, 0x30, 0xe1, 0x1e, 0xd9, 0xa8, 0x89, 0xa1, 0x6a, 0xb5, 0x46, 0x87, 0xcd, + 0x77, 0x3f, 0xb9, 0x88, 0xe2, 0xe9, 0x9a, 0xbf, 0xc1, 0xe5, 0x3b, 0xa4, 0xd1, 0xd1, 0x08, 0x9b, + 0xf1, 0x41, 0x72, 0x61, 0x5d, 0x1d, 0x97, 0x62, 0x27, 0xcf, 0xe6, 0xdc, 0x08, 0xde, 0xa2, 0xef, + 0xa7, 0xc4, 0x3b, 0xcd, 0xac, 0x59, 0x45, 0xfb, 0x4e, 0xd9, 0x6c, 0xdd, 0x9e, 0x46, 0x7a, 0x5c, + 0x4d, 0x6a, 0x61, 0xb6, 0x2e, 0x7b, 0x42, 0x60, 0x5a, 0x70, 0x77, 0x64, 0xaf, 0xd5, 0xe2, 0xbb, + 0x4b, 0x2f, 0xec, 0x8e, 0x4c, 0x6c, 0x9b, 0x61, 0xae, 0x61, 0x0a, 0x6b, 0xef, 0x76, 0x76, 0x1a, + 0xbd, 0x46, 0xe9, 0x41, 0x7a, 0x61, 0x41, 0x35, 0x67, 0x34, 0xb6, 0xa8, 0x2f, 0xb6, 0xd7, 0xdd, + 0xde, 0xeb, 0xf1, 0xa7, 0xf2, 0xfb, 0x99, 0xc5, 0x09, 0x87, 0x13, 0x7f, 0xc0, 0x4a, 0xc5, 0xab, + 0x61, 0xed, 0xf6, 0x20, 0x23, 0x52, 0x66, 0x88, 0x11, 0x85, 0x1b, 0xd3, 0x43, 0x1a, 0xdf, 0x17, + 0xaf, 0xea, 0xf7, 0xb3, 0x0b, 0x7a, 0x08, 0x7d, 0x0f, 0xa3, 0x20, 0x96, 0x77, 0xe1, 0x33, 0x54, + 0xc8, 0x7a, 0xf9, 0x87, 0x90, 0x0b, 0x02, 0x06, 0x5a, 0x27, 0x7b, 0xb7, 0x4d, 0xee, 0x34, 0x08, + 0x1e, 0x3d, 0xb7, 0x4e, 0xc0, 0xb9, 0xeb, 0xb8, 0xe8, 0x5d, 0xb8, 0x8c, 0xa5, 0x5d, 0xad, 0xa5, + 0xdd, 0x46, 0x80, 0x7c, 0x06, 0x0b, 0x00, 0xd2, 0xeb, 0xcb, 0x25, 0x39, 0x41, 0xa8, 0xb3, 0xba, + 0xfe, 0xf0, 0xb3, 0x8d, 0x73, 0x9f, 0xe0, 0xef, 0x8b, 0xcf, 0x36, 0x12, 0xf7, 0x3f, 0xdf, 0x48, + 0x3c, 0xc4, 0xdf, 0xc7, 0xf8, 0xfb, 0x3b, 0xfe, 0x0e, 0xb2, 0xbc, 0x7e, 0x79, 0xe3, 0x3f, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x24, 0xa1, 0x77, 0xb8, 0x17, 0x1e, 0x00, 0x00, } diff --git a/vendor/src/github.com/docker/swarmkit/api/types.proto b/vendor/src/github.com/docker/swarmkit/api/types.proto index 487a02a7d7..48c930ad91 100644 --- a/vendor/src/github.com/docker/swarmkit/api/types.proto +++ b/vendor/src/github.com/docker/swarmkit/api/types.proto @@ -139,20 +139,21 @@ message Mount { BIND = 0 [(gogoproto.enumvalue_customname) = "MountTypeBind"]; // Bind mount host dir VOLUME = 1 [(gogoproto.enumvalue_customname) = "MountTypeVolume"]; // Remote storage volumes + TMPFS = 2 [(gogoproto.enumvalue_customname) = "MountTypeTmpfs"]; // Mount a tmpfs } // Type defines the nature of the mount. Type type = 1; - // Source path to mount + // Source specifies the name of the mount. Depending on mount type, this + // may be a volume name or a host path, or even ignored. string source = 2; // Target path in container string target = 3; - // Writable should be set to true if the mount should be writable from the - // container. - bool writable = 4; + // ReadOnly should be set to true if the mount should not be writable. + bool readonly = 4 [(gogoproto.customname) = "ReadOnly"]; // BindOptions specifies options that are specific to a bind mount. message BindOptions { @@ -174,8 +175,8 @@ message Mount { // VolumeOptions contains parameters for mounting the volume. message VolumeOptions { - // populate volume with data from target - bool populate = 1; + // nocopy prevents automatic copying of data to the volume with data from target + bool nocopy = 1 [(gogoproto.customname) = "NoCopy"]; // labels to apply to the volume if creating map labels = 2; @@ -187,14 +188,58 @@ message Mount { Driver driver_config = 3; } + message TmpfsOptions { + // Size sets the size of the tmpfs, in bytes. + // + // This will be converted to an operating system specific value + // depending on the host. For example, on linux, it will be convered to + // use a 'k', 'm' or 'g' syntax. BSD, though not widely supported with + // docker, uses a straight byte value. + // + // Percentages are not supported. + int64 size_bytes = 1; + + // Mode of the tmpfs upon creation + int32 mode = 2 [(gogoproto.customtype) = "os.FileMode", (gogoproto.nullable) = false]; + + // TODO(stevvooe): There are several more tmpfs flags, specified in the + // daemon, that are accepted. Only the most basic are added for now. + // + // From docker/docker/pkg/mount/flags.go: + // + // var validFlags = map[string]bool{ + // "": true, + // "size": true, X + // "mode": true, X + // "uid": true, + // "gid": true, + // "nr_inodes": true, + // "nr_blocks": true, + // "mpol": true, + // } + // + // Some of these may be straightforward to add, but others, such as + // uid/gid have implications in a clustered system. + } + // Depending on type, one of bind_options or volumes_options will be set. // BindOptions configures properties of a bind mount type. + // + // For mounts of type bind, the source must be an absolute host path. BindOptions bind_options = 5; // VolumeOptions configures the properties specific to a volume mount type. + // + // For mounts of type volume, the source will be used as the volume name. VolumeOptions volume_options = 6; + // TmpfsOptions allows one to set options for mounting a temporary + // filesystem. + // + // The source field will be ignored when using mounts of type tmpfs. + TmpfsOptions tmpfs_options = 7; + // TODO(stevvooe): It be better to use a oneof field above, although the // type is enough to make the decision, while being primary to the // datastructure. @@ -427,10 +472,10 @@ message IssuanceStatus { message AcceptancePolicy { message RoleAdmissionPolicy { - message HashedSecret { - // The actual hashed content + message Secret { + // The actual content (possibly hashed) bytes data = 1; - // The type of hash we are using + // The type of hash we are using, or "plaintext" string alg = 2; } @@ -440,13 +485,12 @@ message AcceptancePolicy { bool autoaccept = 2; // Secret represents a user-provided string that is necessary for new // nodes to join the cluster - HashedSecret secret = 3; + Secret secret = 3; } repeated RoleAdmissionPolicy policies = 1; } - message ExternalCA { enum CAProtocol { CFSSL = 0 [(gogoproto.enumvalue_customname) = "CAProtocolCFSSL"]; diff --git a/vendor/src/github.com/docker/swarmkit/ca/server.go b/vendor/src/github.com/docker/swarmkit/ca/server.go index ee6325375c..229df2e4f4 100644 --- a/vendor/src/github.com/docker/swarmkit/ca/server.go +++ b/vendor/src/github.com/docker/swarmkit/ca/server.go @@ -1,6 +1,8 @@ package ca import ( + "crypto/subtle" + "errors" "fmt" "strings" "sync" @@ -255,7 +257,7 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod } // checkSecretValidity verifies if a secret string matches the secret hash stored in the -// Acceptance Policy. It currently only supports bcrypted hashes. +// Acceptance Policy. It currently only supports bcrypted hashes and plaintext. func checkSecretValidity(policy *api.AcceptancePolicy_RoleAdmissionPolicy, secret string) error { if policy == nil || secret == "" { return fmt.Errorf("invalid policy or secret") @@ -264,6 +266,11 @@ func checkSecretValidity(policy *api.AcceptancePolicy_RoleAdmissionPolicy, secre switch strings.ToLower(policy.Secret.Alg) { case "bcrypt": return bcrypt.CompareHashAndPassword(policy.Secret.Data, []byte(secret)) + case "plaintext": + if subtle.ConstantTimeCompare(policy.Secret.Data, []byte(secret)) == 1 { + return nil + } + return errors.New("incorrect secret") } return fmt.Errorf("hash algorithm not supported: %s", policy.Secret.Alg) diff --git a/vendor/src/github.com/docker/swarmkit/identity/randomid.go b/vendor/src/github.com/docker/swarmkit/identity/randomid.go index eecc612f37..f59179b164 100644 --- a/vendor/src/github.com/docker/swarmkit/identity/randomid.go +++ b/vendor/src/github.com/docker/swarmkit/identity/randomid.go @@ -16,9 +16,8 @@ var ( // parameters for random identifier generation. We can tweak this when there is // time for further analysis. const ( - randomIDEntropyBytes = 16 - randomNodeIDEntropyBytes = 8 - randomIDBase = 36 + randomIDEntropyBytes = 16 + randomIDBase = 36 // To ensure that all identifiers are fixed length, we make sure they // get padded out to 25 characters, which is the maximum for the base36 @@ -28,8 +27,7 @@ const ( // was calculated from floor(log(2^128-1, 36)) + 1. // // See http://mathworld.wolfram.com/NumberLength.html for more information. - maxRandomIDLength = 25 - maxRandomNodeIDLength = 13 + maxRandomIDLength = 25 ) // NewID generates a new identifier for use where random identifiers with low diff --git a/vendor/src/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go b/vendor/src/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go index c9c32d48a3..8bf181cd07 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go +++ b/vendor/src/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go @@ -8,6 +8,8 @@ import ( "github.com/docker/libnetwork/drivers/overlay/ovmanager" "github.com/docker/libnetwork/drvregistry" "github.com/docker/libnetwork/ipamapi" + builtinIpam "github.com/docker/libnetwork/ipams/builtin" + nullIpam "github.com/docker/libnetwork/ipams/null" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" "golang.org/x/net/context" @@ -76,6 +78,15 @@ func New() (*NetworkAllocator, error) { return nil, err } + for _, fn := range [](func(ipamapi.Callback, interface{}, interface{}) error){ + builtinIpam.Init, + nullIpam.Init, + } { + if err := fn(reg, nil, nil); err != nil { + return nil, err + } + } + pa, err := newPortAllocator() if err != nil { return nil, err diff --git a/vendor/src/github.com/docker/swarmkit/manager/controlapi/node.go b/vendor/src/github.com/docker/swarmkit/manager/controlapi/node.go index b2ec541eee..b730224fb6 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/controlapi/node.go +++ b/vendor/src/github.com/docker/swarmkit/manager/controlapi/node.go @@ -2,6 +2,7 @@ package controlapi import ( "github.com/docker/swarmkit/api" + "github.com/docker/swarmkit/manager/state/raft/membership" "github.com/docker/swarmkit/manager/state/store" "golang.org/x/net/context" "google.golang.org/grpc" @@ -188,8 +189,10 @@ func (s *Server) UpdateNode(ctx context.Context, request *api.UpdateNodeRequest) var ( node *api.Node + member *membership.Member demote bool ) + err := s.store.Update(func(tx store.Tx) error { node = store.GetNode(tx, request.NodeID) if node == nil { @@ -199,6 +202,8 @@ func (s *Server) UpdateNode(ctx context.Context, request *api.UpdateNodeRequest) // Demotion sanity checks. if node.Spec.Role == api.NodeRoleManager && request.Spec.Role == api.NodeRoleWorker { demote = true + + // Check for manager entries in Store. managers, err := store.FindNodes(tx, store.ByRole(api.NodeRoleManager)) if err != nil { return grpc.Errorf(codes.Internal, "internal store error: %v", err) @@ -206,6 +211,16 @@ func (s *Server) UpdateNode(ctx context.Context, request *api.UpdateNodeRequest) if len(managers) == 1 && managers[0].ID == node.ID { return grpc.Errorf(codes.FailedPrecondition, "attempting to demote the last manager of the swarm") } + + // Check for node in memberlist + if member = s.raft.GetMemberByNodeID(request.NodeID); member == nil { + return grpc.Errorf(codes.NotFound, "can't find manager in raft memberlist") + } + + // Quorum safeguard + if !s.raft.CanRemoveMember(member.RaftID) { + return grpc.Errorf(codes.FailedPrecondition, "can't remove member from the raft: this would result in a loss of quorum") + } } node.Meta.Version = *request.NodeVersion @@ -220,14 +235,12 @@ func (s *Server) UpdateNode(ctx context.Context, request *api.UpdateNodeRequest) } if demote && s.raft != nil { - memberlist := s.raft.GetMemberlist() - for raftID, member := range memberlist { - if member.NodeID == request.NodeID { - if err := s.raft.RemoveMember(ctx, raftID); err != nil { - return nil, err - } - break - } + // TODO(abronan): the remove can potentially fail and leave the node with + // an incorrect role (worker rather than manager), we need to reconcile the + // memberlist with the desired state rather than attempting to remove the + // member once. + if err := s.raft.RemoveMember(ctx, member.RaftID); err != nil { + return nil, grpc.Errorf(codes.Internal, "cannot demote manager to worker: %v", err) } } diff --git a/vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go b/vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go index 253f71b724..20a8468777 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go +++ b/vendor/src/github.com/docker/swarmkit/manager/controlapi/service.go @@ -7,6 +7,7 @@ import ( "github.com/docker/engine-api/types/reference" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/identity" + "github.com/docker/swarmkit/manager/scheduler" "github.com/docker/swarmkit/manager/state/store" "github.com/docker/swarmkit/protobuf/ptypes" "golang.org/x/net/context" @@ -75,6 +76,14 @@ func validateRestartPolicy(rp *api.RestartPolicy) error { return nil } +func validatePlacement(placement *api.Placement) error { + if placement == nil { + return nil + } + _, err := scheduler.ParseExprs(placement.Constraints) + return err +} + func validateUpdate(uc *api.UpdateConfig) error { if uc == nil { return nil @@ -101,6 +110,10 @@ func validateTask(taskSpec api.TaskSpec) error { return err } + if err := validatePlacement(taskSpec.Placement); err != nil { + return err + } + if taskSpec.GetRuntime() == nil { return grpc.Errorf(codes.InvalidArgument, "TaskSpec: missing runtime") } diff --git a/vendor/src/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go b/vendor/src/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go index 4f040b50dd..64dd08872f 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go +++ b/vendor/src/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go @@ -328,14 +328,14 @@ func (d *Dispatcher) isRunning() bool { } // register is used for registration of node with particular dispatcher. -func (d *Dispatcher) register(ctx context.Context, nodeID string, description *api.NodeDescription) (string, string, error) { +func (d *Dispatcher) register(ctx context.Context, nodeID string, description *api.NodeDescription) (string, error) { // prevent register until we're ready to accept it if err := d.isRunningLocked(); err != nil { - return "", "", err + return "", err } if err := d.nodes.CheckRateLimit(nodeID); err != nil { - return "", "", err + return "", err } // create or update node in store @@ -355,7 +355,7 @@ func (d *Dispatcher) register(ctx context.Context, nodeID string, description *a }) if err != nil { - return "", "", err + return "", err } expireFunc := func() { @@ -377,7 +377,7 @@ func (d *Dispatcher) register(ctx context.Context, nodeID string, description *a // time a node registers, we invalidate the session and issue a new // session, once identity is proven. This will cause misbehaved agents to // be kicked when multiple connections are made. - return rn.Node.ID, rn.SessionID, nil + return rn.SessionID, nil } // UpdateTaskStatus updates status of task. Node should send such updates @@ -650,7 +650,7 @@ func (d *Dispatcher) Session(r *api.SessionRequest, stream api.Dispatcher_Sessio } // register the node. - nodeID, sessionID, err := d.register(stream.Context(), nodeID, r.Description) + sessionID, err := d.register(stream.Context(), nodeID, r.Description) if err != nil { return err } diff --git a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/global.go b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/global.go index bc6a0075e8..f6928af3e9 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/global.go +++ b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/global.go @@ -24,6 +24,8 @@ type GlobalOrchestrator struct { updater *UpdateSupervisor restarts *RestartSupervisor + + cluster *api.Cluster // local instance of the cluster } // NewGlobalOrchestrator creates a new GlobalOrchestrator @@ -50,11 +52,23 @@ func (g *GlobalOrchestrator) Run(ctx context.Context) error { watcher, cancel := queue.Watch() defer cancel() + // lookup the cluster + var err error + g.store.View(func(readTx store.ReadTx) { + var clusters []*api.Cluster + clusters, err = store.FindClusters(readTx, store.ByName("default")) + + if len(clusters) != 1 { + return // just pick up the cluster when it is created. + } + g.cluster = clusters[0] + }) + if err != nil { + return err + } + // Get list of nodes - var ( - nodes []*api.Node - err error - ) + var nodes []*api.Node g.store.View(func(readTx store.ReadTx) { nodes, err = store.FindNodes(readTx, store.All) }) @@ -88,6 +102,8 @@ func (g *GlobalOrchestrator) Run(ctx context.Context) error { case event := <-watcher: // TODO(stevvooe): Use ctx to limit running time of operation. switch v := event.(type) { + case state.EventUpdateCluster: + g.cluster = v.Cluster case state.EventCreateService: if !isGlobalService(v.Service) { continue @@ -228,7 +244,7 @@ func (g *GlobalOrchestrator) reconcileOneService(ctx context.Context, service *a } } if len(updateTasks) > 0 { - g.updater.Update(ctx, service, updateTasks) + g.updater.Update(ctx, g.cluster, service, updateTasks) } return nil }) @@ -325,7 +341,7 @@ func (g *GlobalOrchestrator) reconcileServiceOneNode(ctx context.Context, servic } // restartTask calls the restart supervisor's Restart function, which -// sets a task's desired state to dead and restarts it if the restart +// sets a task's desired state to shutdown and restarts it if the restart // policy calls for it to be restarted. func (g *GlobalOrchestrator) restartTask(ctx context.Context, taskID string, serviceID string) { err := g.store.Update(func(tx store.Tx) error { @@ -337,7 +353,7 @@ func (g *GlobalOrchestrator) restartTask(ctx context.Context, taskID string, ser if service == nil { return nil } - return g.restarts.Restart(ctx, tx, service, *t) + return g.restarts.Restart(ctx, tx, g.cluster, service, *t) }) if err != nil { log.G(ctx).WithError(err).Errorf("global orchestrator: restartTask transaction failed") @@ -361,7 +377,7 @@ func (g *GlobalOrchestrator) removeTask(ctx context.Context, batch *store.Batch, } func (g *GlobalOrchestrator) addTask(ctx context.Context, batch *store.Batch, service *api.Service, nodeID string) { - task := newTask(service, 0) + task := newTask(g.cluster, service, 0) task.NodeID = nodeID err := batch.Update(func(tx store.Tx) error { diff --git a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated.go b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated.go index 485e4ef914..826c8443c4 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated.go +++ b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated.go @@ -27,6 +27,8 @@ type ReplicatedOrchestrator struct { updater *UpdateSupervisor restarts *RestartSupervisor + + cluster *api.Cluster // local cluster instance } // NewReplicatedOrchestrator creates a new ReplicatedOrchestrator. @@ -61,6 +63,7 @@ func (r *ReplicatedOrchestrator) Run(ctx context.Context) error { return } err = r.initServices(readTx) + err = r.initCluster(readTx) }) if err != nil { return err @@ -74,9 +77,11 @@ func (r *ReplicatedOrchestrator) Run(ctx context.Context) error { // TODO(stevvooe): Use ctx to limit running time of operation. r.handleTaskEvent(ctx, event) r.handleServiceEvent(ctx, event) - switch event.(type) { + switch v := event.(type) { case state.EventCommit: r.tick(ctx) + case state.EventUpdateCluster: + r.cluster = v.Cluster } case <-r.stopChan: return nil @@ -99,7 +104,16 @@ func (r *ReplicatedOrchestrator) tick(ctx context.Context) { r.tickServices(ctx) } -func newTask(service *api.Service, instance uint64) *api.Task { +func newTask(cluster *api.Cluster, service *api.Service, instance uint64) *api.Task { + var logDriver *api.Driver + if service.Spec.Task.LogDriver != nil { + // use the log driver specific to the task, if we have it. + logDriver = service.Spec.Task.LogDriver + } else if cluster != nil { + // pick up the cluster default, if available. + logDriver = cluster.Spec.DefaultLogDriver // nil is okay here. + } + // NOTE(stevvooe): For now, we don't override the container naming and // labeling scheme in the agent. If we decide to do this in the future, // they should be overridden here. @@ -118,6 +132,7 @@ func newTask(service *api.Service, instance uint64) *api.Task { Spec: service.Spec.Endpoint.Copy(), }, DesiredState: api.TaskStateRunning, + LogDriver: logDriver, } } diff --git a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/restart.go b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/restart.go index f7ab79b6e1..72cbcc378d 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/restart.go +++ b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/restart.go @@ -59,7 +59,7 @@ func NewRestartSupervisor(store *store.MemoryStore) *RestartSupervisor { // Restart initiates a new task to replace t if appropriate under the service's // restart policy. -func (r *RestartSupervisor) Restart(ctx context.Context, tx store.Tx, service *api.Service, t api.Task) error { +func (r *RestartSupervisor) Restart(ctx context.Context, tx store.Tx, cluster *api.Cluster, service *api.Service, t api.Task) error { // TODO(aluzzardi): This function should not depend on `service`. t.DesiredState = api.TaskStateShutdown @@ -76,9 +76,9 @@ func (r *RestartSupervisor) Restart(ctx context.Context, tx store.Tx, service *a var restartTask *api.Task if isReplicatedService(service) { - restartTask = newTask(service, t.Slot) + restartTask = newTask(cluster, service, t.Slot) } else if isGlobalService(service) { - restartTask = newTask(service, 0) + restartTask = newTask(cluster, service, 0) restartTask.NodeID = t.NodeID } else { log.G(ctx).Error("service not supported by restart supervisor") diff --git a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/services.go b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/services.go index 6dd7e0d66f..afe8591f26 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/services.go +++ b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/services.go @@ -16,6 +16,21 @@ import ( // specifications. This is different from task-level orchestration, which // responds to changes in individual tasks (or nodes which run them). +func (r *ReplicatedOrchestrator) initCluster(readTx store.ReadTx) error { + clusters, err := store.FindClusters(readTx, store.ByName("default")) + if err != nil { + return err + } + + if len(clusters) != 1 { + // we'll just pick it when it is created. + return nil + } + + r.cluster = clusters[0] + return nil +} + func (r *ReplicatedOrchestrator) initServices(readTx store.ReadTx) error { services, err := store.FindServices(readTx, store.All) if err != nil { @@ -70,6 +85,15 @@ func (r *ReplicatedOrchestrator) resolveService(ctx context.Context, task *api.T return service } +type tasksByRunningState []*api.Task + +func (ts tasksByRunningState) Len() int { return len(ts) } +func (ts tasksByRunningState) Swap(i, j int) { ts[i], ts[j] = ts[j], ts[i] } + +func (ts tasksByRunningState) Less(i, j int) bool { + return ts[i].Status.State == api.TaskStateRunning && ts[j].Status.State != api.TaskStateRunning +} + type taskWithIndex struct { task *api.Task @@ -124,7 +148,7 @@ func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Ser case specifiedInstances > numTasks: log.G(ctx).Debugf("Service %s was scaled up from %d to %d instances", service.ID, numTasks, specifiedInstances) // Update all current tasks then add missing tasks - r.updater.Update(ctx, service, runningTasks) + r.updater.Update(ctx, r.cluster, service, runningTasks) _, err = r.store.Batch(func(batch *store.Batch) error { r.addTasks(ctx, batch, service, runningInstances, specifiedInstances-numTasks) return nil @@ -139,6 +163,14 @@ func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Ser // Preferentially remove tasks on the nodes that have the most // copies of this service, to leave a more balanced result. + + // First sort tasks such that tasks which are currently running + // (in terms of observed state) appear before non-running tasks. + // This will cause us to prefer to remove non-running tasks, all + // other things being equal in terms of node balance. + + sort.Sort(tasksByRunningState(runningTasks)) + // Assign each task an index that counts it as the nth copy of // of the service on its node (1, 2, 3, ...), and sort the // tasks by this counter value. @@ -162,7 +194,7 @@ func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Ser sortedTasks = append(sortedTasks, t.task) } - r.updater.Update(ctx, service, sortedTasks[:specifiedInstances]) + r.updater.Update(ctx, r.cluster, service, sortedTasks[:specifiedInstances]) _, err = r.store.Batch(func(batch *store.Batch) error { r.removeTasks(ctx, batch, service, sortedTasks[specifiedInstances:]) return nil @@ -173,7 +205,7 @@ func (r *ReplicatedOrchestrator) reconcile(ctx context.Context, service *api.Ser case specifiedInstances == numTasks: // Simple update, no scaling - update all tasks. - r.updater.Update(ctx, service, runningTasks) + r.updater.Update(ctx, r.cluster, service, runningTasks) } } @@ -189,7 +221,7 @@ func (r *ReplicatedOrchestrator) addTasks(ctx context.Context, batch *store.Batc } err := batch.Update(func(tx store.Tx) error { - return store.CreateTask(tx, newTask(service, instance)) + return store.CreateTask(tx, newTask(r.cluster, service, instance)) }) if err != nil { log.G(ctx).Errorf("Failed to create task: %v", err) diff --git a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/tasks.go b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/tasks.go index add5ed9a07..c6d4c2f368 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/tasks.go +++ b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/tasks.go @@ -149,7 +149,7 @@ func (r *ReplicatedOrchestrator) tickTasks(ctx context.Context) { } // Restart task if applicable - if err := r.restarts.Restart(ctx, tx, service, *t); err != nil { + if err := r.restarts.Restart(ctx, tx, r.cluster, service, *t); err != nil { return err } } diff --git a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/updater.go b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/updater.go index ba1047c954..cb0f241dbc 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/orchestrator/updater.go +++ b/vendor/src/github.com/docker/swarmkit/manager/orchestrator/updater.go @@ -36,7 +36,7 @@ func NewUpdateSupervisor(store *store.MemoryStore, restartSupervisor *RestartSup // Update starts an Update of `tasks` belonging to `service` in the background and returns immediately. // If an update for that service was already in progress, it will be cancelled before the new one starts. -func (u *UpdateSupervisor) Update(ctx context.Context, service *api.Service, tasks []*api.Task) { +func (u *UpdateSupervisor) Update(ctx context.Context, cluster *api.Cluster, service *api.Service, tasks []*api.Task) { u.l.Lock() defer u.l.Unlock() @@ -49,7 +49,7 @@ func (u *UpdateSupervisor) Update(ctx context.Context, service *api.Service, tas update := NewUpdater(u.store, u.restarts) u.updates[id] = update go func() { - update.Run(ctx, service, tasks) + update.Run(ctx, cluster, service, tasks) u.l.Lock() if u.updates[id] == update { delete(u.updates, id) @@ -98,7 +98,7 @@ func (u *Updater) Cancel() { } // Run starts the update and returns only once its complete or cancelled. -func (u *Updater) Run(ctx context.Context, service *api.Service, tasks []*api.Task) { +func (u *Updater) Run(ctx context.Context, cluster *api.Cluster, service *api.Service, tasks []*api.Task) { defer close(u.doneChan) dirtyTasks := []*api.Task{} @@ -130,7 +130,7 @@ func (u *Updater) Run(ctx context.Context, service *api.Service, tasks []*api.Ta wg.Add(parallelism) for i := 0; i < parallelism; i++ { go func() { - u.worker(ctx, service, taskQueue) + u.worker(ctx, cluster, service, taskQueue) wg.Done() }() } @@ -149,9 +149,9 @@ func (u *Updater) Run(ctx context.Context, service *api.Service, tasks []*api.Ta wg.Wait() } -func (u *Updater) worker(ctx context.Context, service *api.Service, queue <-chan *api.Task) { +func (u *Updater) worker(ctx context.Context, cluster *api.Cluster, service *api.Service, queue <-chan *api.Task) { for t := range queue { - updated := newTask(service, t.Slot) + updated := newTask(cluster, service, t.Slot) updated.DesiredState = api.TaskStateReady if isGlobalService(service) { updated.NodeID = t.NodeID diff --git a/vendor/src/github.com/docker/swarmkit/manager/scheduler/constraint.go b/vendor/src/github.com/docker/swarmkit/manager/scheduler/constraint.go index b1b6d31aa3..61be3b907a 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/scheduler/constraint.go +++ b/vendor/src/github.com/docker/swarmkit/manager/scheduler/constraint.go @@ -6,6 +6,11 @@ import ( "github.com/docker/swarmkit/api" ) +const ( + nodeLabelPrefix = "node.labels." + engineLabelPrefix = "engine.labels." +) + // ConstraintFilter selects only nodes that match certain labels. type ConstraintFilter struct { constraints []Expr @@ -13,25 +18,30 @@ type ConstraintFilter struct { // SetTask returns true when the filter is enable for a given task. func (f *ConstraintFilter) SetTask(t *api.Task) bool { - if t.Spec.Placement != nil && len(t.Spec.Placement.Constraints) > 0 { - constraints, err := ParseExprs(t.Spec.Placement.Constraints) - if err == nil { - f.constraints = constraints - return true - } + if t.Spec.Placement == nil || len(t.Spec.Placement.Constraints) == 0 { + return false } - return false + + constraints, err := ParseExprs(t.Spec.Placement.Constraints) + if err != nil { + // constraints have been validated at controlapi + // if in any case it finds an error here, treat this task + // as constraint filter disabled. + return false + } + f.constraints = constraints + return true } // Check returns true if the task's constraint is supported by the given node. func (f *ConstraintFilter) Check(n *NodeInfo) bool { for _, constraint := range f.constraints { - switch constraint.Key { - case "node.id": + switch { + case strings.EqualFold(constraint.Key, "node.id"): if !constraint.Match(n.ID) { return false } - case "node.name": + case strings.EqualFold(constraint.Key, "node.hostname"): // if this node doesn't have hostname // it's equivalent to match an empty hostname // where '==' would fail, '!=' matches @@ -44,29 +54,42 @@ func (f *ConstraintFilter) Check(n *NodeInfo) bool { if !constraint.Match(n.Description.Hostname) { return false } - default: - // default is node label in form like 'node.labels.key==value' - // if it is not well formed, always fails it - if !strings.HasPrefix(constraint.Key, "node.labels.") { + case strings.EqualFold(constraint.Key, "node.role"): + if !constraint.Match(n.Spec.Role.String()) { return false } - // if the node doesn't have any label, - // it's equivalent to match an empty value. - // that is, 'node.labels.key!=value' should pass and - // 'node.labels.key==value' should fail + + // node labels constraint in form like 'node.labels.key==value' + case len(constraint.Key) > len(nodeLabelPrefix) && strings.EqualFold(constraint.Key[:len(nodeLabelPrefix)], nodeLabelPrefix): if n.Spec.Annotations.Labels == nil { if !constraint.Match("") { return false } continue } - label := constraint.Key[len("node.labels."):] - // if the node doesn't have this specific label, - // val is an empty string + label := constraint.Key[len(nodeLabelPrefix):] + // label itself is case sensitive val := n.Spec.Annotations.Labels[label] if !constraint.Match(val) { return false } + + // engine labels constraint in form like 'engine.labels.key!=value' + case len(constraint.Key) > len(engineLabelPrefix) && strings.EqualFold(constraint.Key[:len(engineLabelPrefix)], engineLabelPrefix): + if n.Description == nil || n.Description.Engine == nil || n.Description.Engine.Labels == nil { + if !constraint.Match("") { + return false + } + continue + } + label := constraint.Key[len(engineLabelPrefix):] + val := n.Description.Engine.Labels[label] + if !constraint.Match(val) { + return false + } + default: + // key doesn't match predefined syntax + return false } } diff --git a/vendor/src/github.com/docker/swarmkit/manager/scheduler/expr.go b/vendor/src/github.com/docker/swarmkit/manager/scheduler/expr.go index eda9f36531..5a6697117c 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/scheduler/expr.go +++ b/vendor/src/github.com/docker/swarmkit/manager/scheduler/expr.go @@ -78,7 +78,8 @@ func (e *Expr) Match(whats ...string) bool { // full string match for _, what := range whats { - if e.exp == what { + // case insensitive compare + if strings.EqualFold(e.exp, what) { match = true break } diff --git a/vendor/src/github.com/docker/swarmkit/manager/scheduler/indexed_node_heap.go b/vendor/src/github.com/docker/swarmkit/manager/scheduler/indexed_node_heap.go index 8732595e38..0cc5c0b37b 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/scheduler/indexed_node_heap.go +++ b/vendor/src/github.com/docker/swarmkit/manager/scheduler/indexed_node_heap.go @@ -2,10 +2,13 @@ package scheduler import ( "container/heap" + "errors" "github.com/docker/swarmkit/api" ) +var errNodeNotFound = errors.New("node not found in scheduler heap") + // A nodeHeap implements heap.Interface for nodes. It also includes an index // by node id. type nodeHeap struct { @@ -49,20 +52,17 @@ func (nh *nodeHeap) alloc(n int) { } // nodeInfo returns the NodeInfo struct for a given node identified by its ID. -func (nh *nodeHeap) nodeInfo(nodeID string) NodeInfo { +func (nh *nodeHeap) nodeInfo(nodeID string) (NodeInfo, error) { index, ok := nh.index[nodeID] if ok { - return nh.heap[index] + return nh.heap[index], nil } - return NodeInfo{} + return NodeInfo{}, errNodeNotFound } // addOrUpdateNode sets the number of tasks for a given node. It adds the node // to the heap if it wasn't already tracked. func (nh *nodeHeap) addOrUpdateNode(n NodeInfo) { - if n.Node == nil { - return - } index, ok := nh.index[n.ID] if ok { nh.heap[index] = n @@ -75,9 +75,6 @@ func (nh *nodeHeap) addOrUpdateNode(n NodeInfo) { // updateNode sets the number of tasks for a given node. It ignores the update // if the node isn't already tracked in the heap. func (nh *nodeHeap) updateNode(n NodeInfo) { - if n.Node == nil { - return - } index, ok := nh.index[n.ID] if ok { nh.heap[index] = n diff --git a/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go b/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go index a6e92fa6c3..cc7f9b026e 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go +++ b/vendor/src/github.com/docker/swarmkit/manager/scheduler/nodeinfo.go @@ -23,7 +23,7 @@ func newNodeInfo(n *api.Node, tasks map[string]*api.Task, availableResources api } func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool { - if nodeInfo.Tasks == nil || nodeInfo.Node == nil { + if nodeInfo.Tasks == nil { return false } if _, ok := nodeInfo.Tasks[t.ID]; !ok { @@ -39,9 +39,6 @@ func (nodeInfo *NodeInfo) removeTask(t *api.Task) bool { } func (nodeInfo *NodeInfo) addTask(t *api.Task) bool { - if nodeInfo.Node == nil { - return false - } if nodeInfo.Tasks == nil { nodeInfo.Tasks = make(map[string]*api.Task) } diff --git a/vendor/src/github.com/docker/swarmkit/manager/scheduler/scheduler.go b/vendor/src/github.com/docker/swarmkit/manager/scheduler/scheduler.go index 6a57d4898b..e03c8a3360 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/scheduler/scheduler.go +++ b/vendor/src/github.com/docker/swarmkit/manager/scheduler/scheduler.go @@ -177,8 +177,8 @@ func (s *Scheduler) createTask(ctx context.Context, t *api.Task) int { return 0 } - nodeInfo := s.nodeHeap.nodeInfo(t.NodeID) - if nodeInfo.addTask(t) { + nodeInfo, err := s.nodeHeap.nodeInfo(t.NodeID) + if err == nil && nodeInfo.addTask(t) { s.nodeHeap.updateNode(nodeInfo) } @@ -224,8 +224,8 @@ func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) int { } s.allTasks[t.ID] = t - nodeInfo := s.nodeHeap.nodeInfo(t.NodeID) - if nodeInfo.addTask(t) { + nodeInfo, err := s.nodeHeap.nodeInfo(t.NodeID) + if err == nil && nodeInfo.addTask(t) { s.nodeHeap.updateNode(nodeInfo) } @@ -235,14 +235,14 @@ func (s *Scheduler) updateTask(ctx context.Context, t *api.Task) int { func (s *Scheduler) deleteTask(ctx context.Context, t *api.Task) { delete(s.allTasks, t.ID) delete(s.preassignedTasks, t.ID) - nodeInfo := s.nodeHeap.nodeInfo(t.NodeID) - if nodeInfo.removeTask(t) { + nodeInfo, err := s.nodeHeap.nodeInfo(t.NodeID) + if err == nil && nodeInfo.removeTask(t) { s.nodeHeap.updateNode(nodeInfo) } } func (s *Scheduler) createOrUpdateNode(n *api.Node) { - nodeInfo := s.nodeHeap.nodeInfo(n.ID) + nodeInfo, _ := s.nodeHeap.nodeInfo(n.ID) var resources api.Resources if n.Description != nil && n.Description.Resources != nil { resources = *n.Description.Resources @@ -275,9 +275,10 @@ func (s *Scheduler) processPreassignedTasks(ctx context.Context) { } for _, decision := range failed { s.allTasks[decision.old.ID] = decision.old - nodeInfo := s.nodeHeap.nodeInfo(decision.new.NodeID) - nodeInfo.removeTask(decision.new) - s.nodeHeap.updateNode(nodeInfo) + nodeInfo, err := s.nodeHeap.nodeInfo(decision.new.NodeID) + if err == nil && nodeInfo.removeTask(decision.new) { + s.nodeHeap.updateNode(nodeInfo) + } } } @@ -309,9 +310,10 @@ func (s *Scheduler) tick(ctx context.Context) { for _, decision := range failed { s.allTasks[decision.old.ID] = decision.old - nodeInfo := s.nodeHeap.nodeInfo(decision.new.NodeID) - nodeInfo.removeTask(decision.new) - s.nodeHeap.updateNode(nodeInfo) + nodeInfo, err := s.nodeHeap.nodeInfo(decision.new.NodeID) + if err == nil && nodeInfo.removeTask(decision.new) { + s.nodeHeap.updateNode(nodeInfo) + } // enqueue task for next scheduling attempt s.enqueue(decision.old) @@ -368,7 +370,11 @@ func (s *Scheduler) applySchedulingDecisions(ctx context.Context, schedulingDeci // taskFitNode checks if a node has enough resource to accommodate a task func (s *Scheduler) taskFitNode(ctx context.Context, t *api.Task, nodeID string) *api.Task { - nodeInfo := s.nodeHeap.nodeInfo(nodeID) + nodeInfo, err := s.nodeHeap.nodeInfo(nodeID) + if err != nil { + // node does not exist in heap (it may have been deleted) + return nil + } s.pipeline.SetTask(t) if !s.pipeline.Process(&nodeInfo) { // this node cannot accommodate this task @@ -407,8 +413,8 @@ func (s *Scheduler) scheduleTask(ctx context.Context, t *api.Task) *api.Task { } s.allTasks[t.ID] = &newT - nodeInfo := s.nodeHeap.nodeInfo(n.ID) - if nodeInfo.addTask(&newT) { + nodeInfo, err := s.nodeHeap.nodeInfo(n.ID) + if err == nil && nodeInfo.addTask(&newT) { s.nodeHeap.updateNode(nodeInfo) } return &newT diff --git a/vendor/src/github.com/docker/swarmkit/manager/state/raft/membership/cluster.go b/vendor/src/github.com/docker/swarmkit/manager/state/raft/membership/cluster.go index 89c91b8a7e..ec9d8bfac4 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/state/raft/membership/cluster.go +++ b/vendor/src/github.com/docker/swarmkit/manager/state/raft/membership/cluster.go @@ -113,6 +113,28 @@ func (c *Cluster) RemoveMember(id uint64) error { return nil } +// ReplaceMemberConnection replaces the member's GRPC connection and GRPC +// client. +func (c *Cluster) ReplaceMemberConnection(id uint64, newConn *Member) error { + c.mu.Lock() + defer c.mu.Unlock() + + oldMember, ok := c.members[id] + if !ok { + return ErrIDNotFound + } + + oldMember.Conn.Close() + + newMember := *oldMember + newMember.Conn = newConn.Conn + newMember.RaftClient = newConn.RaftClient + + c.members[id] = &newMember + + return nil +} + // IsIDRemoved checks if a Member is in the remove set. func (c *Cluster) IsIDRemoved(id uint64) bool { c.mu.RLock() @@ -165,19 +187,11 @@ func (c *Cluster) ValidateConfigurationChange(cc raftpb.ConfChange) error { // that might block or harm the Cluster on Member recovery func (c *Cluster) CanRemoveMember(from uint64, id uint64) bool { members := c.Members() - - nmembers := 0 nreachable := 0 for _, m := range members { - // Skip the node that is going to be deleted - if m.RaftID == id { - continue - } - // Local node from where the remove is issued if m.RaftID == from { - nmembers++ nreachable++ continue } @@ -186,8 +200,6 @@ func (c *Cluster) CanRemoveMember(from uint64, id uint64) bool { if err == nil && connState == grpc.Ready { nreachable++ } - - nmembers++ } // Special case of 2 managers @@ -195,7 +207,7 @@ func (c *Cluster) CanRemoveMember(from uint64, id uint64) bool { return false } - nquorum := nmembers/2 + 1 + nquorum := (len(members)+1)/2 + 1 if nreachable < nquorum { return false } diff --git a/vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go b/vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go index a7875d1ec6..be66b9da42 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go +++ b/vendor/src/github.com/docker/swarmkit/manager/state/raft/raft.go @@ -94,6 +94,7 @@ type Node struct { wal *wal.WAL snapshotter *snap.Snapshotter wasLeader bool + restored bool isMember uint32 joinAddr string @@ -394,6 +395,18 @@ func (n *Node) Run(ctx context.Context) error { } } + // If we are the only registered member after + // restoring from the state, campaign to be the + // leader. + if !n.restored { + if len(n.cluster.Members()) <= 1 { + if err := n.Campaign(n.Ctx); err != nil { + panic("raft: cannot campaign to be the leader on node restore") + } + } + n.restored = true + } + // Advance the state machine n.Advance() @@ -638,7 +651,14 @@ func (n *Node) Leave(ctx context.Context, req *api.LeaveRequest) (*api.LeaveResp return &api.LeaveResponse{}, nil } -// RemoveMember submits a configuration change to remove a member from the raft cluster. +// CanRemoveMember checks if a member can be removed from +// the context of the current node. +func (n *Node) CanRemoveMember(id uint64) bool { + return n.cluster.CanRemoveMember(n.Config.ID, id) +} + +// RemoveMember submits a configuration change to remove a member from the raft cluster +// after checking if the operation would not result in a loss of quorum. func (n *Node) RemoveMember(ctx context.Context, id uint64) error { n.membershipLock.Lock() defer n.membershipLock.Unlock() @@ -828,6 +848,18 @@ func (n *Node) GetMemberlist() map[uint64]*api.RaftMember { return memberlist } +// GetMemberByNodeID returns member information based +// on its generic Node ID. +func (n *Node) GetMemberByNodeID(nodeID string) *membership.Member { + members := n.cluster.Members() + for _, member := range members { + if member.NodeID == nodeID { + return member + } + } + return nil +} + // IsMember checks if the raft node has effectively joined // a cluster of existing members. func (n *Node) IsMember() bool { @@ -968,6 +1000,14 @@ func (n *Node) sendToMember(members map[uint64]*membership.Member, m raftpb.Mess panic("node is nil") } n.ReportUnreachable(m.To) + + // Bounce the connection + newConn, err := n.ConnectToMember(conn.Addr, 0) + if err != nil { + n.Config.Logger.Errorf("could connect to member ID %x at %s: %v", m.To, conn.Addr, err) + } else { + n.cluster.ReplaceMemberConnection(m.To, newConn) + } } else if m.Type == raftpb.MsgSnap { n.ReportSnapshot(m.To, raft.SnapshotFinish) } @@ -1172,11 +1212,6 @@ func (n *Node) applyRemoveNode(cc raftpb.ConfChange) (err error) { } } - // Do not unregister yourself - if n.Config.ID == cc.NodeID { - return nil - } - return n.cluster.RemoveMember(cc.NodeID) } diff --git a/vendor/src/github.com/docker/swarmkit/manager/state/raft/storage.go b/vendor/src/github.com/docker/swarmkit/manager/state/raft/storage.go index c0d4b454aa..95074ffc19 100644 --- a/vendor/src/github.com/docker/swarmkit/manager/state/raft/storage.go +++ b/vendor/src/github.com/docker/swarmkit/manager/state/raft/storage.go @@ -65,7 +65,6 @@ func (n *Node) loadAndStart(ctx context.Context, forceNewCluster bool) error { return err } - n.Node = raft.RestartNode(n.Config) return nil }