github.com/khulnasoft-lab/khulnasoft@v26.0.1-0.20240328202558-330a6f959fe0+incompatible/api/server/backend/build/backend.go (about)

     1  package build // import "github.com/docker/docker/api/server/backend/build"
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strconv"
     7  
     8  	"github.com/distribution/reference"
     9  	"github.com/docker/docker/api/types"
    10  	"github.com/docker/docker/api/types/backend"
    11  	"github.com/docker/docker/api/types/events"
    12  	"github.com/docker/docker/builder"
    13  	buildkit "github.com/docker/docker/builder/builder-next"
    14  	daemonevents "github.com/docker/docker/daemon/events"
    15  	"github.com/docker/docker/image"
    16  	"github.com/docker/docker/pkg/stringid"
    17  	"github.com/pkg/errors"
    18  	"google.golang.org/grpc"
    19  )
    20  
    21  // ImageComponent provides an interface for working with images
    22  type ImageComponent interface {
    23  	SquashImage(from string, to string) (string, error)
    24  	TagImage(context.Context, image.ID, reference.Named) error
    25  }
    26  
    27  // Builder defines interface for running a build
    28  type Builder interface {
    29  	Build(context.Context, backend.BuildConfig) (*builder.Result, error)
    30  }
    31  
    32  // Backend provides build functionality to the API router
    33  type Backend struct {
    34  	builder        Builder
    35  	imageComponent ImageComponent
    36  	buildkit       *buildkit.Builder
    37  	eventsService  *daemonevents.Events
    38  }
    39  
    40  // NewBackend creates a new build backend from components
    41  func NewBackend(components ImageComponent, builder Builder, buildkit *buildkit.Builder, es *daemonevents.Events) (*Backend, error) {
    42  	return &Backend{imageComponent: components, builder: builder, buildkit: buildkit, eventsService: es}, nil
    43  }
    44  
    45  // RegisterGRPC registers buildkit controller to the grpc server.
    46  func (b *Backend) RegisterGRPC(s *grpc.Server) {
    47  	if b.buildkit != nil {
    48  		b.buildkit.RegisterGRPC(s)
    49  	}
    50  }
    51  
    52  // Build builds an image from a Source
    53  func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string, error) {
    54  	options := config.Options
    55  	useBuildKit := options.Version == types.BuilderBuildKit
    56  
    57  	tags, err := sanitizeRepoAndTags(options.Tags)
    58  	if err != nil {
    59  		return "", err
    60  	}
    61  
    62  	var build *builder.Result
    63  	if useBuildKit {
    64  		build, err = b.buildkit.Build(ctx, config)
    65  		if err != nil {
    66  			return "", err
    67  		}
    68  	} else {
    69  		build, err = b.builder.Build(ctx, config)
    70  		if err != nil {
    71  			return "", err
    72  		}
    73  	}
    74  
    75  	if build == nil {
    76  		return "", nil
    77  	}
    78  
    79  	imageID := build.ImageID
    80  	if options.Squash {
    81  		if imageID, err = squashBuild(build, b.imageComponent); err != nil {
    82  			return "", err
    83  		}
    84  		if config.ProgressWriter.AuxFormatter != nil {
    85  			if err = config.ProgressWriter.AuxFormatter.Emit("moby.image.id", types.BuildResult{ID: imageID}); err != nil {
    86  				return "", err
    87  			}
    88  		}
    89  	}
    90  
    91  	if !useBuildKit {
    92  		stdout := config.ProgressWriter.StdoutFormatter
    93  		fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
    94  	}
    95  	if imageID != "" && !useBuildKit {
    96  		err = tagImages(ctx, b.imageComponent, config.ProgressWriter.StdoutFormatter, image.ID(imageID), tags)
    97  	}
    98  	return imageID, err
    99  }
   100  
   101  // PruneCache removes all cached build sources
   102  func (b *Backend) PruneCache(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) {
   103  	buildCacheSize, cacheIDs, err := b.buildkit.Prune(ctx, opts)
   104  	if err != nil {
   105  		return nil, errors.Wrap(err, "failed to prune build cache")
   106  	}
   107  	b.eventsService.Log(events.ActionPrune, events.BuilderEventType, events.Actor{
   108  		Attributes: map[string]string{
   109  			"reclaimed": strconv.FormatInt(buildCacheSize, 10),
   110  		},
   111  	})
   112  	return &types.BuildCachePruneReport{SpaceReclaimed: uint64(buildCacheSize), CachesDeleted: cacheIDs}, nil
   113  }
   114  
   115  // Cancel cancels the build by ID
   116  func (b *Backend) Cancel(ctx context.Context, id string) error {
   117  	return b.buildkit.Cancel(ctx, id)
   118  }
   119  
   120  func squashBuild(build *builder.Result, imageComponent ImageComponent) (string, error) {
   121  	var fromID string
   122  	if build.FromImage != nil {
   123  		fromID = build.FromImage.ImageID()
   124  	}
   125  	imageID, err := imageComponent.SquashImage(build.ImageID, fromID)
   126  	if err != nil {
   127  		return "", errors.Wrap(err, "error squashing image")
   128  	}
   129  	return imageID, nil
   130  }