2017-04-13 14:37:32 -04:00
|
|
|
package build
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/docker/distribution/reference"
|
|
|
|
"github.com/docker/docker/api/types/backend"
|
|
|
|
"github.com/docker/docker/builder"
|
|
|
|
"github.com/docker/docker/builder/dockerfile"
|
|
|
|
"github.com/docker/docker/image"
|
2017-05-25 17:03:29 -04:00
|
|
|
"github.com/docker/docker/pkg/idtools"
|
2017-04-13 14:37:32 -04:00
|
|
|
"github.com/docker/docker/pkg/stringid"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
)
|
|
|
|
|
|
|
|
// ImageComponent provides an interface for working with images
|
|
|
|
type ImageComponent interface {
|
|
|
|
SquashImage(from string, to string) (string, error)
|
2017-05-16 19:56:56 -04:00
|
|
|
TagImageWithReference(image.ID, string, reference.Named) error
|
2017-04-13 14:37:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Backend provides build functionality to the API router
|
|
|
|
type Backend struct {
|
|
|
|
manager *dockerfile.BuildManager
|
|
|
|
imageComponent ImageComponent
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewBackend creates a new build backend from components
|
2017-05-15 15:59:15 -04:00
|
|
|
func NewBackend(components ImageComponent, builderBackend builder.Backend, sg dockerfile.SessionGetter, idMappings *idtools.IDMappings) (*Backend, error) {
|
|
|
|
manager := dockerfile.NewBuildManager(builderBackend, sg, idMappings)
|
|
|
|
return &Backend{imageComponent: components, manager: manager}, nil
|
2017-04-13 14:37:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Build builds an image from a Source
|
|
|
|
func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string, error) {
|
|
|
|
options := config.Options
|
|
|
|
tagger, err := NewTagger(b.imageComponent, config.ProgressWriter.StdoutFormatter, options.Tags)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
build, err := b.manager.Build(ctx, config)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
var imageID = build.ImageID
|
|
|
|
if options.Squash {
|
|
|
|
if imageID, err = squashBuild(build, b.imageComponent); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stdout := config.ProgressWriter.StdoutFormatter
|
|
|
|
fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
|
|
|
|
err = tagger.TagImages(image.ID(imageID))
|
|
|
|
return imageID, err
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|