github.com/containerd/nerdctl/v2@v2.0.0-beta.5.0.20240520001846-b5758f54fa28/pkg/composer/serviceparser/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 serviceparser
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"path/filepath"
    23  	"strings"
    24  
    25  	"github.com/compose-spec/compose-go/types"
    26  	"github.com/containerd/containerd/errdefs"
    27  	"github.com/containerd/containerd/identifiers"
    28  	"github.com/containerd/log"
    29  	"github.com/containerd/nerdctl/v2/pkg/reflectutil"
    30  
    31  	securejoin "github.com/cyphar/filepath-securejoin"
    32  )
    33  
    34  func parseBuildConfig(c *types.BuildConfig, project *types.Project, imageName string) (*Build, error) {
    35  	if unknown := reflectutil.UnknownNonEmptyFields(c,
    36  		"Context", "Dockerfile", "Args", "CacheFrom", "Target", "Labels", "Secrets",
    37  	); len(unknown) > 0 {
    38  		log.L.Warnf("Ignoring: build: %+v", unknown)
    39  	}
    40  
    41  	if c.Context == "" {
    42  		return nil, errors.New("build: context must be specified")
    43  	}
    44  	if strings.Contains(c.Context, "://") {
    45  		return nil, fmt.Errorf("build: URL-style context (%q) is not supported yet: %w", c.Context, errdefs.ErrNotImplemented)
    46  	}
    47  	ctxDir := project.RelativePath(c.Context)
    48  
    49  	var b Build
    50  	b.BuildArgs = append(b.BuildArgs, "-t="+imageName)
    51  	if c.Dockerfile != "" {
    52  		if filepath.IsAbs(c.Dockerfile) {
    53  			log.L.Warnf("build.dockerfile should be relative path, got %q", c.Dockerfile)
    54  			b.BuildArgs = append(b.BuildArgs, "-f="+c.Dockerfile)
    55  		} else {
    56  			// no need to use securejoin
    57  			dockerfile := filepath.Join(ctxDir, c.Dockerfile)
    58  			b.BuildArgs = append(b.BuildArgs, "-f="+dockerfile)
    59  		}
    60  	}
    61  
    62  	for k, v := range c.Args {
    63  		if v == nil {
    64  			b.BuildArgs = append(b.BuildArgs, "--build-arg="+k)
    65  		} else {
    66  			b.BuildArgs = append(b.BuildArgs, "--build-arg="+k+"="+*v)
    67  		}
    68  	}
    69  
    70  	for _, s := range c.CacheFrom {
    71  		b.BuildArgs = append(b.BuildArgs, "--cache-from="+s)
    72  	}
    73  
    74  	if c.Target != "" {
    75  		b.BuildArgs = append(b.BuildArgs, "--target="+c.Target)
    76  	}
    77  
    78  	if c.Labels != nil {
    79  		for k, v := range c.Labels {
    80  			b.BuildArgs = append(b.BuildArgs, "--label="+k+"="+v)
    81  		}
    82  	}
    83  
    84  	for _, s := range c.Secrets {
    85  		fileRef := types.FileReferenceConfig(s)
    86  		if err := identifiers.Validate(fileRef.Source); err != nil {
    87  			return nil, fmt.Errorf("secret source %q is invalid: %w", fileRef.Source, err)
    88  		}
    89  		projectSecret, ok := project.Secrets[fileRef.Source]
    90  		if !ok {
    91  			return nil, fmt.Errorf("build: secret %s is undefined", fileRef.Source)
    92  		}
    93  		var src string
    94  		if filepath.IsAbs(projectSecret.File) {
    95  			log.L.Warnf("build.secrets should be relative path, got %q", projectSecret.File)
    96  			src = projectSecret.File
    97  		} else {
    98  			var err error
    99  			src, err = securejoin.SecureJoin(ctxDir, projectSecret.File)
   100  			if err != nil {
   101  				return nil, err
   102  			}
   103  		}
   104  		id := fileRef.Source
   105  		if fileRef.Target != "" {
   106  			id = fileRef.Target
   107  		}
   108  		b.BuildArgs = append(b.BuildArgs, "--secret=id="+id+",src="+src)
   109  	}
   110  
   111  	b.BuildArgs = append(b.BuildArgs, ctxDir)
   112  	return &b, nil
   113  }