mirror of https://github.com/docker/cli.git
Remove experimental "deploy" from "dab" files
The top-level `docker deploy` command (using the "Docker Application Bundle" (`.dab`) file format was introduced as an experimental feature in Docker 1.13 / 17.03, but superseded by support for Docker Compose files. With no development being done on this feature, and no active use of the file format, support for the DAB file format and the top-level `docker deploy` command (hidden by default in 19.03), is removed in this patch, in favour of `docker stack deploy` using compose files. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
8547dfcff7
commit
99ad13e374
|
@ -1,70 +0,0 @@
|
|||
package bundlefile
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Bundlefile stores the contents of a bundlefile
|
||||
type Bundlefile struct {
|
||||
Version string
|
||||
Services map[string]Service
|
||||
}
|
||||
|
||||
// Service is a service from a bundlefile
|
||||
type Service struct {
|
||||
Image string
|
||||
Command []string `json:",omitempty"`
|
||||
Args []string `json:",omitempty"`
|
||||
Env []string `json:",omitempty"`
|
||||
Labels map[string]string `json:",omitempty"`
|
||||
Ports []Port `json:",omitempty"`
|
||||
WorkingDir *string `json:",omitempty"`
|
||||
User *string `json:",omitempty"`
|
||||
Networks []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// Port is a port as defined in a bundlefile
|
||||
type Port struct {
|
||||
Protocol string
|
||||
Port uint32
|
||||
}
|
||||
|
||||
// LoadFile loads a bundlefile from a path to the file
|
||||
func LoadFile(reader io.Reader) (*Bundlefile, error) {
|
||||
bundlefile := &Bundlefile{}
|
||||
|
||||
decoder := json.NewDecoder(reader)
|
||||
if err := decoder.Decode(bundlefile); err != nil {
|
||||
switch jsonErr := err.(type) {
|
||||
case *json.SyntaxError:
|
||||
return nil, errors.Errorf(
|
||||
"JSON syntax error at byte %v: %s",
|
||||
jsonErr.Offset,
|
||||
jsonErr.Error())
|
||||
case *json.UnmarshalTypeError:
|
||||
return nil, errors.Errorf(
|
||||
"Unexpected type at byte %v. Expected %s but received %s.",
|
||||
jsonErr.Offset,
|
||||
jsonErr.Type,
|
||||
jsonErr.Value)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bundlefile, nil
|
||||
}
|
||||
|
||||
// Print writes the contents of the bundlefile to the output writer
|
||||
// as human readable json
|
||||
func Print(out io.Writer, bundle *Bundlefile) error {
|
||||
bytes, err := json.MarshalIndent(*bundle, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = out.Write(bytes)
|
||||
return err
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
package bundlefile
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
is "gotest.tools/assert/cmp"
|
||||
)
|
||||
|
||||
func TestLoadFileV01Success(t *testing.T) {
|
||||
reader := strings.NewReader(`{
|
||||
"Version": "0.1",
|
||||
"Services": {
|
||||
"redis": {
|
||||
"Image": "redis@sha256:4b24131101fa0117bcaa18ac37055fffd9176aa1a240392bb8ea85e0be50f2ce",
|
||||
"Networks": ["default"]
|
||||
},
|
||||
"web": {
|
||||
"Image": "dockercloud/hello-world@sha256:fe79a2cfbd17eefc344fb8419420808df95a1e22d93b7f621a7399fd1e9dca1d",
|
||||
"Networks": ["default"],
|
||||
"User": "web"
|
||||
}
|
||||
}
|
||||
}`)
|
||||
|
||||
bundle, err := LoadFile(reader)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal("0.1", bundle.Version))
|
||||
assert.Check(t, is.Len(bundle.Services, 2))
|
||||
}
|
||||
|
||||
func TestLoadFileSyntaxError(t *testing.T) {
|
||||
reader := strings.NewReader(`{
|
||||
"Version": "0.1",
|
||||
"Services": unquoted string
|
||||
}`)
|
||||
|
||||
_, err := LoadFile(reader)
|
||||
assert.Error(t, err, "JSON syntax error at byte 37: invalid character 'u' looking for beginning of value")
|
||||
}
|
||||
|
||||
func TestLoadFileTypeError(t *testing.T) {
|
||||
reader := strings.NewReader(`{
|
||||
"Version": "0.1",
|
||||
"Services": {
|
||||
"web": {
|
||||
"Image": "redis",
|
||||
"Networks": "none"
|
||||
}
|
||||
}
|
||||
}`)
|
||||
|
||||
_, err := LoadFile(reader)
|
||||
assert.Error(t, err, "Unexpected type at byte 94. Expected []string but received string.")
|
||||
}
|
||||
|
||||
func TestPrint(t *testing.T) {
|
||||
var buffer bytes.Buffer
|
||||
bundle := &Bundlefile{
|
||||
Version: "0.1",
|
||||
Services: map[string]Service{
|
||||
"web": {
|
||||
Image: "image",
|
||||
Command: []string{"echo", "something"},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.Check(t, Print(&buffer, bundle))
|
||||
output := buffer.String()
|
||||
assert.Check(t, is.Contains(output, "\"Image\": \"image\""))
|
||||
assert.Check(t, is.Contains(output,
|
||||
`"Command": [
|
||||
"echo",
|
||||
"something"
|
||||
]`))
|
||||
}
|
|
@ -90,7 +90,6 @@ func AddCommands(cmd *cobra.Command, dockerCli command.Cli) {
|
|||
context.NewContextCommand(dockerCli),
|
||||
|
||||
// legacy commands may be hidden
|
||||
hide(stack.NewTopLevelDeployCommand(dockerCli)),
|
||||
hide(system.NewEventsCommand(dockerCli)),
|
||||
hide(system.NewInfoCommand(dockerCli)),
|
||||
hide(system.NewInspectCommand(dockerCli)),
|
||||
|
|
|
@ -73,18 +73,6 @@ func NewStackCommand(dockerCli command.Cli) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
// NewTopLevelDeployCommand returns a command for `docker deploy`
|
||||
func NewTopLevelDeployCommand(dockerCli command.Cli) *cobra.Command {
|
||||
cmd := newDeployCommand(dockerCli, nil)
|
||||
// Remove the aliases at the top level
|
||||
cmd.Aliases = []string{}
|
||||
cmd.Annotations = map[string]string{
|
||||
"experimental": "",
|
||||
"version": "1.25",
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func getOrchestrator(dockerCli command.Cli, cmd *cobra.Command) (command.Orchestrator, error) {
|
||||
var orchestratorFlag string
|
||||
if o, err := cmd.Flags().GetString("orchestrator"); err == nil {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package stack
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/stack/kubernetes"
|
||||
|
@ -10,7 +8,6 @@ import (
|
|||
"github.com/docker/cli/cli/command/stack/options"
|
||||
"github.com/docker/cli/cli/command/stack/swarm"
|
||||
composetypes "github.com/docker/cli/cli/compose/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
@ -28,24 +25,6 @@ func newDeployCommand(dockerCli command.Cli, common *commonOptions) *cobra.Comma
|
|||
if err := validateStackName(opts.Namespace); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
commonOrchestrator := command.OrchestratorSwarm // default for top-level deploy command
|
||||
if common != nil {
|
||||
commonOrchestrator = common.orchestrator
|
||||
}
|
||||
|
||||
switch {
|
||||
case opts.Bundlefile == "" && len(opts.Composefiles) == 0:
|
||||
return errors.Errorf("Please specify either a bundle file (with --bundle-file) or a Compose file (with --compose-file).")
|
||||
case opts.Bundlefile != "" && len(opts.Composefiles) != 0:
|
||||
return errors.Errorf("You cannot specify both a bundle file and a Compose file.")
|
||||
case opts.Bundlefile != "":
|
||||
if commonOrchestrator != command.OrchestratorSwarm {
|
||||
return errors.Errorf("bundle files are not supported on another orchestrator than swarm.")
|
||||
}
|
||||
return swarm.DeployBundle(context.Background(), dockerCli, opts)
|
||||
}
|
||||
|
||||
config, err := loader.LoadComposefile(dockerCli, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -55,9 +34,6 @@ func newDeployCommand(dockerCli command.Cli, common *commonOptions) *cobra.Comma
|
|||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
flags.StringVar(&opts.Bundlefile, "bundle-file", "", "Path to a Distributed Application Bundle file")
|
||||
flags.SetAnnotation("bundle-file", "experimental", nil)
|
||||
flags.SetAnnotation("bundle-file", "swarm", nil)
|
||||
flags.StringSliceVarP(&opts.Composefiles, "compose-file", "c", []string{}, `Path to a Compose file, or "-" to read from stdin`)
|
||||
flags.SetAnnotation("compose-file", "version", []string{"1.25"})
|
||||
flags.BoolVar(&opts.SendRegistryAuth, "with-registry-auth", false, "Send registry authentication details to Swarm agents")
|
||||
|
|
|
@ -72,7 +72,7 @@ func getConfigDetails(composefiles []string, stdin io.Reader) (composetypes.Conf
|
|||
var details composetypes.ConfigDetails
|
||||
|
||||
if len(composefiles) == 0 {
|
||||
return details, errors.New("no composefile(s)")
|
||||
return details, errors.New("Please specify a Compose file (with --compose-file)")
|
||||
}
|
||||
|
||||
if composefiles[0] == "-" && len(composefiles) == 1 {
|
||||
|
|
|
@ -4,7 +4,6 @@ import "github.com/docker/cli/opts"
|
|||
|
||||
// Deploy holds docker stack deploy options
|
||||
type Deploy struct {
|
||||
Bundlefile string
|
||||
Composefiles []string
|
||||
Namespace string
|
||||
ResolveImage string
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
package swarm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/bundlefile"
|
||||
"github.com/docker/cli/cli/command/stack/options"
|
||||
"github.com/docker/cli/cli/compose/convert"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// DeployBundle deploy a bundlefile (dab) on a swarm.
|
||||
func DeployBundle(ctx context.Context, dockerCli command.Cli, opts options.Deploy) error {
|
||||
bundle, err := loadBundlefile(dockerCli.Err(), opts.Namespace, opts.Bundlefile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkDaemonIsSwarmManager(ctx, dockerCli); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
namespace := convert.NewNamespace(opts.Namespace)
|
||||
|
||||
if opts.Prune {
|
||||
services := map[string]struct{}{}
|
||||
for service := range bundle.Services {
|
||||
services[service] = struct{}{}
|
||||
}
|
||||
pruneServices(ctx, dockerCli, namespace, services)
|
||||
}
|
||||
|
||||
networks := make(map[string]types.NetworkCreate)
|
||||
for _, service := range bundle.Services {
|
||||
for _, networkName := range service.Networks {
|
||||
networks[namespace.Scope(networkName)] = types.NetworkCreate{
|
||||
Labels: convert.AddStackLabel(namespace, nil),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
services := make(map[string]swarm.ServiceSpec)
|
||||
for internalName, service := range bundle.Services {
|
||||
name := namespace.Scope(internalName)
|
||||
|
||||
var ports []swarm.PortConfig
|
||||
for _, portSpec := range service.Ports {
|
||||
ports = append(ports, swarm.PortConfig{
|
||||
Protocol: swarm.PortConfigProtocol(portSpec.Protocol),
|
||||
TargetPort: portSpec.Port,
|
||||
})
|
||||
}
|
||||
|
||||
nets := []swarm.NetworkAttachmentConfig{}
|
||||
for _, networkName := range service.Networks {
|
||||
nets = append(nets, swarm.NetworkAttachmentConfig{
|
||||
Target: namespace.Scope(networkName),
|
||||
Aliases: []string{internalName},
|
||||
})
|
||||
}
|
||||
|
||||
serviceSpec := swarm.ServiceSpec{
|
||||
Annotations: swarm.Annotations{
|
||||
Name: name,
|
||||
Labels: convert.AddStackLabel(namespace, service.Labels),
|
||||
},
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: &swarm.ContainerSpec{
|
||||
Image: service.Image,
|
||||
Command: service.Command,
|
||||
Args: service.Args,
|
||||
Env: service.Env,
|
||||
// Service Labels will not be copied to Containers
|
||||
// automatically during the deployment so we apply
|
||||
// it here.
|
||||
Labels: convert.AddStackLabel(namespace, nil),
|
||||
},
|
||||
},
|
||||
EndpointSpec: &swarm.EndpointSpec{
|
||||
Ports: ports,
|
||||
},
|
||||
Networks: nets,
|
||||
}
|
||||
|
||||
services[internalName] = serviceSpec
|
||||
}
|
||||
|
||||
if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil {
|
||||
return err
|
||||
}
|
||||
return deployServices(ctx, dockerCli, services, namespace, opts.SendRegistryAuth, opts.ResolveImage)
|
||||
}
|
||||
|
||||
func loadBundlefile(stderr io.Writer, namespace string, path string) (*bundlefile.Bundlefile, error) {
|
||||
defaultPath := fmt.Sprintf("%s.dab", namespace)
|
||||
|
||||
if path == "" {
|
||||
path = defaultPath
|
||||
}
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return nil, errors.Errorf(
|
||||
"Bundle %s not found. Specify the path with --file",
|
||||
path)
|
||||
}
|
||||
|
||||
fmt.Fprintf(stderr, "Loading bundle from %s\n", path)
|
||||
reader, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
bundle, err := bundlefile.LoadFile(reader)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("Error reading %s: %v\n", path, err)
|
||||
}
|
||||
return bundle, err
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package swarm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
is "gotest.tools/assert/cmp"
|
||||
)
|
||||
|
||||
func TestLoadBundlefileErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
namespace string
|
||||
path string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
namespace: "namespace_foo",
|
||||
expectedError: "Bundle namespace_foo.dab not found",
|
||||
},
|
||||
{
|
||||
namespace: "namespace_foo",
|
||||
path: "invalid_path",
|
||||
expectedError: "Bundle invalid_path not found",
|
||||
},
|
||||
// FIXME: this test never working, testdata file is missing from repo
|
||||
//{
|
||||
// namespace: "namespace_foo",
|
||||
// path: string(golden.Get(t, "bundlefile_with_invalid_syntax")),
|
||||
// expectedError: "Error reading",
|
||||
//},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
_, err := loadBundlefile(&bytes.Buffer{}, tc.namespace, tc.path)
|
||||
assert.ErrorContains(t, err, tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadBundlefile(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
namespace := ""
|
||||
path := filepath.Join("testdata", "bundlefile_with_two_services.dab")
|
||||
bundleFile, err := loadBundlefile(buf, namespace, path)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(len(bundleFile.Services), 2))
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"Services": {
|
||||
"visualizer": {
|
||||
"Image": "busybox@sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f",
|
||||
"Networks": [
|
||||
"webnet"
|
||||
],
|
||||
"Ports": [
|
||||
{
|
||||
"Port": 8080,
|
||||
"Protocol": "tcp"
|
||||
}
|
||||
]
|
||||
},
|
||||
"web": {
|
||||
"Image": "busybox@sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f",
|
||||
"Networks": [
|
||||
"webnet"
|
||||
],
|
||||
"Ports": [
|
||||
{
|
||||
"Port": 80,
|
||||
"Protocol": "tcp"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Version": "0.1"
|
||||
}
|
|
@ -2695,10 +2695,6 @@ _docker_daemon() {
|
|||
esac
|
||||
}
|
||||
|
||||
_docker_deploy() {
|
||||
__docker_server_is_experimental && _docker_stack_deploy
|
||||
}
|
||||
|
||||
_docker_diff() {
|
||||
_docker_container_diff
|
||||
}
|
||||
|
@ -4878,10 +4874,6 @@ _docker_stack_deploy() {
|
|||
__docker_complete_stack_orchestrator_options && return
|
||||
|
||||
case "$prev" in
|
||||
--bundle-file)
|
||||
_filedir dab
|
||||
return
|
||||
;;
|
||||
--compose-file|-c)
|
||||
_filedir yml
|
||||
return
|
||||
|
@ -4895,13 +4887,12 @@ _docker_stack_deploy() {
|
|||
case "$cur" in
|
||||
-*)
|
||||
local options="--compose-file -c --help --orchestrator"
|
||||
__docker_server_is_experimental && __docker_stack_orchestrator_is swarm && options+=" --bundle-file"
|
||||
__docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig --namespace"
|
||||
__docker_stack_orchestrator_is swarm && options+=" --prune --resolve-image --with-registry-auth"
|
||||
COMPREPLY=( $( compgen -W "$options" -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
local counter=$(__docker_pos_first_nonflag '--bundle-file|--compose-file|-c|--kubeconfig|--namespace|--orchestrator|--resolve-image')
|
||||
local counter=$(__docker_pos_first_nonflag '--compose-file|-c|--kubeconfig|--namespace|--orchestrator|--resolve-image')
|
||||
if [ "$cword" -eq "$counter" ]; then
|
||||
__docker_complete_stacks
|
||||
fi
|
||||
|
@ -5531,7 +5522,6 @@ _docker() {
|
|||
|
||||
local experimental_server_commands=(
|
||||
checkpoint
|
||||
deploy
|
||||
)
|
||||
|
||||
local commands=(${management_commands[*]} ${top_level_commands[*]})
|
||||
|
|
|
@ -2216,7 +2216,6 @@ __docker_stack_subcommand() {
|
|||
(deploy|up)
|
||||
_arguments $(__docker_arguments) \
|
||||
$opts_help \
|
||||
"($help)--bundle-file=[Path to a Distributed Application Bundle file]:dab:_files -g \"*.dab\"" \
|
||||
"($help -c --compose-file)"{-c=,--compose-file=}"[Path to a Compose file, or '-' to read from stdin]:compose file:_files -g \"*.(yml|yaml)\"" \
|
||||
"($help)--with-registry-auth[Send registry authentication details to Swarm agents]" \
|
||||
"($help -):stack:__docker_complete_stacks" && ret=0
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
---
|
||||
title: "deploy"
|
||||
description: "The deploy command description and usage"
|
||||
keywords: "stack, deploy"
|
||||
advisory: "experimental"
|
||||
---
|
||||
|
||||
<!-- This file is maintained within the docker/cli GitHub
|
||||
repository at https://github.com/docker/cli/. Make all
|
||||
pull requests against that repo. If you see this file in
|
||||
another repository, consider it read-only there, as it will
|
||||
periodically be overwritten by the definitive file. Pull
|
||||
requests which include edits to this file in other repositories
|
||||
will be rejected.
|
||||
-->
|
||||
|
||||
# deploy (experimental)
|
||||
|
||||
An alias for `stack deploy`.
|
||||
|
||||
```markdown
|
||||
Usage: docker deploy [OPTIONS] STACK
|
||||
|
||||
Deploy a new stack or update an existing stack
|
||||
|
||||
Aliases:
|
||||
deploy, up
|
||||
|
||||
Options:
|
||||
--bundle-file string Path to a Distributed Application Bundle file
|
||||
--compose-file string Path to a Compose file, or "-" to read from stdin
|
||||
--help Print usage
|
||||
--prune Prune services that are no longer referenced
|
||||
--with-registry-auth Send registry authentication details to Swarm agents
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
Create and update a stack from a `compose` or a `dab` file on the swarm. This command
|
||||
has to be run targeting a manager node.
|
||||
|
||||
## Examples
|
||||
|
||||
### Compose file
|
||||
|
||||
The `deploy` command supports compose file version `3.0` and above.
|
||||
|
||||
```bash
|
||||
$ docker stack deploy --compose-file docker-compose.yml vossibility
|
||||
|
||||
Ignoring unsupported options: links
|
||||
|
||||
Creating network vossibility_vossibility
|
||||
Creating network vossibility_default
|
||||
Creating service vossibility_nsqd
|
||||
Creating service vossibility_logstash
|
||||
Creating service vossibility_elasticsearch
|
||||
Creating service vossibility_kibana
|
||||
Creating service vossibility_ghollector
|
||||
Creating service vossibility_lookupd
|
||||
```
|
||||
|
||||
You can verify that the services were correctly created
|
||||
|
||||
```bash
|
||||
$ docker service ls
|
||||
|
||||
ID NAME MODE REPLICAS IMAGE
|
||||
29bv0vnlm903 vossibility_lookupd replicated 1/1 nsqio/nsq@sha256:eeba05599f31eba418e96e71e0984c3dc96963ceb66924dd37a47bf7ce18a662
|
||||
4awt47624qwh vossibility_nsqd replicated 1/1 nsqio/nsq@sha256:eeba05599f31eba418e96e71e0984c3dc96963ceb66924dd37a47bf7ce18a662
|
||||
4tjx9biia6fs vossibility_elasticsearch replicated 1/1 elasticsearch@sha256:12ac7c6af55d001f71800b83ba91a04f716e58d82e748fa6e5a7359eed2301aa
|
||||
7563uuzr9eys vossibility_kibana replicated 1/1 kibana@sha256:6995a2d25709a62694a937b8a529ff36da92ebee74bafd7bf00e6caf6db2eb03
|
||||
9gc5m4met4he vossibility_logstash replicated 1/1 logstash@sha256:2dc8bddd1bb4a5a34e8ebaf73749f6413c101b2edef6617f2f7713926d2141fe
|
||||
axqh55ipl40h vossibility_vossibility-collector replicated 1/1 icecrime/vossibility-collector@sha256:f03f2977203ba6253988c18d04061c5ec7aab46bca9dfd89a9a1fa4500989fba
|
||||
```
|
||||
|
||||
### DAB file
|
||||
|
||||
```bash
|
||||
$ docker stack deploy --bundle-file vossibility-stack.dab vossibility
|
||||
|
||||
Loading bundle from vossibility-stack.dab
|
||||
Creating service vossibility_elasticsearch
|
||||
Creating service vossibility_kibana
|
||||
Creating service vossibility_logstash
|
||||
Creating service vossibility_lookupd
|
||||
Creating service vossibility_nsqd
|
||||
Creating service vossibility_vossibility-collector
|
||||
```
|
||||
|
||||
You can verify that the services were correctly created:
|
||||
|
||||
```bash
|
||||
$ docker service ls
|
||||
|
||||
ID NAME MODE REPLICAS IMAGE
|
||||
29bv0vnlm903 vossibility_lookupd replicated 1/1 nsqio/nsq@sha256:eeba05599f31eba418e96e71e0984c3dc96963ceb66924dd37a47bf7ce18a662
|
||||
4awt47624qwh vossibility_nsqd replicated 1/1 nsqio/nsq@sha256:eeba05599f31eba418e96e71e0984c3dc96963ceb66924dd37a47bf7ce18a662
|
||||
4tjx9biia6fs vossibility_elasticsearch replicated 1/1 elasticsearch@sha256:12ac7c6af55d001f71800b83ba91a04f716e58d82e748fa6e5a7359eed2301aa
|
||||
7563uuzr9eys vossibility_kibana replicated 1/1 kibana@sha256:6995a2d25709a62694a937b8a529ff36da92ebee74bafd7bf00e6caf6db2eb03
|
||||
9gc5m4met4he vossibility_logstash replicated 1/1 logstash@sha256:2dc8bddd1bb4a5a34e8ebaf73749f6413c101b2edef6617f2f7713926d2141fe
|
||||
axqh55ipl40h vossibility_vossibility-collector replicated 1/1 icecrime/vossibility-collector@sha256:f03f2977203ba6253988c18d04061c5ec7aab46bca9dfd89a9a1fa4500989fba
|
||||
```
|
||||
|
||||
## Related commands
|
||||
|
||||
* [stack deploy](stack_deploy.md)
|
||||
* [stack ls](stack_ls.md)
|
||||
* [stack ps](stack_ps.md)
|
||||
* [stack rm](stack_rm.md)
|
||||
* [stack services](stack_services.md)
|
|
@ -24,7 +24,6 @@ Aliases:
|
|||
deploy, up
|
||||
|
||||
Options:
|
||||
--bundle-file string Path to a Distributed Application Bundle file
|
||||
-c, --compose-file strings Path to a Compose file, or "-" to read from stdin
|
||||
--help Print usage
|
||||
--kubeconfig string Kubernetes config file
|
||||
|
@ -38,8 +37,8 @@ Options:
|
|||
|
||||
## Description
|
||||
|
||||
Create and update a stack from a `compose` or a `dab` file on the swarm. This command
|
||||
has to be run targeting a manager node.
|
||||
Create and update a stack from a `compose` file on the swarm. This command has to
|
||||
be run targeting a manager node.
|
||||
|
||||
## Examples
|
||||
|
||||
|
@ -112,34 +111,6 @@ ID NAME MODE REPLICAS IMAGE
|
|||
axqh55ipl40h vossibility_vossibility-collector replicated 1/1 icecrime/vossibility-collector@sha256:f03f2977203ba6253988c18d04061c5ec7aab46bca9dfd89a9a1fa4500989fba
|
||||
```
|
||||
|
||||
### DAB file
|
||||
|
||||
```bash
|
||||
$ docker stack deploy --bundle-file vossibility-stack.dab vossibility
|
||||
|
||||
Loading bundle from vossibility-stack.dab
|
||||
Creating service vossibility_elasticsearch
|
||||
Creating service vossibility_kibana
|
||||
Creating service vossibility_logstash
|
||||
Creating service vossibility_lookupd
|
||||
Creating service vossibility_nsqd
|
||||
Creating service vossibility_vossibility-collector
|
||||
```
|
||||
|
||||
You can verify that the services were correctly created:
|
||||
|
||||
```bash
|
||||
$ docker service ls
|
||||
|
||||
ID NAME MODE REPLICAS IMAGE
|
||||
29bv0vnlm903 vossibility_lookupd replicated 1/1 nsqio/nsq@sha256:eeba05599f31eba418e96e71e0984c3dc96963ceb66924dd37a47bf7ce18a662
|
||||
4awt47624qwh vossibility_nsqd replicated 1/1 nsqio/nsq@sha256:eeba05599f31eba418e96e71e0984c3dc96963ceb66924dd37a47bf7ce18a662
|
||||
4tjx9biia6fs vossibility_elasticsearch replicated 1/1 elasticsearch@sha256:12ac7c6af55d001f71800b83ba91a04f716e58d82e748fa6e5a7359eed2301aa
|
||||
7563uuzr9eys vossibility_kibana replicated 1/1 kibana@sha256:6995a2d25709a62694a937b8a529ff36da92ebee74bafd7bf00e6caf6db2eb03
|
||||
9gc5m4met4he vossibility_logstash replicated 1/1 logstash@sha256:2dc8bddd1bb4a5a34e8ebaf73749f6413c101b2edef6617f2f7713926d2141fe
|
||||
axqh55ipl40h vossibility_vossibility-collector replicated 1/1 icecrime/vossibility-collector@sha256:f03f2977203ba6253988c18d04061c5ec7aab46bca9dfd89a9a1fa4500989fba
|
||||
```
|
||||
|
||||
## Related commands
|
||||
|
||||
* [stack ls](stack_ls.md)
|
||||
|
|
|
@ -7,7 +7,6 @@ Aliases:
|
|||
deploy, up
|
||||
|
||||
Options:
|
||||
--bundle-file string Path to a Distributed Application Bundle file
|
||||
-c, --compose-file strings Path to a Compose file, or "-" to read
|
||||
from stdin
|
||||
--orchestrator string Orchestrator to use (swarm|kubernetes|all)
|
||||
|
|
|
@ -38,11 +38,8 @@ Option to squash image layers to the base image after successful builds.
|
|||
Checkpoint and restore support for Containers.
|
||||
Metrics (Prometheus) output for basic container, image, and daemon operations.
|
||||
|
||||
* The top-level [docker deploy](../docs/reference/commandline/deploy.md) command. The
|
||||
`docker stack deploy` command is **not** experimental.
|
||||
* [External graphdriver plugins](../docs/extend/plugins_graphdriver.md)
|
||||
* [Ipvlan Network Drivers](vlan-networks.md)
|
||||
* [Distributed Application Bundles](docker-stacks-and-bundles.md)
|
||||
* [Checkpoint & Restore](checkpoint-restore.md)
|
||||
* [Docker build with --squash argument](../docs/reference/commandline/build.md#squash-an-images-layers---squash-experimental-only)
|
||||
|
||||
|
|
|
@ -1,202 +0,0 @@
|
|||
# Docker Stacks and Distributed Application Bundles
|
||||
|
||||
## Overview
|
||||
|
||||
Docker Stacks and Distributed Application Bundles are experimental features
|
||||
introduced in Docker 1.12 and Docker Compose 1.8, alongside the concept of
|
||||
swarm mode, and Nodes and Services in the Engine API.
|
||||
|
||||
A Dockerfile can be built into an image, and containers can be created from
|
||||
that image. Similarly, a docker-compose.yml can be built into a **distributed
|
||||
application bundle**, and **stacks** can be created from that bundle. In that
|
||||
sense, the bundle is a multi-services distributable image format.
|
||||
|
||||
As of Docker 1.12 and Compose 1.8, the features are experimental. Neither
|
||||
Docker Engine nor the Docker Registry supports distribution of bundles.
|
||||
|
||||
## Producing a bundle
|
||||
|
||||
The easiest way to produce a bundle is to generate it using `docker-compose`
|
||||
from an existing `docker-compose.yml`. Of course, that's just *one* possible way
|
||||
to proceed, in the same way that `docker build` isn't the only way to produce a
|
||||
Docker image.
|
||||
|
||||
From `docker-compose`:
|
||||
|
||||
```bash
|
||||
$ docker-compose bundle
|
||||
WARNING: Unsupported key 'network_mode' in services.nsqd - ignoring
|
||||
WARNING: Unsupported key 'links' in services.nsqd - ignoring
|
||||
WARNING: Unsupported key 'volumes' in services.nsqd - ignoring
|
||||
[...]
|
||||
Wrote bundle to vossibility-stack.dab
|
||||
```
|
||||
|
||||
## Creating a stack from a bundle
|
||||
|
||||
A stack is created using the `docker deploy` command:
|
||||
|
||||
```bash
|
||||
$ docker deploy --help
|
||||
Usage: docker deploy [OPTIONS] STACK
|
||||
|
||||
Deploy a new stack or update an existing stack
|
||||
|
||||
Aliases:
|
||||
deploy, up
|
||||
|
||||
Options:
|
||||
--bundle-file string Path to a Distributed Application Bundle file
|
||||
-c, --compose-file string Path to a Compose file
|
||||
--help Print usage
|
||||
--with-registry-auth Send registry authentication details to Swarm agents
|
||||
|
||||
```
|
||||
|
||||
Let's deploy the stack created before:
|
||||
|
||||
```bash
|
||||
$ docker deploy --bundle-file vossibility-stack.dab vossibility-stack
|
||||
Loading bundle from vossibility-stack.dab
|
||||
Creating service vossibility-stack_elasticsearch
|
||||
Creating service vossibility-stack_kibana
|
||||
Creating service vossibility-stack_logstash
|
||||
Creating service vossibility-stack_lookupd
|
||||
Creating service vossibility-stack_nsqd
|
||||
Creating service vossibility-stack_vossibility-collector
|
||||
```
|
||||
|
||||
We can verify that services were correctly created:
|
||||
|
||||
```bash
|
||||
$ docker service ls
|
||||
ID NAME MODE REPLICAS IMAGE
|
||||
29bv0vnlm903 vossibility-stack_lookupd replicated 1/1 nsqio/nsq@sha256:eeba05599f31eba418e96e71e0984c3dc96963ceb66924dd37a47bf7ce18a662
|
||||
4awt47624qwh vossibility-stack_nsqd replicated 1/1 nsqio/nsq@sha256:eeba05599f31eba418e96e71e0984c3dc96963ceb66924dd37a47bf7ce18a662
|
||||
4tjx9biia6fs vossibility-stack_elasticsearch replicated 1/1 elasticsearch@sha256:12ac7c6af55d001f71800b83ba91a04f716e58d82e748fa6e5a7359eed2301aa
|
||||
7563uuzr9eys vossibility-stack_kibana replicated 1/1 kibana@sha256:6995a2d25709a62694a937b8a529ff36da92ebee74bafd7bf00e6caf6db2eb03
|
||||
9gc5m4met4he vossibility-stack_logstash replicated 1/1 logstash@sha256:2dc8bddd1bb4a5a34e8ebaf73749f6413c101b2edef6617f2f7713926d2141fe
|
||||
axqh55ipl40h vossibility-stack_vossibility-collector replicated 1/1 icecrime/vossibility-collector@sha256:f03f2977203ba6253988c18d04061c5ec7aab46bca9dfd89a9a1fa4500989fba
|
||||
```
|
||||
|
||||
## Managing stacks
|
||||
|
||||
Stacks are managed using the `docker stack` command:
|
||||
|
||||
```bash
|
||||
# docker stack --help
|
||||
|
||||
Usage: docker stack COMMAND
|
||||
|
||||
Manage Docker stacks
|
||||
|
||||
Options:
|
||||
--help Print usage
|
||||
|
||||
Commands:
|
||||
deploy Deploy a new stack or update an existing stack
|
||||
ls List stacks
|
||||
ps List the tasks in the stack
|
||||
rm Remove the stack
|
||||
services List the services in the stack
|
||||
|
||||
Run 'docker stack COMMAND --help' for more information on a command.
|
||||
```
|
||||
|
||||
## Bundle file format
|
||||
|
||||
Distributed application bundles are described in a JSON format. When bundles
|
||||
are persisted as files, the file extension is `.dab` (Docker 1.12RC2 tools use
|
||||
`.dsb` for the file extension—this will be updated in the next release client).
|
||||
|
||||
A bundle has two top-level fields: `version` and `services`. The version used
|
||||
by Docker 1.12 and later tools is `0.1`.
|
||||
|
||||
`services` in the bundle are the services that comprise the app. They
|
||||
correspond to the new `Service` object introduced in the 1.12 Docker Engine API.
|
||||
|
||||
A service has the following fields:
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Image (required) <code>string</code>
|
||||
</dt>
|
||||
<dd>
|
||||
The image that the service will run. Docker images should be referenced
|
||||
with full content hash to fully specify the deployment artifact for the
|
||||
service. Example:
|
||||
<code>postgres@sha256:f76245b04ddbcebab5bb6c28e76947f49222c99fec4aadb0bb
|
||||
1c24821a 9e83ef</code>
|
||||
</dd>
|
||||
<dt>
|
||||
Command <code>[]string</code>
|
||||
</dt>
|
||||
<dd>
|
||||
Command to run in service containers.
|
||||
</dd>
|
||||
<dt>
|
||||
Args <code>[]string</code>
|
||||
</dt>
|
||||
<dd>
|
||||
Arguments passed to the service containers.
|
||||
</dd>
|
||||
<dt>
|
||||
Env <code>[]string</code>
|
||||
</dt>
|
||||
<dd>
|
||||
Environment variables.
|
||||
</dd>
|
||||
<dt>
|
||||
Labels <code>map[string]string</code>
|
||||
</dt>
|
||||
<dd>
|
||||
Labels used for setting meta data on services.
|
||||
</dd>
|
||||
<dt>
|
||||
Ports <code>[]Port</code>
|
||||
</dt>
|
||||
<dd>
|
||||
Service ports (composed of <code>Port</code> (<code>int</code>) and
|
||||
<code>Protocol</code> (<code>string</code>). A service description can
|
||||
only specify the container port to be exposed. These ports can be
|
||||
mapped on runtime hosts at the operator's discretion.
|
||||
</dd>
|
||||
<dt>
|
||||
WorkingDir <code>string</code>
|
||||
</dt>
|
||||
<dd>
|
||||
Working directory inside the service containers.
|
||||
</dd>
|
||||
<dt>
|
||||
User <code>string</code>
|
||||
</dt>
|
||||
<dd>
|
||||
Username or UID (format: <code><name|uid>[:<group|gid>]</code>).
|
||||
</dd>
|
||||
<dt>
|
||||
Networks <code>[]string</code>
|
||||
</dt>
|
||||
<dd>
|
||||
Networks that the service containers should be connected to. An entity
|
||||
deploying a bundle should create networks as needed.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
The following is an example of bundlefile with two services:
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "0.1",
|
||||
"Services": {
|
||||
"redis": {
|
||||
"Image": "redis@sha256:4b24131101fa0117bcaa18ac37055fffd9176aa1a240392bb8ea85e0be50f2ce",
|
||||
"Networks": ["default"]
|
||||
},
|
||||
"web": {
|
||||
"Image": "dockercloud/hello-world@sha256:fe79a2cfbd17eefc344fb8419420808df95a1e22d93b7f621a7399fd1e9dca1d",
|
||||
"Networks": ["default"],
|
||||
"User": "web"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
Loading…
Reference in New Issue