in targets/windows/handle_container.go [40:194]
func handleContainer(ctx context.Context, client gwclient.Client) (*gwclient.Result, error) {
dc, err := dockerui.NewClient(client)
if err != nil {
return nil, err
}
if len(dc.TargetPlatforms) > 1 {
return nil, fmt.Errorf("multi-platform output is not supported")
}
sOpt := frontend.SourceOptFromUIClient(ctx, client, dc, nil)
spec, err := frontend.LoadSpec(ctx, dc, nil)
if err != nil {
return nil, err
}
targetKey := frontend.GetTargetKey(client)
bases := spec.GetImageBases(targetKey)
if len(bases) == 0 {
bases = append(bases, dalec.BaseImage{
Rootfs: dalec.Source{
DockerImage: &dalec.SourceDockerImage{Ref: defaultBaseImage},
},
})
}
eg, grpCtx := errgroup.WithContext(ctx)
var mu sync.Mutex
cfgs := make([][]byte, len(bases))
targets := make([]ocispecs.Platform, len(cfgs))
basePlatform := defaultPlatform
if len(dc.TargetPlatforms) > 0 {
basePlatform = dc.TargetPlatforms[0]
}
for idx, bi := range bases {
idx := idx
bi := bi
eg.Go(func() error {
dt, err := bi.ResolveImageConfig(grpCtx, sOpt, sourceresolver.Opt{
Platform: &basePlatform,
ImageOpt: &sourceresolver.ResolveImageOpt{
ResolveMode: dc.ImageResolveMode.String(),
},
})
if err != nil {
return err
}
var cfg dalec.DockerImageSpec
if err := json.Unmarshal(dt, &cfg); err != nil {
return errors.Wrapf(err, "error unmarshalling base image config for base image at index %d", idx)
}
mu.Lock()
cfgs[idx] = dt
targets[idx] = cfg.Platform
mu.Unlock()
return nil
})
}
if err := eg.Wait(); err != nil {
return nil, err
}
seen := make(map[string]struct{})
for _, p := range targets {
s := platforms.FormatAll(p)
if _, ok := seen[s]; ok {
return nil, fmt.Errorf("multiple base images provided with the same platform value")
}
seen[s] = struct{}{}
}
dc.TargetPlatforms = targets
if len(targets) > 1 {
dc.MultiPlatformRequested = true
}
rb, err := dc.Build(ctx, func(ctx context.Context, platform *ocispecs.Platform, idx int) (ref gwclient.Reference, retCfg, retBaseCfg *dalec.DockerImageSpec, retErr error) {
spec, err := frontend.LoadSpec(ctx, dc, platform)
if err != nil {
return nil, nil, nil, err
}
if err := validateRuntimeDeps(spec, targetKey); err != nil {
return nil, nil, nil, fmt.Errorf("error validating windows spec: %w", err)
}
pg := dalec.ProgressGroup("Build windows container: " + spec.Name)
worker, err := distroConfig.Worker(sOpt, pg)
if err != nil {
return nil, nil, nil, err
}
bin, err := buildBinaries(ctx, spec, worker, client, sOpt, targetKey)
if err != nil {
return nil, nil, nil, fmt.Errorf("unable to build binary %w", err)
}
bi := bases[idx]
if platform == nil {
platform = &defaultPlatform
}
baseImage, err := bi.ToState(sOpt, pg, llb.Platform(*platform))
if err != nil {
return nil, nil, nil, err
}
out := baseImage.
File(llb.Copy(bin, "/", windowsSystemDir)).
With(copySymlinks(spec.GetImagePost(targetKey)))
def, err := out.Marshal(ctx)
if err != nil {
return nil, nil, nil, err
}
res, err := client.Solve(ctx, gwclient.SolveRequest{
Definition: def.ToPB(),
})
if err != nil {
return nil, nil, nil, err
}
dt := cfgs[idx]
var baseCfg dalec.DockerImageSpec
if err := json.Unmarshal(cfgs[idx], &baseCfg); err != nil {
return nil, nil, nil, errors.Wrap(err, "error unmarshalling base image config")
}
var img dalec.DockerImageSpec
if err := json.Unmarshal(dt, &img); err != nil {
return nil, nil, nil, errors.Wrap(err, "error unmarshalling base image config")
}
if err := dalec.BuildImageConfig(spec, targetKey, &img); err != nil {
return nil, nil, nil, errors.Wrap(err, "error creating image config")
}
ref, err = res.SingleRef()
return ref, &img, &baseCfg, err
})
if err != nil {
return nil, err
}
return rb.Finalize()
}