diff --git a/cli/cmd/compose/create.go b/cli/cmd/compose/create.go index 4380c6bf8..87ef50894 100644 --- a/cli/cmd/compose/create.go +++ b/cli/cmd/compose/create.go @@ -17,6 +17,8 @@ package compose import ( + "fmt" + "github.com/spf13/cobra" ) @@ -34,10 +36,17 @@ func createCommand(p *projectOptions) *cobra.Command { Use: "create [SERVICE...]", Short: "Creates containers for a service.", RunE: func(cmd *cobra.Command, args []string) error { + if opts.Build && opts.noBuild { + return fmt.Errorf("--build and --no-build are incompatible") + } + if opts.forceRecreate && opts.noRecreate { + return fmt.Errorf("--force-recreate and --no-recreate are incompatible") + } return runCreateStart(cmd.Context(), upOptions{ composeOptions: &composeOptions{ projectOptions: p, Build: opts.Build, + noBuild: opts.noBuild, }, noStart: true, forceRecreate: opts.forceRecreate, @@ -47,6 +56,7 @@ func createCommand(p *projectOptions) *cobra.Command { } flags := cmd.Flags() flags.BoolVar(&opts.Build, "build", false, "Build images before starting containers.") + flags.BoolVar(&opts.noBuild, "no-build", false, "Don't build an image, even if it's missing.") flags.BoolVar(&opts.forceRecreate, "force-recreate", false, "Recreate containers even if their configuration and image haven't changed.") flags.BoolVar(&opts.noRecreate, "no-recreate", false, "If containers already exist, don't recreate them. Incompatible with --force-recreate.") return cmd diff --git a/cli/cmd/compose/up.go b/cli/cmd/compose/up.go index a52ffb09b..2cff80c49 100644 --- a/cli/cmd/compose/up.go +++ b/cli/cmd/compose/up.go @@ -42,7 +42,8 @@ import ( // composeOptions hold options common to `up` and `run` to run compose project type composeOptions struct { *projectOptions - Build bool + Build bool + noBuild bool // ACI only DomainName string } @@ -87,6 +88,9 @@ func upCommand(p *projectOptions, contextType string) *cobra.Command { if opts.exitCodeFrom != "" { opts.cascadeStop = true } + if opts.Build && opts.noBuild { + return fmt.Errorf("--build and --no-build are incompatible") + } if opts.cascadeStop && opts.Detach { return fmt.Errorf("--abort-on-container-exit and --detach are incompatible") } @@ -103,6 +107,7 @@ func upCommand(p *projectOptions, contextType string) *cobra.Command { flags.StringArrayVarP(&opts.Environment, "environment", "e", []string{}, "Environment variables") flags.BoolVarP(&opts.Detach, "detach", "d", false, "Detached mode: Run containers in the background") flags.BoolVar(&opts.Build, "build", false, "Build images before starting containers.") + flags.BoolVar(&opts.noBuild, "no-build", false, "Don't build an image, even if it's missing.") flags.BoolVar(&opts.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.") flags.StringArrayVar(&opts.scale, "scale", []string{}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.") flags.BoolVar(&opts.noColor, "no-color", false, "Produce monochrome output.") @@ -284,10 +289,18 @@ func setup(ctx context.Context, opts composeOptions, services []string) (*client project.Services[0].DomainName = opts.DomainName } if opts.Build { - for _, service := range project.Services { + for i, service := range project.Services { service.PullPolicy = types.PullPolicyBuild + project.Services[i] = service } } + if opts.noBuild { + for i, service := range project.Services { + service.Build = nil + project.Services[i] = service + } + } + if opts.EnvFile != "" { var services types.Services for _, s := range project.Services { diff --git a/local/compose/build.go b/local/compose/build.go index 9c88430f1..78f5426a3 100644 --- a/local/compose/build.go +++ b/local/compose/build.go @@ -56,7 +56,7 @@ func (s *composeService) ensureImagesExists(ctx context.Context, project *types. if err != nil { return err } - // TODO build vs pull should be controlled by pull policy, see https://github.com/compose-spec/compose-spec/issues/26 + if service.Image != "" { if localImagePresent { continue