123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- package build // import "github.com/docker/docker/api/server/backend/build"
- import (
- "context"
- "fmt"
- "strconv"
- "github.com/distribution/reference"
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/backend"
- "github.com/docker/docker/api/types/events"
- "github.com/docker/docker/builder"
- buildkit "github.com/docker/docker/builder/builder-next"
- daemonevents "github.com/docker/docker/daemon/events"
- "github.com/docker/docker/image"
- "github.com/docker/docker/pkg/stringid"
- "github.com/pkg/errors"
- "google.golang.org/grpc"
- )
- // ImageComponent provides an interface for working with images
- type ImageComponent interface {
- SquashImage(from string, to string) (string, error)
- TagImage(context.Context, image.ID, reference.Named) error
- }
- // Builder defines interface for running a build
- type Builder interface {
- Build(context.Context, backend.BuildConfig) (*builder.Result, error)
- }
- // Backend provides build functionality to the API router
- type Backend struct {
- builder Builder
- imageComponent ImageComponent
- buildkit *buildkit.Builder
- eventsService *daemonevents.Events
- }
- // NewBackend creates a new build backend from components
- func NewBackend(components ImageComponent, builder Builder, buildkit *buildkit.Builder, es *daemonevents.Events) (*Backend, error) {
- return &Backend{imageComponent: components, builder: builder, buildkit: buildkit, eventsService: es}, nil
- }
- // RegisterGRPC registers buildkit controller to the grpc server.
- func (b *Backend) RegisterGRPC(s *grpc.Server) {
- if b.buildkit != nil {
- b.buildkit.RegisterGRPC(s)
- }
- }
- // Build builds an image from a Source
- func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string, error) {
- options := config.Options
- useBuildKit := options.Version == types.BuilderBuildKit
- tags, err := sanitizeRepoAndTags(options.Tags)
- if err != nil {
- return "", err
- }
- var build *builder.Result
- if useBuildKit {
- build, err = b.buildkit.Build(ctx, config)
- if err != nil {
- return "", err
- }
- } else {
- build, err = b.builder.Build(ctx, config)
- if err != nil {
- return "", err
- }
- }
- if build == nil {
- return "", nil
- }
- imageID := build.ImageID
- if options.Squash {
- if imageID, err = squashBuild(build, b.imageComponent); err != nil {
- return "", err
- }
- if config.ProgressWriter.AuxFormatter != nil {
- if err = config.ProgressWriter.AuxFormatter.Emit("moby.image.id", types.BuildResult{ID: imageID}); err != nil {
- return "", err
- }
- }
- }
- if !useBuildKit {
- stdout := config.ProgressWriter.StdoutFormatter
- fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
- }
- if imageID != "" && !useBuildKit {
- err = tagImages(ctx, b.imageComponent, config.ProgressWriter.StdoutFormatter, image.ID(imageID), tags)
- }
- return imageID, err
- }
- // PruneCache removes all cached build sources
- func (b *Backend) PruneCache(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) {
- buildCacheSize, cacheIDs, err := b.buildkit.Prune(ctx, opts)
- if err != nil {
- return nil, errors.Wrap(err, "failed to prune build cache")
- }
- b.eventsService.Log(events.ActionPrune, events.BuilderEventType, events.Actor{
- Attributes: map[string]string{
- "reclaimed": strconv.FormatInt(buildCacheSize, 10),
- },
- })
- return &types.BuildCachePruneReport{SpaceReclaimed: uint64(buildCacheSize), CachesDeleted: cacheIDs}, nil
- }
- // Cancel cancels the build by ID
- func (b *Backend) Cancel(ctx context.Context, id string) error {
- return b.buildkit.Cancel(ctx, id)
- }
- func squashBuild(build *builder.Result, imageComponent ImageComponent) (string, error) {
- var fromID string
- if build.FromImage != nil {
- fromID = build.FromImage.ImageID()
- }
- imageID, err := imageComponent.SquashImage(build.ImageID, fromID)
- if err != nil {
- return "", errors.Wrap(err, "error squashing image")
- }
- return imageID, nil
- }
|