diff --git a/bake/compose.go b/bake/compose.go index db33a8c9..eac95bf3 100644 --- a/bake/compose.go +++ b/bake/compose.go @@ -1,6 +1,9 @@ package bake import ( + "fmt" + "reflect" + "github.com/docker/cli/cli/compose/loader" composetypes "github.com/docker/cli/cli/compose/types" ) @@ -26,6 +29,7 @@ func ParseCompose(dt []byte) (*Config, error) { } var c Config + var zeroBuildConfig composetypes.BuildConfig if len(cfg.Services) > 0 { c.Group = map[string]Group{} c.Target = map[string]Target{} @@ -33,7 +37,15 @@ func ParseCompose(dt []byte) (*Config, error) { var g Group for _, s := range cfg.Services { - g.Targets = append(g.Targets, s.Name) + + if reflect.DeepEqual(s.Build, zeroBuildConfig) { + // if not make sure they're setting an image or it's invalid d-c.yml + if s.Image == "" { + return nil, fmt.Errorf("compose file invalid: service %s has neither an image nor a build context specified. At least one must be provided.", s.Name) + } + continue + } + var contextPathP *string if s.Build.Context != "" { contextPath := s.Build.Context @@ -44,6 +56,7 @@ func ParseCompose(dt []byte) (*Config, error) { dockerfilePath := s.Build.Dockerfile dockerfilePathP = &dockerfilePath } + g.Targets = append(g.Targets, s.Name) t := Target{ Context: contextPathP, Dockerfile: dockerfilePathP, diff --git a/bake/compose_test.go b/bake/compose_test.go index 2f367179..94bf235d 100644 --- a/bake/compose_test.go +++ b/bake/compose_test.go @@ -40,6 +40,21 @@ services: require.Equal(t, "123", c.Target["webapp"].Args["buildno"]) } +func TestNoBuildOutOfTreeService(t *testing.T) { + var dt = []byte(` +version: "3.7" + +services: + external: + image: "verycooldb:1337" + webapp: + build: ./db +`) + c, err := ParseCompose(dt) + require.NoError(t, err) + require.Equal(t, 1, len(c.Group)) +} + func TestParseComposeTarget(t *testing.T) { var dt = []byte(` version: "3.7" @@ -47,9 +62,11 @@ version: "3.7" services: db: build: + context: ./db target: db webapp: build: + context: . target: webapp `) @@ -59,3 +76,42 @@ services: require.Equal(t, "db", *c.Target["db"].Target) require.Equal(t, "webapp", *c.Target["webapp"].Target) } + +func TestComposeBuildWithoutContext(t *testing.T) { + var dt = []byte(` +version: "3.7" + +services: + db: + build: + target: db + webapp: + build: + context: . + target: webapp +`) + + c, err := ParseCompose(dt) + require.NoError(t, err) + require.Equal(t, "db", *c.Target["db"].Target) + require.Equal(t, "webapp", *c.Target["webapp"].Target) +} + +func TestBogusCompose(t *testing.T) { + var dt = []byte(` +version: "3.7" + +services: + db: + labels: + - "foo" + webapp: + build: + context: . + target: webapp +`) + + _, err := ParseCompose(dt) + require.Error(t, err) + require.Contains(t, err.Error(), "has neither an image nor a build context specified. At least one must be provided") +} diff --git a/hack/demo-env/examples/compose/docker-compose.yml b/hack/demo-env/examples/compose/docker-compose.yml index b31c3515..f9b03d13 100644 --- a/hack/demo-env/examples/compose/docker-compose.yml +++ b/hack/demo-env/examples/compose/docker-compose.yml @@ -7,6 +7,7 @@ services: image: docker.io/tonistiigi/db webapp: build: + context: . dockerfile: Dockerfile.webapp args: buildno: 1 \ No newline at end of file