This repository has been archived by the owner on Jan 20, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract squash and tagging from the Dockerfile builder.
Remove pathCache and replace it with syncmap Cleanup NewBuilder Create an api/server/backend/build Extract BuildTagger Signed-off-by: Daniel Nephin <dnephin@docker.com>
- Loading branch information
Showing
15 changed files
with
337 additions
and
259 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
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" | ||
"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) | ||
TagImageWithReference(image.ID, reference.Named) error | ||
} | ||
|
||
// Backend provides build functionality to the API router | ||
type Backend struct { | ||
manager *dockerfile.BuildManager | ||
imageComponent ImageComponent | ||
} | ||
|
||
// NewBackend creates a new build backend from components | ||
func NewBackend(components ImageComponent, builderBackend builder.Backend) *Backend { | ||
manager := dockerfile.NewBuildManager(builderBackend) | ||
return &Backend{imageComponent: components, manager: manager} | ||
} | ||
|
||
// 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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package build | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
|
||
"github.com/docker/distribution/reference" | ||
"github.com/docker/docker/image" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
// Tagger is responsible for tagging an image created by a builder | ||
type Tagger struct { | ||
imageComponent ImageComponent | ||
stdout io.Writer | ||
repoAndTags []reference.Named | ||
} | ||
|
||
// NewTagger returns a new Tagger for tagging the images of a build. | ||
// If any of the names are invalid tags an error is returned. | ||
func NewTagger(backend ImageComponent, stdout io.Writer, names []string) (*Tagger, error) { | ||
reposAndTags, err := sanitizeRepoAndTags(names) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &Tagger{ | ||
imageComponent: backend, | ||
stdout: stdout, | ||
repoAndTags: reposAndTags, | ||
}, nil | ||
} | ||
|
||
// TagImages creates image tags for the imageID | ||
func (bt *Tagger) TagImages(imageID image.ID) error { | ||
for _, rt := range bt.repoAndTags { | ||
if err := bt.imageComponent.TagImageWithReference(imageID, rt); err != nil { | ||
return err | ||
} | ||
fmt.Fprintf(bt.stdout, "Successfully tagged %s\n", reference.FamiliarString(rt)) | ||
} | ||
return nil | ||
} | ||
|
||
// sanitizeRepoAndTags parses the raw "t" parameter received from the client | ||
// to a slice of repoAndTag. | ||
// It also validates each repoName and tag. | ||
func sanitizeRepoAndTags(names []string) ([]reference.Named, error) { | ||
var ( | ||
repoAndTags []reference.Named | ||
// This map is used for deduplicating the "-t" parameter. | ||
uniqNames = make(map[string]struct{}) | ||
) | ||
for _, repo := range names { | ||
if repo == "" { | ||
continue | ||
} | ||
|
||
ref, err := reference.ParseNormalizedNamed(repo) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if _, isCanonical := ref.(reference.Canonical); isCanonical { | ||
return nil, errors.New("build tag cannot contain a digest") | ||
} | ||
|
||
ref = reference.TagNameOnly(ref) | ||
|
||
nameWithTag := ref.String() | ||
|
||
if _, exists := uniqNames[nameWithTag]; !exists { | ||
uniqNames[nameWithTag] = struct{}{} | ||
repoAndTags = append(repoAndTags, ref) | ||
} | ||
} | ||
return repoAndTags, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,17 @@ | ||
package build | ||
|
||
import ( | ||
"io" | ||
|
||
"github.com/docker/docker/api/types" | ||
"github.com/docker/docker/api/types/backend" | ||
"golang.org/x/net/context" | ||
) | ||
|
||
// Backend abstracts an image builder whose only purpose is to build an image referenced by an imageID. | ||
type Backend interface { | ||
// BuildFromContext builds a Docker image referenced by an imageID string. | ||
// | ||
// Note: Tagging an image should not be done by a Builder, it should instead be done | ||
// by the caller. | ||
// | ||
// Build a Docker image returning the id of the image | ||
// TODO: make this return a reference instead of string | ||
BuildFromContext(ctx context.Context, src io.ReadCloser, buildOptions *types.ImageBuildOptions, pg backend.ProgressWriter) (string, error) | ||
Build(context.Context, backend.BuildConfig) (string, error) | ||
} | ||
|
||
type experimentalProvider interface { | ||
HasExperimental() bool | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.