diff --git a/cli/command/cli.go b/cli/command/cli.go index 242b5f0358ff..9314af629de0 100644 --- a/cli/command/cli.go +++ b/cli/command/cli.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" "runtime" + "strconv" "time" "github.com/docker/cli/cli" @@ -133,6 +134,20 @@ func (cli *DockerCli) ContentTrustEnabled() bool { return cli.contentTrust } +// BuildKitEnabled returns whether buildkit is enabled either through a daemon setting +// or otherwise the client-side DOCKER_BUILDKIT environment variable +func BuildKitEnabled(si ServerInfo) (bool, error) { + buildkitEnabled := si.BuildkitVersion == types.BuilderBuildKit + if buildkitEnv := os.Getenv("DOCKER_BUILDKIT"); buildkitEnv != "" { + var err error + buildkitEnabled, err = strconv.ParseBool(buildkitEnv) + if err != nil { + return false, errors.Wrap(err, "DOCKER_BUILDKIT environment variable expects boolean value") + } + } + return buildkitEnabled, nil +} + // ManifestStore returns a store for local manifests func (cli *DockerCli) ManifestStore() manifeststore.Store { // TODO: support override default location from config file diff --git a/cli/command/image/build.go b/cli/command/image/build.go index ad7a21f1f5cb..e91bb48c212e 100644 --- a/cli/command/image/build.go +++ b/cli/command/image/build.go @@ -13,7 +13,6 @@ import ( "path/filepath" "regexp" "runtime" - "strconv" "strings" "github.com/docker/cli/cli" @@ -137,6 +136,8 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command { flags.BoolVar(&options.pull, "pull", false, "Always attempt to pull a newer version of the image") flags.StringSliceVar(&options.cacheFrom, "cache-from", []string{}, "Images to consider as cache sources") flags.BoolVar(&options.compress, "compress", false, "Compress the build context using gzip") + flags.SetAnnotation("compress", "no-buildkit", nil) + flags.StringSliceVar(&options.securityOpt, "security-opt", []string{}, "Security options") flags.StringVar(&options.networkMode, "network", "default", "Set the networking mode for the RUN instructions during build") flags.SetAnnotation("network", "version", []string{"1.25"}) @@ -154,14 +155,18 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command { flags.BoolVar(&options.stream, "stream", false, "Stream attaches to server to negotiate build context") flags.SetAnnotation("stream", "experimental", nil) flags.SetAnnotation("stream", "version", []string{"1.31"}) + flags.SetAnnotation("stream", "no-buildkit", nil) - flags.StringVar(&options.progress, "progress", "auto", "Set type of progress output (only if BuildKit enabled) (auto, plain, tty). Use plain to show container output") + flags.StringVar(&options.progress, "progress", "auto", "Set type of progress output (auto, plain, tty). Use plain to show container output") + flags.SetAnnotation("progress", "buildkit", nil) flags.StringArrayVar(&options.secrets, "secret", []string{}, "Secret file to expose to the build (only if BuildKit enabled): id=mysecret,src=/local/secret") flags.SetAnnotation("secret", "version", []string{"1.39"}) + flags.SetAnnotation("secret", "buildkit", nil) flags.StringArrayVar(&options.ssh, "ssh", []string{}, "SSH agent socket or keys to expose to the build (only if BuildKit enabled) (format: default|[=|[,]])") flags.SetAnnotation("ssh", "version", []string{"1.39"}) + flags.SetAnnotation("ssh", "buildkit", nil) return cmd } @@ -183,22 +188,17 @@ func (out *lastProgressOutput) WriteProgress(prog progress.Progress) error { // nolint: gocyclo func runBuild(dockerCli command.Cli, options buildOptions) error { - if buildkitEnv := os.Getenv("DOCKER_BUILDKIT"); buildkitEnv != "" { - enableBuildkit, err := strconv.ParseBool(buildkitEnv) - if err != nil { - return errors.Wrap(err, "DOCKER_BUILDKIT environment variable expects boolean value") - } - if enableBuildkit { - return runBuildBuildKit(dockerCli, options) - } - } else if dockerCli.ServerInfo().BuildkitVersion == types.BuilderBuildKit { + buildkitEnabled, err := command.BuildKitEnabled(dockerCli.ServerInfo()) + if err != nil { + return err + } + if buildkitEnabled { return runBuildBuildKit(dockerCli, options) } var ( buildCtx io.ReadCloser dockerfileCtx io.ReadCloser - err error contextDir string tempDir string relDockerfile string diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index a2bcd2a2cdf3..9b7a9a136716 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -100,8 +100,10 @@ func setHelpFunc(dockerCli *command.DockerCli, cmd *cobra.Command, flags *pflag. ccmd.Println(err) return } - - hideUnsupportedFeatures(ccmd, dockerCli) + if err := hideUnsupportedFeatures(ccmd, dockerCli); err != nil { + ccmd.Println(err) + return + } defaultHelpFunc(ccmd, args) }) } @@ -235,15 +237,21 @@ func hideFeatureSubCommand(subcmd *cobra.Command, hasFeature bool, annotation st } } -func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) { +func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) error { clientVersion := details.Client().ClientVersion() osType := details.ServerInfo().OSType hasExperimental := details.ServerInfo().HasExperimental hasExperimentalCLI := details.ClientInfo().HasExperimental + hasBuildKit, err := command.BuildKitEnabled(details.ServerInfo()) + if err != nil { + return err + } cmd.Flags().VisitAll(func(f *pflag.Flag) { hideFeatureFlag(f, hasExperimental, "experimental") hideFeatureFlag(f, hasExperimentalCLI, "experimentalCLI") + hideFeatureFlag(f, hasBuildKit, "buildkit") + hideFeatureFlag(f, !hasBuildKit, "no-buildkit") // hide flags not supported by the server if !isOSTypeSupported(f, osType) || !isVersionSupported(f, clientVersion) { f.Hidden = true @@ -259,6 +267,8 @@ func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) { for _, subcmd := range cmd.Commands() { hideFeatureSubCommand(subcmd, hasExperimental, "experimental") hideFeatureSubCommand(subcmd, hasExperimentalCLI, "experimentalCLI") + hideFeatureSubCommand(subcmd, hasBuildKit, "buildkit") + hideFeatureSubCommand(subcmd, !hasBuildKit, "no-buildkit") // hide subcommands not supported by the server if subcmdVersion, ok := subcmd.Annotations["version"]; ok && versions.LessThan(clientVersion, subcmdVersion) { subcmd.Hidden = true @@ -267,6 +277,7 @@ func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) { subcmd.Hidden = true } } + return nil } // Checks if a command or one of its ancestors is in the list @@ -313,6 +324,7 @@ func areFlagsSupported(cmd *cobra.Command, details versionDetails) error { if _, ok := f.Annotations["experimentalCLI"]; ok && !hasExperimentalCLI { errs = append(errs, fmt.Sprintf("\"--%s\" is on a Docker cli with experimental cli features enabled", f.Name)) } + // buildkit-specific flags are noop when buildkit is not enabled, so we do not add an error in that case } }) if len(errs) > 0 {