Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ func RootCommand(dockerCli command.Cli, backendOptions *BackendOptions) *cobra.C
statsCommand(&opts, dockerCli),
watchCommand(&opts, dockerCli, backendOptions),
publishCommand(&opts, dockerCli, backendOptions),
deployCommand(&opts, dockerCli, backendOptions),
alphaCommand(&opts, dockerCli, backendOptions),
bridgeCommand(&opts, dockerCli),
volumesCommand(&opts, dockerCli, backendOptions),
Expand Down
113 changes: 113 additions & 0 deletions cmd/compose/deploy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
Copyright 2020 Docker Compose CLI authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package compose

import (
"context"
"fmt"
"time"

"github.com/docker/cli/cli/command"
"github.com/spf13/cobra"

"github.com/docker/compose/v5/pkg/api"
"github.com/docker/compose/v5/pkg/compose"
)

type deployOptions struct {
*ProjectOptions
composeOptions
build bool
noBuild bool
push bool
quiet bool
removeOrphans bool
wait bool
waitTimeout int
}

func deployCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *BackendOptions) *cobra.Command {
opts := deployOptions{
ProjectOptions: p,
}
cmd := &cobra.Command{
Use: "deploy [OPTIONS] [SERVICE...]",
Short: "Deploy a Compose application to a Docker server",
Long: `Deploy a Compose application to a Docker server.

This command applies the Compose project to the target Docker server,
recreating containers with updated configuration and images. Images are
pulled from the registry unless --build is specified.

Use health checks defined in the Compose file to ensure zero-downtime
deployments by passing --wait.`,
PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
if opts.waitTimeout < 0 {
return fmt.Errorf("--wait-timeout must be a non-negative integer")
}
if opts.build && opts.noBuild {
return fmt.Errorf("--build and --no-build are incompatible")
}
return nil
}),
RunE: Adapt(func(ctx context.Context, args []string) error {
return runDeploy(ctx, dockerCli, backendOptions, opts, args)
}),
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
flags := cmd.Flags()
flags.BoolVar(&opts.build, "build", false, "Build images before deploying")
flags.BoolVar(&opts.noBuild, "no-build", false, "Do not build images even if build configuration is defined")
flags.BoolVar(&opts.push, "push", false, "Push images to registry before deploying")
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Suppress pull/push progress output")
flags.BoolVar(&opts.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file")
flags.BoolVar(&opts.wait, "wait", false, "Wait for services to be healthy before returning")
flags.IntVar(&opts.waitTimeout, "wait-timeout", 0, "Maximum duration in seconds to wait for services to be healthy (0 = no timeout)")
return cmd
}

func runDeploy(ctx context.Context, dockerCli command.Cli, backendOptions *BackendOptions, opts deployOptions, services []string) error {
backend, err := compose.NewComposeService(dockerCli, backendOptions.Options...)
if err != nil {
return err
}

project, _, err := opts.ToProject(ctx, dockerCli, backend, services)
if err != nil {
return err
}

deployOpts := api.DeployOptions{
Push: opts.push,
Quiet: opts.quiet,
RemoveOrphans: opts.removeOrphans,
Wait: opts.wait,
Services: services,
}

if opts.waitTimeout > 0 {
deployOpts.WaitTimeout = time.Duration(opts.waitTimeout) * time.Second
}

if opts.build && !opts.noBuild {
deployOpts.Build = &api.BuildOptions{
Services: services,
}
}

return backend.Deploy(ctx, project, deployOpts)
}
1 change: 1 addition & 0 deletions docs/reference/compose.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Define and run multi-container applications with Docker
| [`config`](compose_config.md) | Parse, resolve and render compose file in canonical format |
| [`cp`](compose_cp.md) | Copy files/folders between a service container and the local filesystem |
| [`create`](compose_create.md) | Creates containers for a service |
| [`deploy`](compose_deploy.md) | Deploy a Compose application to a Docker server |
| [`down`](compose_down.md) | Stop and remove containers, networks |
| [`events`](compose_events.md) | Receive real time events from containers |
| [`exec`](compose_exec.md) | Execute a command in a running container |
Expand Down
28 changes: 28 additions & 0 deletions docs/reference/compose_deploy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# docker compose deploy

<!---MARKER_GEN_START-->
Deploy a Compose application to a Docker server.

This command applies the Compose project to the target Docker server,
recreating containers with updated configuration and images. Images are
pulled from the registry unless --build is specified.

Use health checks defined in the Compose file to ensure zero-downtime
deployments by passing --wait.

### Options

| Name | Type | Default | Description |
|:-------------------|:-------|:--------|:--------------------------------------------------------------------------------|
| `--build` | `bool` | | Build images before deploying |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--no-build` | `bool` | | Do not build images even if build configuration is defined |
| `--push` | `bool` | | Push images to registry before deploying |
| `-q`, `--quiet` | `bool` | | Suppress pull/push progress output |
| `--remove-orphans` | `bool` | | Remove containers for services not defined in the Compose file |
| `--wait` | `bool` | | Wait for services to be healthy before returning |
| `--wait-timeout` | `int` | `0` | Maximum duration in seconds to wait for services to be healthy (0 = no timeout) |


<!---MARKER_GEN_END-->

2 changes: 2 additions & 0 deletions docs/reference/docker_compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ cname:
- docker compose config
- docker compose cp
- docker compose create
- docker compose deploy
- docker compose down
- docker compose events
- docker compose exec
Expand Down Expand Up @@ -48,6 +49,7 @@ clink:
- docker_compose_config.yaml
- docker_compose_cp.yaml
- docker_compose_create.yaml
- docker_compose_deploy.yaml
- docker_compose_down.yaml
- docker_compose_events.yaml
- docker_compose_exec.yaml
Expand Down
105 changes: 105 additions & 0 deletions docs/reference/docker_compose_deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
command: docker compose deploy
short: Deploy a Compose application to a Docker server
long: |-
Deploy a Compose application to a Docker server.

This command applies the Compose project to the target Docker server,
recreating containers with updated configuration and images. Images are
pulled from the registry unless --build is specified.

Use health checks defined in the Compose file to ensure zero-downtime
deployments by passing --wait.
usage: docker compose deploy [OPTIONS] [SERVICE...]
pname: docker compose
plink: docker_compose.yaml
options:
- option: build
value_type: bool
default_value: "false"
description: Build images before deploying
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: no-build
value_type: bool
default_value: "false"
description: Do not build images even if build configuration is defined
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: push
value_type: bool
default_value: "false"
description: Push images to registry before deploying
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: quiet
shorthand: q
value_type: bool
default_value: "false"
description: Suppress pull/push progress output
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: remove-orphans
value_type: bool
default_value: "false"
description: Remove containers for services not defined in the Compose file
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: wait
value_type: bool
default_value: "false"
description: Wait for services to be healthy before returning
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: wait-timeout
value_type: int
default_value: "0"
description: |
Maximum duration in seconds to wait for services to be healthy (0 = no timeout)
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
inherited_options:
- option: dry-run
value_type: bool
default_value: "false"
description: Execute command in dry run mode
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false

20 changes: 20 additions & 0 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,26 @@ type Compose interface {
Volumes(ctx context.Context, project string, options VolumesOptions) ([]VolumesSummary, error)
// LoadProject loads and validates a Compose project from configuration files.
LoadProject(ctx context.Context, options ProjectLoadOptions) (*types.Project, error)
// Deploy executes the equivalent to a `compose deploy`
Deploy(ctx context.Context, project *types.Project, options DeployOptions) error
}

// DeployOptions group options of the Deploy API
type DeployOptions struct {
// Build rebuilds service images before deploying
Build *BuildOptions
// Push pushes images to the registry before deploying
Push bool
// Quiet suppresses pull/push progress output
Quiet bool
// RemoveOrphans removes containers for services not defined in the project
RemoveOrphans bool
// Services is the list of services to deploy (defaults to all)
Services []string
// Wait waits for services to be healthy after deploy
Wait bool
// WaitTimeout is the maximum time to wait for services to become healthy
WaitTimeout time.Duration
}

type VolumesOptions struct {
Expand Down
58 changes: 58 additions & 0 deletions pkg/compose/deploy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
Copyright 2020 Docker Compose CLI authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package compose

import (
"context"

"github.com/compose-spec/compose-go/v2/types"

"github.com/docker/compose/v5/pkg/api"
)

func (s *composeService) Deploy(ctx context.Context, project *types.Project, options api.DeployOptions) error {
if options.Build != nil {
if err := s.Build(ctx, project, *options.Build); err != nil {
return err
}
}

if options.Push {
if err := s.Push(ctx, project, api.PushOptions{
Quiet: options.Quiet,
}); err != nil {
return err
}
}

return s.Up(ctx, project, api.UpOptions{
Create: api.CreateOptions{
Services: options.Services,
Recreate: api.RecreateForce,
RecreateDependencies: api.RecreateForce,
RemoveOrphans: options.RemoveOrphans,
Inherit: true,
QuietPull: options.Quiet,
},
Start: api.StartOptions{
Project: project,
Services: options.Services,
Wait: options.Wait,
WaitTimeout: options.WaitTimeout,
},
})
}
Loading
Loading