backend.go 2.7 KB

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