github.com/cookieai-jar/moby@v17.12.1-ce-rc2+incompatible/api/server/backend/build/backend.go (about) 1 package build 2 3 import ( 4 "fmt" 5 6 "github.com/docker/distribution/reference" 7 "github.com/docker/docker/api/types" 8 "github.com/docker/docker/api/types/backend" 9 "github.com/docker/docker/builder" 10 "github.com/docker/docker/builder/fscache" 11 "github.com/docker/docker/image" 12 "github.com/docker/docker/pkg/stringid" 13 "github.com/pkg/errors" 14 "golang.org/x/net/context" 15 ) 16 17 // ImageComponent provides an interface for working with images 18 type ImageComponent interface { 19 SquashImage(from string, to string) (string, error) 20 TagImageWithReference(image.ID, string, reference.Named) error 21 } 22 23 // Builder defines interface for running a build 24 type Builder interface { 25 Build(context.Context, backend.BuildConfig) (*builder.Result, error) 26 } 27 28 // Backend provides build functionality to the API router 29 type Backend struct { 30 builder Builder 31 fsCache *fscache.FSCache 32 imageComponent ImageComponent 33 } 34 35 // NewBackend creates a new build backend from components 36 func NewBackend(components ImageComponent, builder Builder, fsCache *fscache.FSCache) (*Backend, error) { 37 return &Backend{imageComponent: components, builder: builder, fsCache: fsCache}, nil 38 } 39 40 // Build builds an image from a Source 41 func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string, error) { 42 options := config.Options 43 tagger, err := NewTagger(b.imageComponent, config.ProgressWriter.StdoutFormatter, options.Tags) 44 if err != nil { 45 return "", err 46 } 47 48 build, err := b.builder.Build(ctx, config) 49 if err != nil { 50 return "", err 51 } 52 53 var imageID = build.ImageID 54 if options.Squash { 55 if imageID, err = squashBuild(build, b.imageComponent); err != nil { 56 return "", err 57 } 58 if config.ProgressWriter.AuxFormatter != nil { 59 if err = config.ProgressWriter.AuxFormatter.Emit(types.BuildResult{ID: imageID}); err != nil { 60 return "", err 61 } 62 } 63 } 64 65 stdout := config.ProgressWriter.StdoutFormatter 66 fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID)) 67 err = tagger.TagImages(image.ID(imageID)) 68 return imageID, err 69 } 70 71 // PruneCache removes all cached build sources 72 func (b *Backend) PruneCache(ctx context.Context) (*types.BuildCachePruneReport, error) { 73 size, err := b.fsCache.Prune(ctx) 74 if err != nil { 75 return nil, errors.Wrap(err, "failed to prune build cache") 76 } 77 return &types.BuildCachePruneReport{SpaceReclaimed: size}, nil 78 } 79 80 func squashBuild(build *builder.Result, imageComponent ImageComponent) (string, error) { 81 var fromID string 82 if build.FromImage != nil { 83 fromID = build.FromImage.ImageID() 84 } 85 imageID, err := imageComponent.SquashImage(build.ImageID, fromID) 86 if err != nil { 87 return "", errors.Wrap(err, "error squashing image") 88 } 89 return imageID, nil 90 }