Browse code

Fix docker rmi trying to remove a being used parent

Signed-off-by: Lei Jitang <leijitang@huawei.com>

Lei Jitang authored on 2015/11/26 10:57:20
Showing 3 changed files
... ...
@@ -195,6 +195,7 @@ func (daemon *Daemon) removeAllReferencesToImageID(imgID image.ID, records *[]ty
195 195
 // Implements the error interface.
196 196
 type imageDeleteConflict struct {
197 197
 	hard    bool
198
+	used    bool
198 199
 	imgID   image.ID
199 200
 	message string
200 201
 }
... ...
@@ -225,8 +226,8 @@ func (daemon *Daemon) imageDeleteHelper(imgID image.ID, records *[]types.ImageDe
225 225
 	// First, determine if this image has any conflicts. Ignore soft conflicts
226 226
 	// if force is true.
227 227
 	if conflict := daemon.checkImageDeleteConflict(imgID, force); conflict != nil {
228
-		if quiet && !daemon.imageIsDangling(imgID) {
229
-			// Ignore conflicts UNLESS the image is "dangling" in
228
+		if quiet && (!daemon.imageIsDangling(imgID) || conflict.used) {
229
+			// Ignore conflicts UNLESS the image is "dangling" or not being used in
230 230
 			// which case we want the user to know.
231 231
 			return nil
232 232
 		}
... ...
@@ -312,6 +313,7 @@ func (daemon *Daemon) checkImageDeleteHardConflict(imgID image.ID) *imageDeleteC
312 312
 			return &imageDeleteConflict{
313 313
 				imgID:   imgID,
314 314
 				hard:    true,
315
+				used:    true,
315 316
 				message: fmt.Sprintf("image is being used by running container %s", stringid.TruncateID(container.ID)),
316 317
 			}
317 318
 		}
... ...
@@ -339,6 +341,7 @@ func (daemon *Daemon) checkImageDeleteSoftConflict(imgID image.ID) *imageDeleteC
339 339
 		if container.ImageID == imgID {
340 340
 			return &imageDeleteConflict{
341 341
 				imgID:   imgID,
342
+				used:    true,
342 343
 				message: fmt.Sprintf("image is being used by stopped container %s", stringid.TruncateID(container.ID)),
343 344
 			}
344 345
 		}
... ...
@@ -60,9 +60,9 @@ func (s *DockerSuite) TestRmContainerOrphaning(c *check.C) {
60 60
 	// rebuild dockerfile with a small addition at the end
61 61
 	_, err = buildImage(img, dockerfile2, true)
62 62
 	c.Assert(err, check.IsNil, check.Commentf("Could not rebuild image %s", img))
63
-	// try to remove the image, should error out.
63
+	// try to remove the image, should not error out.
64 64
 	out, _, err := dockerCmdWithError("rmi", img)
65
-	c.Assert(err, check.NotNil, check.Commentf("Expected to error out removing the image, but succeeded: %s", out))
65
+	c.Assert(err, check.IsNil, check.Commentf("Expected to removing the image, but failed: %s", out))
66 66
 
67 67
 	// check if we deleted the first image
68 68
 	out, _ = dockerCmd(c, "images", "-q", "--no-trunc")
... ...
@@ -322,3 +322,18 @@ func (*DockerSuite) TestRmiParentImageFail(c *check.C) {
322 322
 		c.Fatalf("rmi should have failed because it's a parent image, got %s", out)
323 323
 	}
324 324
 }
325
+
326
+func (s *DockerSuite) TestRmiWithParentInUse(c *check.C) {
327
+	testRequires(c, DaemonIsLinux)
328
+	out, _ := dockerCmd(c, "create", "busybox")
329
+	cID := strings.TrimSpace(out)
330
+	out, _ = dockerCmd(c, "commit", cID)
331
+	imageID := strings.TrimSpace(out)
332
+
333
+	out, _ = dockerCmd(c, "create", imageID)
334
+	cID = strings.TrimSpace(out)
335
+	out, _ = dockerCmd(c, "commit", cID)
336
+	imageID = strings.TrimSpace(out)
337
+
338
+	dockerCmd(c, "rmi", imageID)
339
+}