backend.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package build
  2. import (
  3. "fmt"
  4. "github.com/docker/distribution/reference"
  5. "github.com/docker/docker/api/types/backend"
  6. "github.com/docker/docker/builder"
  7. "github.com/docker/docker/builder/dockerfile"
  8. "github.com/docker/docker/image"
  9. "github.com/docker/docker/pkg/stringid"
  10. "github.com/pkg/errors"
  11. "golang.org/x/net/context"
  12. )
  13. // ImageComponent provides an interface for working with images
  14. type ImageComponent interface {
  15. SquashImage(from string, to string) (string, error)
  16. TagImageWithReference(image.ID, reference.Named) error
  17. }
  18. // Backend provides build functionality to the API router
  19. type Backend struct {
  20. manager *dockerfile.BuildManager
  21. imageComponent ImageComponent
  22. }
  23. // NewBackend creates a new build backend from components
  24. func NewBackend(components ImageComponent, builderBackend builder.Backend) *Backend {
  25. manager := dockerfile.NewBuildManager(builderBackend)
  26. return &Backend{imageComponent: components, manager: manager}
  27. }
  28. // Build builds an image from a Source
  29. func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string, error) {
  30. options := config.Options
  31. tagger, err := NewTagger(b.imageComponent, config.ProgressWriter.StdoutFormatter, options.Tags)
  32. if err != nil {
  33. return "", err
  34. }
  35. build, err := b.manager.Build(ctx, config)
  36. if err != nil {
  37. return "", err
  38. }
  39. var imageID = build.ImageID
  40. if options.Squash {
  41. if imageID, err = squashBuild(build, b.imageComponent); err != nil {
  42. return "", err
  43. }
  44. }
  45. stdout := config.ProgressWriter.StdoutFormatter
  46. fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
  47. err = tagger.TagImages(image.ID(imageID))
  48. return imageID, err
  49. }
  50. func squashBuild(build *builder.Result, imageComponent ImageComponent) (string, error) {
  51. var fromID string
  52. if build.FromImage != nil {
  53. fromID = build.FromImage.ImageID()
  54. }
  55. imageID, err := imageComponent.SquashImage(build.ImageID, fromID)
  56. if err != nil {
  57. return "", errors.Wrap(err, "error squashing image")
  58. }
  59. return imageID, nil
  60. }