Browse code

Merge pull request #5063 from vieux/force_rmi_stopped_container

docker rmi -f works with stopped containers + revamped error messages

Victor Vieux authored on 2014/05/03 08:41:13
Showing 1 changed files
... ...
@@ -24,19 +24,6 @@ package server
24 24
 import (
25 25
 	"encoding/json"
26 26
 	"fmt"
27
-	"github.com/dotcloud/docker/api"
28
-	"github.com/dotcloud/docker/archive"
29
-	"github.com/dotcloud/docker/daemon"
30
-	"github.com/dotcloud/docker/daemonconfig"
31
-	"github.com/dotcloud/docker/dockerversion"
32
-	"github.com/dotcloud/docker/engine"
33
-	"github.com/dotcloud/docker/graph"
34
-	"github.com/dotcloud/docker/image"
35
-	"github.com/dotcloud/docker/pkg/graphdb"
36
-	"github.com/dotcloud/docker/pkg/signal"
37
-	"github.com/dotcloud/docker/registry"
38
-	"github.com/dotcloud/docker/runconfig"
39
-	"github.com/dotcloud/docker/utils"
40 27
 	"io"
41 28
 	"io/ioutil"
42 29
 	"log"
... ...
@@ -53,6 +40,20 @@ import (
53 53
 	"sync"
54 54
 	"syscall"
55 55
 	"time"
56
+
57
+	"github.com/dotcloud/docker/api"
58
+	"github.com/dotcloud/docker/archive"
59
+	"github.com/dotcloud/docker/daemon"
60
+	"github.com/dotcloud/docker/daemonconfig"
61
+	"github.com/dotcloud/docker/dockerversion"
62
+	"github.com/dotcloud/docker/engine"
63
+	"github.com/dotcloud/docker/graph"
64
+	"github.com/dotcloud/docker/image"
65
+	"github.com/dotcloud/docker/pkg/graphdb"
66
+	"github.com/dotcloud/docker/pkg/signal"
67
+	"github.com/dotcloud/docker/registry"
68
+	"github.com/dotcloud/docker/runconfig"
69
+	"github.com/dotcloud/docker/utils"
56 70
 )
57 71
 
58 72
 // jobInitApi runs the remote api server `srv` as a daemon,
... ...
@@ -1953,6 +1954,7 @@ func (srv *Server) DeleteImage(name string, imgs *engine.Table, first, force, no
1953 1953
 	var (
1954 1954
 		repoName, tag string
1955 1955
 		tags          = []string{}
1956
+		tagDeleted    bool
1956 1957
 	)
1957 1958
 
1958 1959
 	repoName, tag = utils.ParseRepositoryTag(name)
... ...
@@ -2003,7 +2005,7 @@ func (srv *Server) DeleteImage(name string, imgs *engine.Table, first, force, no
2003 2003
 
2004 2004
 	//Untag the current image
2005 2005
 	for _, tag := range tags {
2006
-		tagDeleted, err := srv.daemon.Repositories().Delete(repoName, tag)
2006
+		tagDeleted, err = srv.daemon.Repositories().Delete(repoName, tag)
2007 2007
 		if err != nil {
2008 2008
 			return err
2009 2009
 		}
... ...
@@ -2017,7 +2019,7 @@ func (srv *Server) DeleteImage(name string, imgs *engine.Table, first, force, no
2017 2017
 	tags = srv.daemon.Repositories().ByID()[img.ID]
2018 2018
 	if (len(tags) <= 1 && repoName == "") || len(tags) == 0 {
2019 2019
 		if len(byParents[img.ID]) == 0 {
2020
-			if err := srv.canDeleteImage(img.ID); err != nil {
2020
+			if err := srv.canDeleteImage(img.ID, force, tagDeleted); err != nil {
2021 2021
 				return err
2022 2022
 			}
2023 2023
 			if err := srv.daemon.Repositories().DeleteAll(img.ID); err != nil {
... ...
@@ -2060,7 +2062,11 @@ func (srv *Server) ImageDelete(job *engine.Job) engine.Status {
2060 2060
 	return engine.StatusOK
2061 2061
 }
2062 2062
 
2063
-func (srv *Server) canDeleteImage(imgID string) error {
2063
+func (srv *Server) canDeleteImage(imgID string, force, untagged bool) error {
2064
+	var message string
2065
+	if untagged {
2066
+		message = " (docker untagged the image)"
2067
+	}
2064 2068
 	for _, container := range srv.daemon.List() {
2065 2069
 		parent, err := srv.daemon.Repositories().LookupImage(container.Image)
2066 2070
 		if err != nil {
... ...
@@ -2069,7 +2075,14 @@ func (srv *Server) canDeleteImage(imgID string) error {
2069 2069
 
2070 2070
 		if err := parent.WalkHistory(func(p *image.Image) error {
2071 2071
 			if imgID == p.ID {
2072
-				return fmt.Errorf("Conflict, cannot delete %s because the container %s is using it", utils.TruncateID(imgID), utils.TruncateID(container.ID))
2072
+				if container.State.IsRunning() {
2073
+					if force {
2074
+						return fmt.Errorf("Conflict, cannot force delete %s because the running container %s is using it%s, stop it and retry", utils.TruncateID(imgID), utils.TruncateID(container.ID), message)
2075
+					}
2076
+					return fmt.Errorf("Conflict, cannot delete %s because the running container %s is using it%s, stop it and use -f to force", utils.TruncateID(imgID), utils.TruncateID(container.ID), message)
2077
+				} else if !force {
2078
+					return fmt.Errorf("Conflict, cannot delete %s because the container %s is using it%s, use -f to force", utils.TruncateID(imgID), utils.TruncateID(container.ID), message)
2079
+				}
2073 2080
 			}
2074 2081
 			return nil
2075 2082
 		}); err != nil {