github.com/ruphin/docker@v1.10.1/integration-cli/docker_cli_rmi_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os/exec"
     6  	"strings"
     7  
     8  	"github.com/docker/docker/pkg/integration/checker"
     9  	"github.com/docker/docker/pkg/stringid"
    10  	"github.com/go-check/check"
    11  )
    12  
    13  func (s *DockerSuite) TestRmiWithContainerFails(c *check.C) {
    14  	testRequires(c, DaemonIsLinux)
    15  	errSubstr := "is using it"
    16  
    17  	// create a container
    18  	out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
    19  
    20  	cleanedContainerID := strings.TrimSpace(out)
    21  
    22  	// try to delete the image
    23  	out, _, err := dockerCmdWithError("rmi", "busybox")
    24  	// Container is using image, should not be able to rmi
    25  	c.Assert(err, checker.NotNil)
    26  	// Container is using image, error message should contain errSubstr
    27  	c.Assert(out, checker.Contains, errSubstr, check.Commentf("Container: %q", cleanedContainerID))
    28  
    29  	// make sure it didn't delete the busybox name
    30  	images, _ := dockerCmd(c, "images")
    31  	// The name 'busybox' should not have been removed from images
    32  	c.Assert(images, checker.Contains, "busybox")
    33  }
    34  
    35  func (s *DockerSuite) TestRmiTag(c *check.C) {
    36  	testRequires(c, DaemonIsLinux)
    37  	imagesBefore, _ := dockerCmd(c, "images", "-a")
    38  	dockerCmd(c, "tag", "busybox", "utest:tag1")
    39  	dockerCmd(c, "tag", "busybox", "utest/docker:tag2")
    40  	dockerCmd(c, "tag", "busybox", "utest:5000/docker:tag3")
    41  	{
    42  		imagesAfter, _ := dockerCmd(c, "images", "-a")
    43  		c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+3, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
    44  	}
    45  	dockerCmd(c, "rmi", "utest/docker:tag2")
    46  	{
    47  		imagesAfter, _ := dockerCmd(c, "images", "-a")
    48  		c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+2, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
    49  	}
    50  	dockerCmd(c, "rmi", "utest:5000/docker:tag3")
    51  	{
    52  		imagesAfter, _ := dockerCmd(c, "images", "-a")
    53  		c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+1, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
    54  
    55  	}
    56  	dockerCmd(c, "rmi", "utest:tag1")
    57  	{
    58  		imagesAfter, _ := dockerCmd(c, "images", "-a")
    59  		c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n"), check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
    60  
    61  	}
    62  }
    63  
    64  func (s *DockerSuite) TestRmiImgIDMultipleTag(c *check.C) {
    65  	testRequires(c, DaemonIsLinux)
    66  	out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-one'")
    67  
    68  	containerID := strings.TrimSpace(out)
    69  	dockerCmd(c, "commit", containerID, "busybox-one")
    70  
    71  	imagesBefore, _ := dockerCmd(c, "images", "-a")
    72  	dockerCmd(c, "tag", "busybox-one", "busybox-one:tag1")
    73  	dockerCmd(c, "tag", "busybox-one", "busybox-one:tag2")
    74  
    75  	imagesAfter, _ := dockerCmd(c, "images", "-a")
    76  	// tag busybox to create 2 more images with same imageID
    77  	c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+2, check.Commentf("docker images shows: %q\n", imagesAfter))
    78  
    79  	imgID, err := inspectField("busybox-one:tag1", "Id")
    80  	c.Assert(err, checker.IsNil)
    81  
    82  	// run a container with the image
    83  	out, _ = dockerCmd(c, "run", "-d", "busybox-one", "top")
    84  
    85  	containerID = strings.TrimSpace(out)
    86  
    87  	// first checkout without force it fails
    88  	out, _, err = dockerCmdWithError("rmi", imgID)
    89  	expected := fmt.Sprintf("conflict: unable to delete %s (cannot be forced) - image is being used by running container %s", stringid.TruncateID(imgID), stringid.TruncateID(containerID))
    90  	// rmi tagged in multiple repos should have failed without force
    91  	c.Assert(err, checker.NotNil)
    92  	c.Assert(out, checker.Contains, expected)
    93  
    94  	dockerCmd(c, "stop", containerID)
    95  	dockerCmd(c, "rmi", "-f", imgID)
    96  
    97  	imagesAfter, _ = dockerCmd(c, "images", "-a")
    98  	// rmi -f failed, image still exists
    99  	c.Assert(imagesAfter, checker.Not(checker.Contains), imgID[:12], check.Commentf("ImageID:%q; ImagesAfter: %q", imgID, imagesAfter))
   100  }
   101  
   102  func (s *DockerSuite) TestRmiImgIDForce(c *check.C) {
   103  	testRequires(c, DaemonIsLinux)
   104  	out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-test'")
   105  
   106  	containerID := strings.TrimSpace(out)
   107  	dockerCmd(c, "commit", containerID, "busybox-test")
   108  
   109  	imagesBefore, _ := dockerCmd(c, "images", "-a")
   110  	dockerCmd(c, "tag", "busybox-test", "utest:tag1")
   111  	dockerCmd(c, "tag", "busybox-test", "utest:tag2")
   112  	dockerCmd(c, "tag", "busybox-test", "utest/docker:tag3")
   113  	dockerCmd(c, "tag", "busybox-test", "utest:5000/docker:tag4")
   114  	{
   115  		imagesAfter, _ := dockerCmd(c, "images", "-a")
   116  		c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+4, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
   117  	}
   118  	imgID, err := inspectField("busybox-test", "Id")
   119  	c.Assert(err, checker.IsNil)
   120  
   121  	// first checkout without force it fails
   122  	out, _, err = dockerCmdWithError("rmi", imgID)
   123  	// rmi tagged in multiple repos should have failed without force
   124  	c.Assert(err, checker.NotNil)
   125  	// rmi tagged in multiple repos should have failed without force
   126  	c.Assert(out, checker.Contains, "(must be forced) - image is referenced in one or more repositories", check.Commentf("out: %s; err: %v;", out, err))
   127  
   128  	dockerCmd(c, "rmi", "-f", imgID)
   129  	{
   130  		imagesAfter, _ := dockerCmd(c, "images", "-a")
   131  		// rmi failed, image still exists
   132  		c.Assert(imagesAfter, checker.Not(checker.Contains), imgID[:12])
   133  	}
   134  }
   135  
   136  // See https://github.com/docker/docker/issues/14116
   137  func (s *DockerSuite) TestRmiImageIDForceWithRunningContainersAndMultipleTags(c *check.C) {
   138  	testRequires(c, DaemonIsLinux)
   139  	dockerfile := "FROM busybox\nRUN echo test 14116\n"
   140  	imgID, err := buildImage("test-14116", dockerfile, false)
   141  	c.Assert(err, checker.IsNil)
   142  
   143  	newTag := "newtag"
   144  	dockerCmd(c, "tag", imgID, newTag)
   145  	dockerCmd(c, "run", "-d", imgID, "top")
   146  
   147  	out, _, err := dockerCmdWithError("rmi", "-f", imgID)
   148  	// rmi -f should not delete image with running containers
   149  	c.Assert(err, checker.NotNil)
   150  	c.Assert(out, checker.Contains, "(cannot be forced) - image is being used by running container")
   151  }
   152  
   153  func (s *DockerSuite) TestRmiTagWithExistingContainers(c *check.C) {
   154  	testRequires(c, DaemonIsLinux)
   155  	container := "test-delete-tag"
   156  	newtag := "busybox:newtag"
   157  	bb := "busybox:latest"
   158  	dockerCmd(c, "tag", bb, newtag)
   159  
   160  	dockerCmd(c, "run", "--name", container, bb, "/bin/true")
   161  
   162  	out, _ := dockerCmd(c, "rmi", newtag)
   163  	c.Assert(strings.Count(out, "Untagged: "), checker.Equals, 1)
   164  }
   165  
   166  func (s *DockerSuite) TestRmiForceWithExistingContainers(c *check.C) {
   167  	testRequires(c, DaemonIsLinux)
   168  	image := "busybox-clone"
   169  
   170  	cmd := exec.Command(dockerBinary, "build", "--no-cache", "-t", image, "-")
   171  	cmd.Stdin = strings.NewReader(`FROM busybox
   172  MAINTAINER foo`)
   173  
   174  	out, _, err := runCommandWithOutput(cmd)
   175  	c.Assert(err, checker.IsNil, check.Commentf("Could not build %s: %s", image, out))
   176  
   177  	dockerCmd(c, "run", "--name", "test-force-rmi", image, "/bin/true")
   178  
   179  	dockerCmd(c, "rmi", "-f", image)
   180  }
   181  
   182  func (s *DockerSuite) TestRmiWithMultipleRepositories(c *check.C) {
   183  	testRequires(c, DaemonIsLinux)
   184  	newRepo := "127.0.0.1:5000/busybox"
   185  	oldRepo := "busybox"
   186  	newTag := "busybox:test"
   187  	dockerCmd(c, "tag", oldRepo, newRepo)
   188  
   189  	dockerCmd(c, "run", "--name", "test", oldRepo, "touch", "/home/abcd")
   190  
   191  	dockerCmd(c, "commit", "test", newTag)
   192  
   193  	out, _ := dockerCmd(c, "rmi", newTag)
   194  	c.Assert(out, checker.Contains, "Untagged: "+newTag)
   195  }
   196  
   197  func (s *DockerSuite) TestRmiForceWithMultipleRepositories(c *check.C) {
   198  	testRequires(c, DaemonIsLinux)
   199  	imageName := "rmiimage"
   200  	tag1 := imageName + ":tag1"
   201  	tag2 := imageName + ":tag2"
   202  
   203  	_, err := buildImage(tag1,
   204  		`FROM scratch
   205  		MAINTAINER "docker"`,
   206  		true)
   207  	if err != nil {
   208  		c.Fatal(err)
   209  	}
   210  
   211  	dockerCmd(c, "tag", tag1, tag2)
   212  
   213  	out, _ := dockerCmd(c, "rmi", "-f", tag2)
   214  	c.Assert(out, checker.Contains, "Untagged: "+tag2)
   215  	c.Assert(out, checker.Not(checker.Contains), "Untagged: "+tag1)
   216  
   217  	// Check built image still exists
   218  	images, _ := dockerCmd(c, "images", "-a")
   219  	c.Assert(images, checker.Contains, imageName, check.Commentf("Built image missing %q; Images: %q", imageName, images))
   220  }
   221  
   222  func (s *DockerSuite) TestRmiBlank(c *check.C) {
   223  	testRequires(c, DaemonIsLinux)
   224  	// try to delete a blank image name
   225  	out, _, err := dockerCmdWithError("rmi", "")
   226  	// Should have failed to delete '' image
   227  	c.Assert(err, checker.NotNil)
   228  	// Wrong error message generated
   229  	c.Assert(out, checker.Not(checker.Contains), "no such id", check.Commentf("out: %s", out))
   230  	// Expected error message not generated
   231  	c.Assert(out, checker.Contains, "image name cannot be blank", check.Commentf("out: %s", out))
   232  
   233  	out, _, err = dockerCmdWithError("rmi", " ")
   234  	// Should have failed to delete ' ' image
   235  	c.Assert(err, checker.NotNil)
   236  	// Expected error message not generated
   237  	c.Assert(out, checker.Contains, "image name cannot be blank", check.Commentf("out: %s", out))
   238  }
   239  
   240  func (s *DockerSuite) TestRmiContainerImageNotFound(c *check.C) {
   241  	testRequires(c, DaemonIsLinux)
   242  	// Build 2 images for testing.
   243  	imageNames := []string{"test1", "test2"}
   244  	imageIds := make([]string, 2)
   245  	for i, name := range imageNames {
   246  		dockerfile := fmt.Sprintf("FROM busybox\nMAINTAINER %s\nRUN echo %s\n", name, name)
   247  		id, err := buildImage(name, dockerfile, false)
   248  		c.Assert(err, checker.IsNil)
   249  		imageIds[i] = id
   250  	}
   251  
   252  	// Create a long-running container.
   253  	dockerCmd(c, "run", "-d", imageNames[0], "top")
   254  
   255  	// Create a stopped container, and then force remove its image.
   256  	dockerCmd(c, "run", imageNames[1], "true")
   257  	dockerCmd(c, "rmi", "-f", imageIds[1])
   258  
   259  	// Try to remove the image of the running container and see if it fails as expected.
   260  	out, _, err := dockerCmdWithError("rmi", "-f", imageIds[0])
   261  	// The image of the running container should not be removed.
   262  	c.Assert(err, checker.NotNil)
   263  	c.Assert(out, checker.Contains, "image is being used by running container", check.Commentf("out: %s", out))
   264  }
   265  
   266  // #13422
   267  func (s *DockerSuite) TestRmiUntagHistoryLayer(c *check.C) {
   268  	testRequires(c, DaemonIsLinux)
   269  	image := "tmp1"
   270  	// Build a image for testing.
   271  	dockerfile := `FROM busybox
   272  MAINTAINER foo
   273  RUN echo 0 #layer0
   274  RUN echo 1 #layer1
   275  RUN echo 2 #layer2
   276  `
   277  	_, err := buildImage(image, dockerfile, false)
   278  	c.Assert(err, checker.IsNil)
   279  
   280  	out, _ := dockerCmd(c, "history", "-q", image)
   281  	ids := strings.Split(out, "\n")
   282  	idToTag := ids[2]
   283  
   284  	// Tag layer0 to "tmp2".
   285  	newTag := "tmp2"
   286  	dockerCmd(c, "tag", idToTag, newTag)
   287  	// Create a container based on "tmp1".
   288  	dockerCmd(c, "run", "-d", image, "true")
   289  
   290  	// See if the "tmp2" can be untagged.
   291  	out, _ = dockerCmd(c, "rmi", newTag)
   292  	// Expected 1 untagged entry
   293  	c.Assert(strings.Count(out, "Untagged: "), checker.Equals, 1, check.Commentf("out: %s", out))
   294  
   295  	// Now let's add the tag again and create a container based on it.
   296  	dockerCmd(c, "tag", idToTag, newTag)
   297  	out, _ = dockerCmd(c, "run", "-d", newTag, "true")
   298  	cid := strings.TrimSpace(out)
   299  
   300  	// At this point we have 2 containers, one based on layer2 and another based on layer0.
   301  	// Try to untag "tmp2" without the -f flag.
   302  	out, _, err = dockerCmdWithError("rmi", newTag)
   303  	// should not be untagged without the -f flag
   304  	c.Assert(err, checker.NotNil)
   305  	c.Assert(out, checker.Contains, cid[:12])
   306  	c.Assert(out, checker.Contains, "(must force)")
   307  
   308  	// Add the -f flag and test again.
   309  	out, _ = dockerCmd(c, "rmi", "-f", newTag)
   310  	// should be allowed to untag with the -f flag
   311  	c.Assert(out, checker.Contains, fmt.Sprintf("Untagged: %s:latest", newTag))
   312  }
   313  
   314  func (*DockerSuite) TestRmiParentImageFail(c *check.C) {
   315  	testRequires(c, DaemonIsLinux)
   316  
   317  	parent, err := inspectField("busybox", "Parent")
   318  	c.Assert(err, check.IsNil)
   319  	out, _, err := dockerCmdWithError("rmi", parent)
   320  	c.Assert(err, check.NotNil)
   321  	if !strings.Contains(out, "image has dependent child images") {
   322  		c.Fatalf("rmi should have failed because it's a parent image, got %s", out)
   323  	}
   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  }
   340  
   341  // #18873
   342  func (s *DockerSuite) TestRmiByIDHardConflict(c *check.C) {
   343  	testRequires(c, DaemonIsLinux)
   344  	dockerCmd(c, "create", "busybox")
   345  
   346  	imgID, err := inspectField("busybox:latest", "Id")
   347  	c.Assert(err, checker.IsNil)
   348  
   349  	_, _, err = dockerCmdWithError("rmi", imgID[:12])
   350  	c.Assert(err, checker.NotNil)
   351  
   352  	// check that tag was not removed
   353  	imgID2, err := inspectField("busybox:latest", "Id")
   354  	c.Assert(err, checker.IsNil)
   355  	c.Assert(imgID, checker.Equals, imgID2)
   356  }