Skip to content
Closed
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
9 changes: 6 additions & 3 deletions cmd/compose/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
noAttach []string
timestamp bool
wait bool
waitServices []string
waitTimeout int
watch bool
navigationMenu bool
Expand Down Expand Up @@ -168,7 +169,8 @@
flags.StringArrayVar(&up.attach, "attach", []string{}, "Restrict attaching to the specified services. Incompatible with --attach-dependencies.")
flags.StringArrayVar(&up.noAttach, "no-attach", []string{}, "Do not attach (stream logs) to the specified services")
flags.BoolVar(&up.attachDependencies, "attach-dependencies", false, "Automatically attach to log output of dependent services")
flags.BoolVar(&up.wait, "wait", false, "Wait for services to be running|healthy. Implies detached mode.")
flags.BoolVar(&up.wait, "wait", false, "Wait for all services to be running|healthy. Implies detached mode.")
flags.StringArrayVar(&up.waitServices, "wait-services", []string{}, "Wait for specified services to be running|healthy. Implies detached mode.")
flags.IntVar(&up.waitTimeout, "wait-timeout", 0, "Maximum duration in seconds to wait for the project to be running|healthy")
flags.BoolVarP(&up.watch, "watch", "w", false, "Watch source code and rebuild/refresh containers when files are updated.")
flags.BoolVar(&up.navigationMenu, "menu", false, "Enable interactive shortcuts when running attached. Incompatible with --detach. Can also be enable/disable by setting COMPOSE_MENU environment var.")
Expand All @@ -192,9 +194,9 @@
if up.cascadeStop && up.cascadeFail {
return fmt.Errorf("--abort-on-container-failure cannot be combined with --abort-on-container-exit")
}
if up.wait {
if up.wait || len(up.waitServices) > 0 {
if up.attachDependencies || up.cascadeStop || len(up.attach) > 0 {
return fmt.Errorf("--wait cannot be combined with --abort-on-container-exit, --attach or --attach-dependencies")
return fmt.Errorf("--wait|--wait-services cannot be combined with --abort-on-container-exit, --attach or --attach-dependencies")

Check warning on line 199 in cmd/compose/up.go

View check run for this annotation

Codecov / codecov/patch

cmd/compose/up.go#L199

Added line #L199 was not covered by tests
}
up.Detach = true
}
Expand Down Expand Up @@ -325,6 +327,7 @@
ExitCodeFrom: upOptions.exitCodeFrom,
OnExit: upOptions.OnExit(),
Wait: upOptions.wait,
WaitServices: upOptions.waitServices,
WaitTimeout: timeout,
Watch: upOptions.watch,
Services: services,
Expand Down
3 changes: 2 additions & 1 deletion docs/reference/compose_up.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ If the process is interrupted using `SIGINT` (ctrl + C) or `SIGTERM`, the contai
| `--scale` | `stringArray` | | Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. |
| `-t`, `--timeout` | `int` | `0` | Use this timeout in seconds for container shutdown when attached or when containers are already running |
| `--timestamps` | `bool` | | Show timestamps |
| `--wait` | `bool` | | Wait for services to be running\|healthy. Implies detached mode. |
| `--wait` | `bool` | | Wait for all services to be running\|healthy. Implies detached mode. |
| `--wait-services` | `stringArray` | | Wait for specified services to be running\|healthy. Implies detached mode. |
| `--wait-timeout` | `int` | `0` | Maximum duration in seconds to wait for the project to be running\|healthy |
| `-w`, `--watch` | `bool` | | Watch source code and rebuild/refresh containers when files are updated. |
| `-y`, `--yes` | `bool` | | Assume "yes" as answer to all prompts and run non-interactively |
Expand Down
14 changes: 13 additions & 1 deletion docs/reference/docker_compose_up.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,19 @@ options:
- option: wait
value_type: bool
default_value: "false"
description: Wait for services to be running|healthy. Implies detached mode.
description: |
Wait for all services to be running|healthy. Implies detached mode.
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: wait-services
value_type: stringArray
default_value: '[]'
description: |
Wait for specified services to be running|healthy. Implies detached mode.
deprecated: false
hidden: false
experimental: false
Expand Down
5 changes: 4 additions & 1 deletion pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,10 @@ type StartOptions struct {
// ExitCodeFrom return exit code from specified service
ExitCodeFrom string
// Wait won't return until containers reached the running|healthy state
Wait bool
Wait bool
// WaitServices defines the services to wait for
WaitServices []string
// WaitTimeout set delay to wait for container to reach running state
WaitTimeout time.Duration
// Services passed in the command line to be started
Services []string
Expand Down
52 changes: 34 additions & 18 deletions pkg/compose/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,30 +134,46 @@
return err
}

if options.Wait {
depends := types.DependsOnConfig{}
for _, s := range project.Services {
depends[s.Name] = types.ServiceDependency{
Condition: getDependencyCondition(s, project),
Required: true,
}
err = s.waitIfNeeded(ctx, project, options, containers)
if err != nil {
return err
}

Check warning on line 140 in pkg/compose/start.go

View check run for this annotation

Codecov / codecov/patch

pkg/compose/start.go#L139-L140

Added lines #L139 - L140 were not covered by tests

return eg.Wait()
}

func (s *composeService) waitIfNeeded(ctx context.Context, project *types.Project, options api.StartOptions, containers Containers) error {
if !options.Wait && len(options.WaitServices) == 0 {
return nil
}

depends := types.DependsOnConfig{}
for _, s := range project.Services {
if len(options.WaitServices) > 0 && !utils.Contains(options.WaitServices, s.Name) {
continue

Check warning on line 153 in pkg/compose/start.go

View check run for this annotation

Codecov / codecov/patch

pkg/compose/start.go#L153

Added line #L153 was not covered by tests
}
if options.WaitTimeout > 0 {
withTimeout, cancel := context.WithTimeout(ctx, options.WaitTimeout)
ctx = withTimeout
defer cancel()

depends[s.Name] = types.ServiceDependency{
Condition: getDependencyCondition(s, project),
Required: true,
}
}

err = s.waitDependencies(ctx, project, project.Name, depends, containers, 0)
if err != nil {
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
return fmt.Errorf("application not healthy after %s", options.WaitTimeout)
}
return err
if options.WaitTimeout > 0 {
withTimeout, cancel := context.WithTimeout(ctx, options.WaitTimeout)
ctx = withTimeout
defer cancel()
}

Check warning on line 166 in pkg/compose/start.go

View check run for this annotation

Codecov / codecov/patch

pkg/compose/start.go#L163-L166

Added lines #L163 - L166 were not covered by tests

err := s.waitDependencies(ctx, project, project.Name, depends, containers, 0)
if err != nil {
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
return fmt.Errorf("application not healthy after %s", options.WaitTimeout)

Check warning on line 171 in pkg/compose/start.go

View check run for this annotation

Codecov / codecov/patch

pkg/compose/start.go#L170-L171

Added lines #L170 - L171 were not covered by tests
}
return err

Check warning on line 173 in pkg/compose/start.go

View check run for this annotation

Codecov / codecov/patch

pkg/compose/start.go#L173

Added line #L173 was not covered by tests
}

return eg.Wait()
return nil
}

// getDependencyCondition checks if service is depended on by other services
Expand Down