mirror of https://github.com/docker/cli.git
Merge pull request #2216 from thaJeztah/remove_dab_deploy
Remove experimental "deploy" from "dab" files
This commit is contained in:
commit
08eaead288
|
@ -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