mirror of https://github.com/docker/compose.git
Merge pull request #1554 from docker/poll_completed
fix race condition with init containers
This commit is contained in:
commit
bce61295ba
2
go.mod
2
go.mod
|
@ -17,7 +17,7 @@ require (
|
|||
github.com/awslabs/goformation/v4 v4.15.6
|
||||
github.com/buger/goterm v1.0.0
|
||||
github.com/cnabio/cnab-to-oci v0.3.1-beta1
|
||||
github.com/compose-spec/compose-go v0.0.0-20210412113016-e35895260882
|
||||
github.com/compose-spec/compose-go v0.0.0-20210421142148-66b18e67d2c0
|
||||
github.com/containerd/console v1.0.1
|
||||
github.com/containerd/containerd v1.4.3
|
||||
github.com/containerd/continuity v0.0.0-20200928162600-f2cc35102c2a // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -308,8 +308,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
|
|||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/compose-spec/compose-go v0.0.0-20210412113016-e35895260882 h1:vLKOiHY9QPS1eiBvGfsEI7wR23B1bGNvwOF5aVl25Fs=
|
||||
github.com/compose-spec/compose-go v0.0.0-20210412113016-e35895260882/go.mod h1:6eIT9U2OgdHmkRD6szmqatCrWWEEUSwl/j2iJYH4jLo=
|
||||
github.com/compose-spec/compose-go v0.0.0-20210421142148-66b18e67d2c0 h1:aoUSQGFmWi8dn1OfT4H5Mx48u5wHt+n07nLFw5j1JXs=
|
||||
github.com/compose-spec/compose-go v0.0.0-20210421142148-66b18e67d2c0/go.mod h1:6eIT9U2OgdHmkRD6szmqatCrWWEEUSwl/j2iJYH4jLo=
|
||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
|
||||
github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340 h1:9atoWyI9RtXFwf7UDbme/6M8Ud0rFrx+Q3ZWgSnsxtw=
|
||||
|
|
|
@ -19,9 +19,7 @@ package compose
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
|
@ -50,7 +48,7 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti
|
|||
if service.Build != nil {
|
||||
imageName := getImageName(service, project.Name)
|
||||
imagesToBuild = append(imagesToBuild, imageName)
|
||||
buildOptions, err := s.toBuildOptions(service, project.WorkingDir, imageName)
|
||||
buildOptions, err := s.toBuildOptions(service, imageName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -132,7 +130,7 @@ func (s *composeService) getBuildOptions(project *types.Project, images map[stri
|
|||
continue
|
||||
}
|
||||
imagesToBuild = append(imagesToBuild, imageName)
|
||||
opt, err := s.toBuildOptions(service, project.WorkingDir, imageName)
|
||||
opt, err := s.toBuildOptions(service, imageName)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -257,13 +255,10 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opts
|
|||
return imagesBuilt, err
|
||||
}
|
||||
|
||||
func (s *composeService) toBuildOptions(service types.ServiceConfig, contextPath string, imageTag string) (build.Options, error) {
|
||||
func (s *composeService) toBuildOptions(service types.ServiceConfig, imageTag string) (build.Options, error) {
|
||||
var tags []string
|
||||
tags = append(tags, imageTag)
|
||||
|
||||
if service.Build.Dockerfile == "" {
|
||||
service.Build.Dockerfile = "Dockerfile"
|
||||
}
|
||||
var buildArgs map[string]string
|
||||
|
||||
var plats []specs.Platform
|
||||
|
@ -275,22 +270,11 @@ func (s *composeService) toBuildOptions(service types.ServiceConfig, contextPath
|
|||
plats = append(plats, p)
|
||||
}
|
||||
|
||||
var input build.Inputs
|
||||
_, err := url.ParseRequestURI(service.Build.Context)
|
||||
if err == nil {
|
||||
input = build.Inputs{
|
||||
return build.Options{
|
||||
Inputs: build.Inputs{
|
||||
ContextPath: service.Build.Context,
|
||||
DockerfilePath: service.Build.Dockerfile,
|
||||
}
|
||||
} else {
|
||||
input = build.Inputs{
|
||||
ContextPath: path.Join(contextPath, service.Build.Context),
|
||||
DockerfilePath: path.Join(contextPath, service.Build.Context, service.Build.Dockerfile),
|
||||
}
|
||||
}
|
||||
|
||||
return build.Options{
|
||||
Inputs: input,
|
||||
},
|
||||
BuildArgs: flatten(mergeArgs(service.Build.Args, buildArgs)),
|
||||
Tags: tags,
|
||||
Target: service.Build.Target,
|
||||
|
|
|
@ -25,10 +25,10 @@ import (
|
|||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
|
@ -147,13 +147,13 @@ func getContainerProgressName(container moby.Container) string {
|
|||
func (s *composeService) waitDependencies(ctx context.Context, project *types.Project, service types.ServiceConfig) error {
|
||||
eg, _ := errgroup.WithContext(ctx)
|
||||
for dep, config := range service.DependsOn {
|
||||
switch config.Condition {
|
||||
case "service_healthy":
|
||||
eg.Go(func() error {
|
||||
ticker := time.NewTicker(500 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
<-ticker.C
|
||||
eg.Go(func() error {
|
||||
ticker := time.NewTicker(500 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
<-ticker.C
|
||||
switch config.Condition {
|
||||
case types.ServiceConditionHealthy:
|
||||
healthy, err := s.isServiceHealthy(ctx, project, dep)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -161,17 +161,26 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr
|
|||
if healthy {
|
||||
return nil
|
||||
}
|
||||
case types.ServiceConditionCompletedSuccessfully:
|
||||
exited, code, err := s.isServiceCompleted(ctx, project, dep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exited {
|
||||
if code != 0 {
|
||||
return fmt.Errorf("service %q didn't completed successfully: exit %d", dep, code)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
case types.ServiceConditionStarted:
|
||||
// already managed by InDependencyOrder
|
||||
return nil
|
||||
default:
|
||||
logrus.Warnf("unsupported depends_on condition: %s", config.Condition)
|
||||
return nil
|
||||
}
|
||||
})
|
||||
case "service_completed_successfully":
|
||||
exit, err := s.waitCompleted(ctx, project, dep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exit != 0 {
|
||||
return fmt.Errorf("service %q didn't completed successfully: exit %d", dep, exit)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return eg.Wait()
|
||||
}
|
||||
|
@ -360,26 +369,21 @@ func (s *composeService) isServiceHealthy(ctx context.Context, project *types.Pr
|
|||
return true, nil
|
||||
}
|
||||
|
||||
func (s *composeService) waitCompleted(ctx context.Context, project *types.Project, dep string) (int64, error) {
|
||||
containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||
Filters: filters.NewArgs(
|
||||
projectFilter(project.Name),
|
||||
serviceFilter(dep),
|
||||
),
|
||||
})
|
||||
func (s *composeService) isServiceCompleted(ctx context.Context, project *types.Project, dep string) (bool, int, error) {
|
||||
containers, err := s.getContainers(ctx, project.Name, oneOffExclude, true, dep)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return false, 0, err
|
||||
}
|
||||
for _, c := range containers {
|
||||
wait, errors := s.apiClient.ContainerWait(ctx, c.ID, container.WaitConditionNextExit)
|
||||
select {
|
||||
case w := <-wait:
|
||||
return w.StatusCode, nil
|
||||
case err := <-errors:
|
||||
return 0, err
|
||||
container, err := s.apiClient.ContainerInspect(ctx, c.ID)
|
||||
if err != nil {
|
||||
return false, 0, err
|
||||
}
|
||||
if container.State != nil && container.State.Status == "exited" {
|
||||
return true, container.State.ExitCode, nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
return false, 0, nil
|
||||
}
|
||||
|
||||
func (s *composeService) startService(ctx context.Context, project *types.Project, service types.ServiceConfig) error {
|
||||
|
|
Loading…
Reference in New Issue