Browse code

Add rm option to docker build to remove intermediate containers

Michael Crosby authored on 2013/09/11 03:39:47
Showing 6 changed files
... ...
@@ -833,6 +833,7 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
833 833
 	repoName := r.FormValue("t")
834 834
 	rawSuppressOutput := r.FormValue("q")
835 835
 	rawNoCache := r.FormValue("nocache")
836
+	rawRm := r.FormValue("rm")
836 837
 	repoName, tag := utils.ParseRepositoryTag(repoName)
837 838
 
838 839
 	var context io.Reader
... ...
@@ -883,8 +884,12 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
883 883
 	if err != nil {
884 884
 		return err
885 885
 	}
886
+	rm, err := getBoolParam(rawRm)
887
+	if err != nil {
888
+		return err
889
+	}
886 890
 
887
-	b := NewBuildFile(srv, utils.NewWriteFlusher(w), !suppressOutput, !noCache)
891
+	b := NewBuildFile(srv, utils.NewWriteFlusher(w), !suppressOutput, !noCache, rm)
888 892
 	id, err := b.Build(context)
889 893
 	if err != nil {
890 894
 		fmt.Fprintf(w, "Error build: %s\n", err)
... ...
@@ -30,6 +30,7 @@ type buildFile struct {
30 30
 	context      string
31 31
 	verbose      bool
32 32
 	utilizeCache bool
33
+	rm           bool
33 34
 
34 35
 	tmpContainers map[string]struct{}
35 36
 	tmpImages     map[string]struct{}
... ...
@@ -37,15 +38,11 @@ type buildFile struct {
37 37
 	out io.Writer
38 38
 }
39 39
 
40
-func (b *buildFile) clearTmp(containers, images map[string]struct{}) {
40
+func (b *buildFile) clearTmp(containers map[string]struct{}) {
41 41
 	for c := range containers {
42 42
 		tmp := b.runtime.Get(c)
43 43
 		b.runtime.Destroy(tmp)
44
-		utils.Debugf("Removing container %s", c)
45
-	}
46
-	for i := range images {
47
-		b.runtime.graph.Delete(i)
48
-		utils.Debugf("Removing image %s", i)
44
+		fmt.Fprintf(b.out, "Removing intermediate container %s\n", utils.TruncateID(c))
49 45
 	}
50 46
 }
51 47
 
... ...
@@ -514,12 +511,15 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
514 514
 	}
515 515
 	if b.image != "" {
516 516
 		fmt.Fprintf(b.out, "Successfully built %s\n", utils.TruncateID(b.image))
517
+		if b.rm {
518
+			b.clearTmp(b.tmpContainers)
519
+		}
517 520
 		return b.image, nil
518 521
 	}
519 522
 	return "", fmt.Errorf("An error occurred during the build\n")
520 523
 }
521 524
 
522
-func NewBuildFile(srv *Server, out io.Writer, verbose, utilizeCache bool) BuildFile {
525
+func NewBuildFile(srv *Server, out io.Writer, verbose, utilizeCache, rm bool) BuildFile {
523 526
 	return &buildFile{
524 527
 		runtime:       srv.runtime,
525 528
 		srv:           srv,
... ...
@@ -529,5 +529,6 @@ func NewBuildFile(srv *Server, out io.Writer, verbose, utilizeCache bool) BuildF
529 529
 		tmpImages:     make(map[string]struct{}),
530 530
 		verbose:       verbose,
531 531
 		utilizeCache:  utilizeCache,
532
+		rm:            rm,
532 533
 	}
533 534
 }
... ...
@@ -257,7 +257,7 @@ func buildImage(context testContextTemplate, t *testing.T, srv *Server, useCache
257 257
 	ip := srv.runtime.networkManager.bridgeNetwork.IP
258 258
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
259 259
 
260
-	buildfile := NewBuildFile(srv, ioutil.Discard, false, useCache)
260
+	buildfile := NewBuildFile(srv, ioutil.Discard, false, useCache, false)
261 261
 	id, err := buildfile.Build(mkTestContext(dockerfile, context.files, t))
262 262
 	if err != nil {
263 263
 		t.Fatal(err)
... ...
@@ -498,7 +498,7 @@ func TestForbiddenContextPath(t *testing.T) {
498 498
 	ip := srv.runtime.networkManager.bridgeNetwork.IP
499 499
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
500 500
 
501
-	buildfile := NewBuildFile(srv, ioutil.Discard, false, true)
501
+	buildfile := NewBuildFile(srv, ioutil.Discard, false, true, false)
502 502
 	_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
503 503
 
504 504
 	if err == nil {
... ...
@@ -546,7 +546,7 @@ func TestBuildADDFileNotFound(t *testing.T) {
546 546
 	ip := srv.runtime.networkManager.bridgeNetwork.IP
547 547
 	dockerfile := constructDockerfile(context.dockerfile, ip, port)
548 548
 
549
-	buildfile := NewBuildFile(srv, ioutil.Discard, false, true)
549
+	buildfile := NewBuildFile(srv, ioutil.Discard, false, true, false)
550 550
 	_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
551 551
 
552 552
 	if err == nil {
... ...
@@ -165,6 +165,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
165 165
 	tag := cmd.String("t", "", "Repository name (and optionally a tag) to be applied to the resulting image in case of success")
166 166
 	suppressOutput := cmd.Bool("q", false, "Suppress verbose build output")
167 167
 	noCache := cmd.Bool("no-cache", false, "Do not use cache when building the image")
168
+	rm := cmd.Bool("rm", false, "Remove intermediate containers after a successful build")
168 169
 	if err := cmd.Parse(args); err != nil {
169 170
 		return nil
170 171
 	}
... ...
@@ -215,6 +216,9 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
215 215
 	if *noCache {
216 216
 		v.Set("nocache", "1")
217 217
 	}
218
+	if *rm {
219
+		v.Set("rm", "1")
220
+	}
218 221
 	req, err := http.NewRequest("POST", fmt.Sprintf("/v%g/build?%s", APIVERSION, v.Encode()), body)
219 222
 	if err != nil {
220 223
 		return err
... ...
@@ -976,6 +976,7 @@ Build an image from Dockerfile via stdin
976 976
 	:query t: repository name (and optionally a tag) to be applied to the resulting image in case of success
977 977
 	:query q: suppress verbose build output
978 978
     :query nocache: do not use the cache when building the image
979
+    :query rm: remove intermediate containers after a successful build
979 980
 	:statuscode 200: no error
980 981
     :statuscode 500: server error
981 982
 
... ...
@@ -13,6 +13,7 @@
13 13
       -t="": Repository name (and optionally a tag) to be applied to the resulting image in case of success.
14 14
       -q=false: Suppress verbose build output.
15 15
       -no-cache: Do not use the cache when building the image.
16
+      -rm: Remove intermediate containers after a successful build
16 17
     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
17 18
 
18 19