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),
|
context.NewContextCommand(dockerCli),
|
||||||
|
|
||||||
// legacy commands may be hidden
|
// legacy commands may be hidden
|
||||||
hide(stack.NewTopLevelDeployCommand(dockerCli)),
|
|
||||||
hide(system.NewEventsCommand(dockerCli)),
|
hide(system.NewEventsCommand(dockerCli)),
|
||||||
hide(system.NewInfoCommand(dockerCli)),
|
hide(system.NewInfoCommand(dockerCli)),
|
||||||
hide(system.NewInspectCommand(dockerCli)),
|
hide(system.NewInspectCommand(dockerCli)),
|
||||||
|
@ -73,18 +73,6 @@ func NewStackCommand(dockerCli command.Cli) *cobra.Command {
|
|||||||
return cmd
|
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) {
|
func getOrchestrator(dockerCli command.Cli, cmd *cobra.Command) (command.Orchestrator, error) {
|
||||||
var orchestratorFlag string
|
var orchestratorFlag string
|
||||||
if o, err := cmd.Flags().GetString("orchestrator"); err == nil {
|
if o, err := cmd.Flags().GetString("orchestrator"); err == nil {
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package stack
|
package stack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/cli/command/stack/kubernetes"
|
"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/options"
|
||||||
"github.com/docker/cli/cli/command/stack/swarm"
|
"github.com/docker/cli/cli/command/stack/swarm"
|
||||||
composetypes "github.com/docker/cli/cli/compose/types"
|
composetypes "github.com/docker/cli/cli/compose/types"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
@ -28,24 +25,6 @@ func newDeployCommand(dockerCli command.Cli, common *commonOptions) *cobra.Comma
|
|||||||
if err := validateStackName(opts.Namespace); err != nil {
|
if err := validateStackName(opts.Namespace); err != nil {
|
||||||
return err
|
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)
|
config, err := loader.LoadComposefile(dockerCli, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -55,9 +34,6 @@ func newDeployCommand(dockerCli command.Cli, common *commonOptions) *cobra.Comma
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags := cmd.Flags()
|
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.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.SetAnnotation("compose-file", "version", []string{"1.25"})
|
||||||
flags.BoolVar(&opts.SendRegistryAuth, "with-registry-auth", false, "Send registry authentication details to Swarm agents")
|
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
|
var details composetypes.ConfigDetails
|
||||||
|
|
||||||
if len(composefiles) == 0 {
|
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 {
|
if composefiles[0] == "-" && len(composefiles) == 1 {
|
||||||
|
@ -4,7 +4,6 @@ import "github.com/docker/cli/opts"
|
|||||||
|
|
||||||
// Deploy holds docker stack deploy options
|
// Deploy holds docker stack deploy options
|
||||||
type Deploy struct {
|
type Deploy struct {
|
||||||
Bundlefile string
|
|
||||||
Composefiles []string
|
Composefiles []string
|
||||||
Namespace string
|
Namespace string
|
||||||
ResolveImage 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
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
_docker_deploy() {
|
|
||||||
__docker_server_is_experimental && _docker_stack_deploy
|
|
||||||
}
|
|
||||||
|
|
||||||
_docker_diff() {
|
_docker_diff() {
|
||||||
_docker_container_diff
|
_docker_container_diff
|
||||||
}
|
}
|
||||||
@ -4878,10 +4874,6 @@ _docker_stack_deploy() {
|
|||||||
__docker_complete_stack_orchestrator_options && return
|
__docker_complete_stack_orchestrator_options && return
|
||||||
|
|
||||||
case "$prev" in
|
case "$prev" in
|
||||||
--bundle-file)
|
|
||||||
_filedir dab
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
--compose-file|-c)
|
--compose-file|-c)
|
||||||
_filedir yml
|
_filedir yml
|
||||||
return
|
return
|
||||||
@ -4895,13 +4887,12 @@ _docker_stack_deploy() {
|
|||||||
case "$cur" in
|
case "$cur" in
|
||||||
-*)
|
-*)
|
||||||
local options="--compose-file -c --help --orchestrator"
|
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 kubernetes && options+=" --kubeconfig --namespace"
|
||||||
__docker_stack_orchestrator_is swarm && options+=" --prune --resolve-image --with-registry-auth"
|
__docker_stack_orchestrator_is swarm && options+=" --prune --resolve-image --with-registry-auth"
|
||||||
COMPREPLY=( $( compgen -W "$options" -- "$cur" ) )
|
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
|
if [ "$cword" -eq "$counter" ]; then
|
||||||
__docker_complete_stacks
|
__docker_complete_stacks
|
||||||
fi
|
fi
|
||||||
@ -5531,7 +5522,6 @@ _docker() {
|
|||||||
|
|
||||||
local experimental_server_commands=(
|
local experimental_server_commands=(
|
||||||
checkpoint
|
checkpoint
|
||||||
deploy
|
|
||||||
)
|
)
|
||||||
|
|
||||||
local commands=(${management_commands[*]} ${top_level_commands[*]})
|
local commands=(${management_commands[*]} ${top_level_commands[*]})
|
||||||
|
@ -2216,7 +2216,6 @@ __docker_stack_subcommand() {
|
|||||||
(deploy|up)
|
(deploy|up)
|
||||||
_arguments $(__docker_arguments) \
|
_arguments $(__docker_arguments) \
|
||||||
$opts_help \
|
$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 -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)--with-registry-auth[Send registry authentication details to Swarm agents]" \
|
||||||
"($help -):stack:__docker_complete_stacks" && ret=0
|
"($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
|
deploy, up
|
||||||
|
|
||||||
Options:
|
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
|
-c, --compose-file strings Path to a Compose file, or "-" to read from stdin
|
||||||
--help Print usage
|
--help Print usage
|
||||||
--kubeconfig string Kubernetes config file
|
--kubeconfig string Kubernetes config file
|
||||||
@ -38,8 +37,8 @@ Options:
|
|||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
Create and update a stack from a `compose` or a `dab` file on the swarm. This command
|
Create and update a stack from a `compose` file on the swarm. This command has to
|
||||||
has to be run targeting a manager node.
|
be run targeting a manager node.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
@ -112,34 +111,6 @@ ID NAME MODE REPLICAS IMAGE
|
|||||||
axqh55ipl40h vossibility_vossibility-collector replicated 1/1 icecrime/vossibility-collector@sha256:f03f2977203ba6253988c18d04061c5ec7aab46bca9dfd89a9a1fa4500989fba
|
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
|
## Related commands
|
||||||
|
|
||||||
* [stack ls](stack_ls.md)
|
* [stack ls](stack_ls.md)
|
||||||
|
@ -7,7 +7,6 @@ Aliases:
|
|||||||
deploy, up
|
deploy, up
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--bundle-file string Path to a Distributed Application Bundle file
|
|
||||||
-c, --compose-file strings Path to a Compose file, or "-" to read
|
-c, --compose-file strings Path to a Compose file, or "-" to read
|
||||||
from stdin
|
from stdin
|
||||||
--orchestrator string Orchestrator to use (swarm|kubernetes|all)
|
--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.
|
Checkpoint and restore support for Containers.
|
||||||
Metrics (Prometheus) output for basic container, image, and daemon operations.
|
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)
|
* [External graphdriver plugins](../docs/extend/plugins_graphdriver.md)
|
||||||
* [Ipvlan Network Drivers](vlan-networks.md)
|
* [Ipvlan Network Drivers](vlan-networks.md)
|
||||||
* [Distributed Application Bundles](docker-stacks-and-bundles.md)
|
|
||||||
* [Checkpoint & Restore](checkpoint-restore.md)
|
* [Checkpoint & Restore](checkpoint-restore.md)
|
||||||
* [Docker build with --squash argument](../docs/reference/commandline/build.md#squash-an-images-layers---squash-experimental-only)
|
* [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…
x
Reference in New Issue
Block a user