Merge pull request #1848 from dotcloud/build-clean

Add rm option to docker build to remove intermediate containers
This commit is contained in:
Michael Crosby 2013-09-13 10:58:59 -07:00
commit 33972627b7
7 changed files with 24 additions and 12 deletions

7
api.go
View file

@ -833,6 +833,7 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
repoName := r.FormValue("t")
rawSuppressOutput := r.FormValue("q")
rawNoCache := r.FormValue("nocache")
rawRm := r.FormValue("rm")
repoName, tag := utils.ParseRepositoryTag(repoName)
var context io.Reader
@ -883,8 +884,12 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
if err != nil {
return err
}
rm, err := getBoolParam(rawRm)
if err != nil {
return err
}
b := NewBuildFile(srv, utils.NewWriteFlusher(w), !suppressOutput, !noCache)
b := NewBuildFile(srv, utils.NewWriteFlusher(w), !suppressOutput, !noCache, rm)
id, err := b.Build(context)
if err != nil {
fmt.Fprintf(w, "Error build: %s\n", err)

View file

@ -30,6 +30,7 @@ type buildFile struct {
context string
verbose bool
utilizeCache bool
rm bool
tmpContainers map[string]struct{}
tmpImages map[string]struct{}
@ -37,15 +38,11 @@ type buildFile struct {
out io.Writer
}
func (b *buildFile) clearTmp(containers, images map[string]struct{}) {
func (b *buildFile) clearTmp(containers map[string]struct{}) {
for c := range containers {
tmp := b.runtime.Get(c)
b.runtime.Destroy(tmp)
utils.Debugf("Removing container %s", c)
}
for i := range images {
b.runtime.graph.Delete(i)
utils.Debugf("Removing image %s", i)
fmt.Fprintf(b.out, "Removing intermediate container %s\n", utils.TruncateID(c))
}
}
@ -514,12 +511,15 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
}
if b.image != "" {
fmt.Fprintf(b.out, "Successfully built %s\n", utils.TruncateID(b.image))
if b.rm {
b.clearTmp(b.tmpContainers)
}
return b.image, nil
}
return "", fmt.Errorf("An error occurred during the build\n")
}
func NewBuildFile(srv *Server, out io.Writer, verbose, utilizeCache bool) BuildFile {
func NewBuildFile(srv *Server, out io.Writer, verbose, utilizeCache, rm bool) BuildFile {
return &buildFile{
runtime: srv.runtime,
srv: srv,
@ -529,5 +529,6 @@ func NewBuildFile(srv *Server, out io.Writer, verbose, utilizeCache bool) BuildF
tmpImages: make(map[string]struct{}),
verbose: verbose,
utilizeCache: utilizeCache,
rm: rm,
}
}

View file

@ -257,7 +257,7 @@ func buildImage(context testContextTemplate, t *testing.T, srv *Server, useCache
ip := srv.runtime.networkManager.bridgeNetwork.IP
dockerfile := constructDockerfile(context.dockerfile, ip, port)
buildfile := NewBuildFile(srv, ioutil.Discard, false, useCache)
buildfile := NewBuildFile(srv, ioutil.Discard, false, useCache, false)
id, err := buildfile.Build(mkTestContext(dockerfile, context.files, t))
if err != nil {
t.Fatal(err)
@ -498,7 +498,7 @@ func TestForbiddenContextPath(t *testing.T) {
ip := srv.runtime.networkManager.bridgeNetwork.IP
dockerfile := constructDockerfile(context.dockerfile, ip, port)
buildfile := NewBuildFile(srv, ioutil.Discard, false, true)
buildfile := NewBuildFile(srv, ioutil.Discard, false, true, false)
_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
if err == nil {
@ -546,7 +546,7 @@ func TestBuildADDFileNotFound(t *testing.T) {
ip := srv.runtime.networkManager.bridgeNetwork.IP
dockerfile := constructDockerfile(context.dockerfile, ip, port)
buildfile := NewBuildFile(srv, ioutil.Discard, false, true)
buildfile := NewBuildFile(srv, ioutil.Discard, false, true, false)
_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
if err == nil {

View file

@ -165,6 +165,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
tag := cmd.String("t", "", "Repository name (and optionally a tag) to be applied to the resulting image in case of success")
suppressOutput := cmd.Bool("q", false, "Suppress verbose build output")
noCache := cmd.Bool("no-cache", false, "Do not use cache when building the image")
rm := cmd.Bool("rm", false, "Remove intermediate containers after a successful build")
if err := cmd.Parse(args); err != nil {
return nil
}
@ -215,6 +216,9 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
if *noCache {
v.Set("nocache", "1")
}
if *rm {
v.Set("rm", "1")
}
req, err := http.NewRequest("POST", fmt.Sprintf("/v%g/build?%s", APIVERSION, v.Encode()), body)
if err != nil {
return err

View file

@ -114,7 +114,7 @@ _docker_build()
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "-no-cache -t -q" -- "$cur" ) )
COMPREPLY=( $( compgen -W "-no-cache -t -q -rm" -- "$cur" ) )
;;
*)
_filedir

View file

@ -976,6 +976,7 @@ Build an image from Dockerfile via stdin
:query t: repository name (and optionally a tag) to be applied to the resulting image in case of success
:query q: suppress verbose build output
:query nocache: do not use the cache when building the image
:query rm: remove intermediate containers after a successful build
:statuscode 200: no error
:statuscode 500: server error

View file

@ -13,6 +13,7 @@
-t="": Repository name (and optionally a tag) to be applied to the resulting image in case of success.
-q=false: Suppress verbose build output.
-no-cache: Do not use the cache when building the image.
-rm: Remove intermediate containers after a successful build
When a single Dockerfile is given as URL, then no context is set. When a git repository is set as URL, the repository is used as context