github.com/containerd/nerdctl@v1.7.7/cmd/nerdctl/builder_build.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "errors" 21 "fmt" 22 "os" 23 "strings" 24 25 "github.com/containerd/nerdctl/pkg/api/types" 26 "github.com/containerd/nerdctl/pkg/buildkitutil" 27 "github.com/containerd/nerdctl/pkg/clientutil" 28 "github.com/containerd/nerdctl/pkg/cmd/builder" 29 "github.com/containerd/nerdctl/pkg/defaults" 30 "github.com/containerd/nerdctl/pkg/strutil" 31 32 "github.com/spf13/cobra" 33 ) 34 35 func newBuildCommand() *cobra.Command { 36 var buildCommand = &cobra.Command{ 37 Use: "build [flags] PATH", 38 Short: "Build an image from a Dockerfile. Needs buildkitd to be running.", 39 Long: `Build an image from a Dockerfile. Needs buildkitd to be running. 40 If Dockerfile is not present and -f is not specified, it will look for Containerfile and build with it. `, 41 RunE: buildAction, 42 SilenceUsage: true, 43 SilenceErrors: true, 44 } 45 AddStringFlag(buildCommand, "buildkit-host", nil, defaults.BuildKitHost(), "BUILDKIT_HOST", "BuildKit address") 46 buildCommand.Flags().StringArrayP("tag", "t", nil, "Name and optionally a tag in the 'name:tag' format") 47 buildCommand.Flags().StringP("file", "f", "", "Name of the Dockerfile") 48 buildCommand.Flags().String("target", "", "Set the target build stage to build") 49 buildCommand.Flags().StringArray("build-arg", nil, "Set build-time variables") 50 buildCommand.Flags().Bool("no-cache", false, "Do not use cache when building the image") 51 buildCommand.Flags().StringP("output", "o", "", "Output destination (format: type=local,dest=path)") 52 buildCommand.Flags().String("progress", "auto", "Set type of progress output (auto, plain, tty). Use plain to show container output") 53 buildCommand.Flags().StringArray("secret", nil, "Secret file to expose to the build: id=mysecret,src=/local/secret") 54 buildCommand.Flags().StringArray("allow", nil, "Allow extra privileged entitlement, e.g. network.host, security.insecure") 55 buildCommand.RegisterFlagCompletionFunc("allow", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 56 return []string{"network.host", "security.insecure"}, cobra.ShellCompDirectiveNoFileComp 57 }) 58 buildCommand.Flags().StringArray("ssh", nil, "SSH agent socket or keys to expose to the build (format: default|<id>[=<socket>|<key>[,<key>]])") 59 buildCommand.Flags().BoolP("quiet", "q", false, "Suppress the build output and print image ID on success") 60 buildCommand.Flags().StringArray("cache-from", nil, "External cache sources (eg. user/app:cache, type=local,src=path/to/dir)") 61 buildCommand.Flags().StringArray("cache-to", nil, "Cache export destinations (eg. user/app:cache, type=local,dest=path/to/dir)") 62 buildCommand.Flags().Bool("rm", true, "Remove intermediate containers after a successful build") 63 buildCommand.Flags().String("network", "default", "Set type of network for build (format:network=default|none|host)") 64 buildCommand.RegisterFlagCompletionFunc("network", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { 65 return []string{"default", "host", "none"}, cobra.ShellCompDirectiveNoFileComp 66 }) 67 // #region platform flags 68 // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" 69 buildCommand.Flags().StringSlice("platform", []string{}, "Set target platform for build (e.g., \"amd64\", \"arm64\")") 70 buildCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) 71 // #endregion 72 73 buildCommand.Flags().String("iidfile", "", "Write the image ID to the file") 74 buildCommand.Flags().StringArray("label", nil, "Set metadata for an image") 75 76 return buildCommand 77 } 78 79 func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBuildOptions, error) { 80 globalOptions, err := processRootCmdFlags(cmd) 81 if err != nil { 82 return types.BuilderBuildOptions{}, err 83 } 84 buildKitHost, err := getBuildkitHost(cmd, globalOptions.Namespace) 85 if err != nil { 86 return types.BuilderBuildOptions{}, err 87 } 88 platform, err := cmd.Flags().GetStringSlice("platform") 89 if err != nil { 90 return types.BuilderBuildOptions{}, err 91 } 92 platform = strutil.DedupeStrSlice(platform) 93 if len(args) < 1 { 94 return types.BuilderBuildOptions{}, errors.New("context needs to be specified") 95 } 96 buildContext := args[0] 97 if buildContext == "-" || strings.Contains(buildContext, "://") { 98 return types.BuilderBuildOptions{}, fmt.Errorf("unsupported build context: %q", buildContext) 99 } 100 output, err := cmd.Flags().GetString("output") 101 if err != nil { 102 return types.BuilderBuildOptions{}, err 103 } 104 tagValue, err := cmd.Flags().GetStringArray("tag") 105 if err != nil { 106 return types.BuilderBuildOptions{}, err 107 } 108 progress, err := cmd.Flags().GetString("progress") 109 if err != nil { 110 return types.BuilderBuildOptions{}, err 111 } 112 filename, err := cmd.Flags().GetString("file") 113 if err != nil { 114 return types.BuilderBuildOptions{}, err 115 } 116 target, err := cmd.Flags().GetString("target") 117 if err != nil { 118 return types.BuilderBuildOptions{}, err 119 } 120 buildArgs, err := cmd.Flags().GetStringArray("build-arg") 121 if err != nil { 122 return types.BuilderBuildOptions{}, err 123 } 124 label, err := cmd.Flags().GetStringArray("label") 125 if err != nil { 126 return types.BuilderBuildOptions{}, err 127 } 128 noCache, err := cmd.Flags().GetBool("no-cache") 129 if err != nil { 130 return types.BuilderBuildOptions{}, err 131 } 132 secret, err := cmd.Flags().GetStringArray("secret") 133 if err != nil { 134 return types.BuilderBuildOptions{}, err 135 } 136 allow, err := cmd.Flags().GetStringArray("allow") 137 if err != nil { 138 return types.BuilderBuildOptions{}, err 139 } 140 ssh, err := cmd.Flags().GetStringArray("ssh") 141 if err != nil { 142 return types.BuilderBuildOptions{}, err 143 } 144 cacheFrom, err := cmd.Flags().GetStringArray("cache-from") 145 if err != nil { 146 return types.BuilderBuildOptions{}, err 147 } 148 cacheTo, err := cmd.Flags().GetStringArray("cache-to") 149 if err != nil { 150 return types.BuilderBuildOptions{}, err 151 } 152 rm, err := cmd.Flags().GetBool("rm") 153 if err != nil { 154 return types.BuilderBuildOptions{}, err 155 } 156 iidfile, err := cmd.Flags().GetString("iidfile") 157 if err != nil { 158 return types.BuilderBuildOptions{}, err 159 } 160 quiet, err := cmd.Flags().GetBool("quiet") 161 if err != nil { 162 return types.BuilderBuildOptions{}, err 163 } 164 network, err := cmd.Flags().GetString("network") 165 if err != nil { 166 return types.BuilderBuildOptions{}, err 167 } 168 return types.BuilderBuildOptions{ 169 GOptions: globalOptions, 170 BuildKitHost: buildKitHost, 171 BuildContext: buildContext, 172 Output: output, 173 Tag: tagValue, 174 Progress: progress, 175 File: filename, 176 Target: target, 177 BuildArgs: buildArgs, 178 Label: label, 179 NoCache: noCache, 180 Secret: secret, 181 Allow: allow, 182 SSH: ssh, 183 CacheFrom: cacheFrom, 184 CacheTo: cacheTo, 185 Rm: rm, 186 IidFile: iidfile, 187 Quiet: quiet, 188 Platform: platform, 189 Stdout: cmd.OutOrStdout(), 190 Stderr: cmd.OutOrStderr(), 191 Stdin: cmd.InOrStdin(), 192 NetworkMode: network, 193 }, nil 194 } 195 196 func getBuildkitHost(cmd *cobra.Command, namespace string) (string, error) { 197 if cmd.Flags().Changed("buildkit-host") || os.Getenv("BUILDKIT_HOST") != "" { 198 // If address is explicitly specified, use it. 199 buildkitHost, err := cmd.Flags().GetString("buildkit-host") 200 if err != nil { 201 return "", err 202 } 203 if err := buildkitutil.PingBKDaemon(buildkitHost); err != nil { 204 return "", err 205 } 206 return buildkitHost, nil 207 } 208 return buildkitutil.GetBuildkitHost(namespace) 209 } 210 211 func buildAction(cmd *cobra.Command, args []string) error { 212 options, err := processBuildCommandFlag(cmd, args) 213 if err != nil { 214 return err 215 } 216 217 client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), options.GOptions.Namespace, options.GOptions.Address) 218 if err != nil { 219 return err 220 } 221 defer cancel() 222 223 return builder.Build(ctx, client, options) 224 }