github.com/rumpl/bof@v23.0.0-rc.2+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/docker/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 TagImageWithReference(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 tagger, err := NewTagger(b.imageComponent, config.ProgressWriter.StdoutFormatter, 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 var 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 != "" { 96 err = tagger.TagImages(image.ID(imageID)) 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("prune", 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 }