Skip to content

Commit 80dc420

Browse files
committed
[Windows] nerdctl build - Replace default type=docker with type=image
- Use default image name only when user has not specified one Signed-off-by: Christine Murimi <[email protected]>
1 parent 8b814ca commit 80dc420

File tree

2 files changed

+67
-35
lines changed

2 files changed

+67
-35
lines changed

Diff for: docs/command-reference.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,10 @@ Flags:
691691
- :whale: `--target`: Set the target build stage to build
692692
- :whale: `--build-arg`: Set build-time variables
693693
- :whale: `--no-cache`: Do not use cache when building the image
694-
- :whale: `--output=OUTPUT`: Output destination (format: type=local,dest=path)
694+
- :whale: `--output=OUTPUT`: Output destination (format: type=local,dest=path). See [buildctl output](https://github.com/moby/buildkit?tab=readme-ov-file#output) option for more details.
695+
696+
If this flag is not specified, it defaults to `type=image,name=docker.io/library/<TAG>:latest`.
697+
695698
- :whale: `type=local,dest=path/to/output-dir`: Local directory
696699
- :whale: `type=oci[,dest=path/to/output.tar]`: Docker/OCI dual-format tar ball (compatible with `docker buildx build`)
697700
- :whale: `type=docker[,dest=path/to/output.tar]`: Docker format tar ball (compatible with `docker buildx build`)

Diff for: pkg/cmd/builder/build.go

+63-34
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,22 @@ func (p platformParser) DefaultSpec() platforms.Platform {
6161
}
6262

6363
func Build(ctx context.Context, client *containerd.Client, options types.BuilderBuildOptions) error {
64-
buildctlBinary, buildctlArgs, needsLoading, metaFile, tags, cleanup, err := generateBuildctlArgs(ctx, client, options)
64+
buildCtlArgs, err := generateBuildctlArgs(ctx, client, options)
6565
if err != nil {
6666
return err
6767
}
68-
if cleanup != nil {
69-
defer cleanup()
68+
if buildCtlArgs.Cleanup != nil {
69+
defer buildCtlArgs.Cleanup()
7070
}
7171

72+
buildctlBinary := buildCtlArgs.BuildctlBinary
73+
buildctlArgs := buildCtlArgs.BuildctlArgs
74+
7275
log.L.Debugf("running %s %v", buildctlBinary, buildctlArgs)
7376
buildctlCmd := exec.Command(buildctlBinary, buildctlArgs...)
7477
buildctlCmd.Env = os.Environ()
7578

79+
needsLoading := buildCtlArgs.NeedsLoading
7680
var buildctlStdout io.Reader
7781
if needsLoading {
7882
buildctlStdout, err = buildctlCmd.StdoutPipe()
@@ -95,6 +99,8 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder
9599
if err != nil {
96100
return err
97101
}
102+
103+
// Load the image into the containerd image store
98104
if err = loadImage(ctx, buildctlStdout, options.GOptions.Namespace, options.GOptions.Address, options.GOptions.Snapshotter, options.Stdout, platMC, options.Quiet); err != nil {
99105
return err
100106
}
@@ -105,7 +111,7 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder
105111
}
106112

107113
if options.IidFile != "" {
108-
id, err := getDigestFromMetaFile(metaFile)
114+
id, err := getDigestFromMetaFile(buildCtlArgs.MetaFile)
109115
if err != nil {
110116
return err
111117
}
@@ -114,6 +120,7 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder
114120
}
115121
}
116122

123+
tags := buildCtlArgs.Tags
117124
if len(tags) > 1 {
118125
log.L.Debug("Found more than 1 tag")
119126
imageService := client.ImageService()
@@ -160,11 +167,15 @@ func loadImage(ctx context.Context, in io.Reader, namespace, address, snapshotte
160167
client.Close()
161168
}()
162169
r := &readCounter{Reader: in}
163-
imgs, err := client.Import(ctx, r, containerd.WithDigestRef(archive.DigestTranslator(snapshotter)), containerd.WithSkipDigestRef(func(name string) bool { return name != "" }), containerd.WithImportPlatform(platMC))
170+
imgs, err := client.Import(ctx, r,
171+
containerd.WithDigestRef(archive.DigestTranslator(snapshotter)),
172+
containerd.WithSkipDigestRef(func(name string) bool { return name != "" }),
173+
containerd.WithImportPlatform(platMC),
174+
)
164175
if err != nil {
165176
if r.N == 0 {
166177
// Avoid confusing "unrecognized image format"
167-
return errors.New("no image was built")
178+
return fmt.Errorf("no image was built: %w", err)
168179
}
169180
if errors.Is(err, images.ErrEmptyWalk) {
170181
err = fmt.Errorf("%w (Hint: set `--platform=PLATFORM` or `--all-platforms`)", err)
@@ -192,69 +203,85 @@ func loadImage(ctx context.Context, in io.Reader, namespace, address, snapshotte
192203
return nil
193204
}
194205

195-
func generateBuildctlArgs(ctx context.Context, client *containerd.Client, options types.BuilderBuildOptions) (buildCtlBinary string,
196-
buildctlArgs []string, needsLoading bool, metaFile string, tags []string, cleanup func(), err error) {
206+
type BuildctlArgsResult struct {
207+
BuildctlArgs []string
208+
BuildctlBinary string
209+
Cleanup func()
210+
DestFile string
211+
MetaFile string
212+
NeedsLoading bool // Specifies whether the image needs to be loaded into the containerd image store
213+
Tags []string
214+
}
197215

216+
func generateBuildctlArgs(ctx context.Context, client *containerd.Client, options types.BuilderBuildOptions) (result BuildctlArgsResult, err error) {
198217
buildctlBinary, err := buildkitutil.BuildctlBinary()
199218
if err != nil {
200-
return "", nil, false, "", nil, nil, err
219+
return result, err
201220
}
221+
result.BuildctlBinary = buildctlBinary
202222

203223
output := options.Output
204224
if output == "" {
205225
info, err := client.Server(ctx)
206226
if err != nil {
207-
return "", nil, false, "", nil, nil, err
227+
return result, err
208228
}
209229
sharable, err := isImageSharable(options.BuildKitHost, options.GOptions.Namespace, info.UUID, options.GOptions.Snapshotter, options.Platform)
210230
if err != nil {
211-
return "", nil, false, "", nil, nil, err
231+
return result, err
212232
}
213233
if sharable {
214234
output = "type=image,unpack=true" // ensure the target stage is unlazied (needed for any snapshotters)
215235
} else {
216-
output = "type=docker"
236+
// https://github.com/moby/buildkit?tab=readme-ov-file#output
237+
// type=image is the native type for containerd
238+
output = "type=image"
217239
if len(options.Platform) > 1 {
218240
// For avoiding `error: failed to solve: docker exporter does not currently support exporting manifest lists`
219241
// TODO: consider using type=oci for single-options.Platform build too
220242
output = "type=oci"
221243
}
222-
needsLoading = true
223244
}
224245
} else {
225246
if !strings.Contains(output, "type=") {
226247
// should accept --output <DIR> as an alias of --output
227248
// type=local,dest=<DIR>
228249
output = fmt.Sprintf("type=local,dest=%s", output)
229250
}
230-
if strings.Contains(output, "type=docker") || strings.Contains(output, "type=oci") {
231-
if !strings.Contains(output, "dest=") {
232-
needsLoading = true
233-
}
251+
}
252+
253+
if strings.Contains(output, "type=docker") || strings.Contains(output, "type=oci") {
254+
if !strings.Contains(output, "dest=") {
255+
result.NeedsLoading = true
234256
}
235257
}
258+
259+
var tags []string
236260
if tags = strutil.DedupeStrSlice(options.Tag); len(tags) > 0 {
237261
ref := tags[0]
238262
parsedReference, err := referenceutil.Parse(ref)
239263
if err != nil {
240-
return "", nil, false, "", nil, nil, err
264+
return result, err
265+
}
266+
// Update the output with the the image name if it is not already set
267+
if !strings.Contains(output, "name=") {
268+
output += ",name=" + parsedReference.String()
241269
}
242-
output += ",name=" + parsedReference.String()
243270

244271
// pick the first tag and add it to output
245272
for idx, tag := range tags {
246273
parsedReference, err = referenceutil.Parse(tag)
247274
if err != nil {
248-
return "", nil, false, "", nil, nil, err
275+
return result, err
249276
}
250277
tags[idx] = parsedReference.String()
251278
}
252279
} else if len(tags) == 0 {
253280
output = output + ",dangling-name-prefix=<none>"
254281
}
282+
result.Tags = tags
255283

256-
buildctlArgs = buildkitutil.BuildctlBaseArgs(options.BuildKitHost)
257-
284+
buildctlArgs := buildkitutil.BuildctlBaseArgs(options.BuildKitHost)
258285
buildctlArgs = append(buildctlArgs, []string{
259286
"build",
260287
"--progress=" + options.Progress,
@@ -271,9 +298,9 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
271298
var err error
272299
dir, err = buildkitutil.WriteTempDockerfile(options.Stdin)
273300
if err != nil {
274-
return "", nil, false, "", nil, nil, err
301+
return result, err
275302
}
276-
cleanup = func() {
303+
result.Cleanup = func() {
277304
os.RemoveAll(dir)
278305
}
279306
} else {
@@ -286,12 +313,12 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
286313
}
287314
dir, file, err = buildkitutil.BuildKitFile(dir, file)
288315
if err != nil {
289-
return "", nil, false, "", nil, nil, err
316+
return result, err
290317
}
291318

292319
buildCtx, err := parseContextNames(options.ExtendedBuildContext)
293320
if err != nil {
294-
return "", nil, false, "", nil, nil, err
321+
return result, err
295322
}
296323

297324
for k, v := range buildCtx {
@@ -306,7 +333,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
306333
if isOCILayout := strings.HasPrefix(v, "oci-layout://"); isOCILayout {
307334
args, err := parseBuildContextFromOCILayout(k, v)
308335
if err != nil {
309-
return "", nil, false, "", nil, nil, err
336+
return result, err
310337
}
311338

312339
buildctlArgs = append(buildctlArgs, args...)
@@ -315,7 +342,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
315342

316343
path, err := filepath.Abs(v)
317344
if err != nil {
318-
return "", nil, false, "", nil, nil, err
345+
return result, err
319346
}
320347
buildctlArgs = append(buildctlArgs, fmt.Sprintf("--local=%s=%s", k, path))
321348
buildctlArgs = append(buildctlArgs, fmt.Sprintf("--opt=context:%s=local:%s", k, k))
@@ -362,7 +389,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
362389
}
363390
}
364391
} else {
365-
return "", nil, false, "", nil, nil, fmt.Errorf("invalid build arg %q", ba)
392+
return result, fmt.Errorf("invalid build arg %q", ba)
366393
}
367394
}
368395

@@ -405,7 +432,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
405432
optAttestType := strings.TrimPrefix(optAttestType, "type=")
406433
buildctlArgs = append(buildctlArgs, fmt.Sprintf("--opt=attest:%s=%s", optAttestType, optAttestAttrs))
407434
} else {
408-
return "", nil, false, "", nil, nil, fmt.Errorf("attestation type not specified")
435+
return result, fmt.Errorf("attestation type not specified")
409436
}
410437
}
411438

@@ -434,11 +461,11 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
434461
if options.IidFile != "" {
435462
file, err := os.CreateTemp("", "buildkit-meta-*")
436463
if err != nil {
437-
return "", nil, false, "", nil, cleanup, err
464+
return result, err
438465
}
439466
defer file.Close()
440-
metaFile = file.Name()
441-
buildctlArgs = append(buildctlArgs, "--metadata-file="+metaFile)
467+
result.MetaFile = file.Name()
468+
buildctlArgs = append(buildctlArgs, "--metadata-file="+result.MetaFile)
442469
}
443470

444471
if options.NetworkMode != "" {
@@ -453,7 +480,9 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
453480
}
454481
}
455482

456-
return buildctlBinary, buildctlArgs, needsLoading, metaFile, tags, cleanup, nil
483+
result.BuildctlArgs = buildctlArgs
484+
485+
return result, nil
457486
}
458487

459488
func getDigestFromMetaFile(path string) (string, error) {

0 commit comments

Comments
 (0)