Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit 58c2488

Browse files
committed
Merge pull request #19568 from cpuguy83/17907_fix_rmv
On container rm, don't remove named mountpoints
2 parents ced2d37 + dd7d1c8 commit 58c2488

File tree

8 files changed

+90
-3
lines changed

8 files changed

+90
-3
lines changed

daemon/mounts.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ func (daemon *Daemon) removeMountPoints(container *container.Container, rm bool)
2525
}
2626
daemon.volumes.Dereference(m.Volume, container.ID)
2727
if rm {
28+
// Do not remove named mountpoints
29+
// these are mountpoints specified like `docker run -v <name>:/foo`
30+
if m.Named {
31+
continue
32+
}
2833
err := daemon.volumes.Remove(m.Volume)
2934
// Ignore volume in use errors because having this
3035
// volume being referenced by other container is

daemon/volumes.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
9090
Driver: m.Driver,
9191
Destination: m.Destination,
9292
Propagation: m.Propagation,
93+
Named: m.Named,
9394
}
9495

9596
if len(cp.Source) == 0 {
@@ -126,6 +127,7 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
126127
bind.Source = v.Path()
127128
// bind.Name is an already existing volume, we need to use that here
128129
bind.Driver = v.DriverName()
130+
bind.Named = true
129131
bind = setBindModeIfNull(bind)
130132
}
131133
if label.RelabelNeeded(bind.Mode) {

docs/reference/commandline/rm.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,17 @@ This command will delete all stopped containers. The command
4545
`docker ps -a -q` will return all existing container IDs and pass them to
4646
the `rm` command which will delete them. Any running containers will not be
4747
deleted.
48+
49+
$ docker rm -v redis
50+
redis
51+
52+
This command will remove the container and any volumes associated with it.
53+
Note that if a volume was specified with a name, it will not be removed.
54+
55+
$ docker create -v awesome:/foo -v /bar --name hello redis
56+
hello
57+
$ docker rm -v hello
58+
59+
In this example, the volume for `/foo` will remain intact, but the volume for
60+
`/bar` will be removed. The same behavior holds for volumes inherited with
61+
`--volumes-from`.

docs/reference/run.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,11 @@ the container exits**, you can add the `--rm` flag:
590590

591591
> **Note**: When you set the `--rm` flag, Docker also removes the volumes
592592
associated with the container when the container is removed. This is similar
593-
to running `docker rm -v my-container`.
593+
to running `docker rm -v my-container`. Only volumes that are specified without a
594+
name are removed. For example, with
595+
`docker run --rm -v /foo -v awesome:/bar busybox top`, the volume for `/foo` will be removed,
596+
but the volume for `/bar` will not. Volumes inheritted via `--volumes-from` will be removed
597+
with the same logic -- if the original volume was specified with a name it will **not** be removed.
594598

595599
## Security configuration
596600
--security-opt="label:user:USER" : Set the label user for the container

integration-cli/docker_cli_run_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4137,3 +4137,42 @@ func (s *DockerSuite) TestRunNamedVolumeCopyImageData(c *check.C) {
41374137
out, _ := dockerCmd(c, "run", "-v", "foo:/foo", "busybox", "cat", "/foo/hello")
41384138
c.Assert(strings.TrimSpace(out), check.Equals, "hello")
41394139
}
4140+
4141+
func (s *DockerSuite) TestRunNamedVolumeNotRemoved(c *check.C) {
4142+
prefix := ""
4143+
if daemonPlatform == "windows" {
4144+
prefix = "c:"
4145+
}
4146+
4147+
dockerCmd(c, "volume", "create", "--name", "test")
4148+
4149+
dockerCmd(c, "run", "--rm", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
4150+
dockerCmd(c, "volume", "inspect", "test")
4151+
out, _ := dockerCmd(c, "volume", "ls", "-q")
4152+
c.Assert(strings.TrimSpace(out), checker.Equals, "test")
4153+
4154+
dockerCmd(c, "run", "--name=test", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
4155+
dockerCmd(c, "rm", "-fv", "test")
4156+
dockerCmd(c, "volume", "inspect", "test")
4157+
out, _ = dockerCmd(c, "volume", "ls", "-q")
4158+
c.Assert(strings.TrimSpace(out), checker.Equals, "test")
4159+
}
4160+
4161+
func (s *DockerSuite) TestRunNamedVolumesFromNotRemoved(c *check.C) {
4162+
prefix := ""
4163+
if daemonPlatform == "windows" {
4164+
prefix = "c:"
4165+
}
4166+
4167+
dockerCmd(c, "volume", "create", "--name", "test")
4168+
dockerCmd(c, "run", "--name=parent", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
4169+
dockerCmd(c, "run", "--name=child", "--volumes-from=parent", "busybox", "true")
4170+
4171+
// Remove the parent so there are not other references to the volumes
4172+
dockerCmd(c, "rm", "-f", "parent")
4173+
// now remove the child and ensure the named volume (and only the named volume) still exists
4174+
dockerCmd(c, "rm", "-fv", "child")
4175+
dockerCmd(c, "volume", "inspect", "test")
4176+
out, _ := dockerCmd(c, "volume", "ls", "-q")
4177+
c.Assert(strings.TrimSpace(out), checker.Equals, "test")
4178+
}

integration-cli/docker_cli_start_volume_driver_unix_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverNamed(c *check.C) {
228228
c.Assert(err, checker.IsNil, check.Commentf(out))
229229
c.Assert(out, checker.Contains, s.server.URL)
230230

231+
_, err = s.d.Cmd("volume", "rm", "external-volume-test")
232+
c.Assert(err, checker.IsNil)
233+
231234
p := hostVolumePath("external-volume-test")
232235
_, err = os.Lstat(p)
233236
c.Assert(err, checker.NotNil)
@@ -362,6 +365,9 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverRetryNotImmediatelyE
362365
c.Fatal("volume creates fail when plugin not immediately available")
363366
}
364367

368+
_, err = s.d.Cmd("volume", "rm", "external-volume-test")
369+
c.Assert(err, checker.IsNil)
370+
365371
c.Assert(s.ec.activations, checker.Equals, 1)
366372
c.Assert(s.ec.creations, checker.Equals, 1)
367373
c.Assert(s.ec.removals, checker.Equals, 1)
@@ -385,7 +391,7 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverBindExternalVolume(c
385391
c.Assert(mounts[0].Driver, checker.Equals, "test-external-volume-driver")
386392
}
387393

388-
func (s *DockerExternalVolumeSuite) TestStartExternalVolumeDriverList(c *check.C) {
394+
func (s *DockerExternalVolumeSuite) TesttExternalVolumeDriverList(c *check.C) {
389395
dockerCmd(c, "volume", "create", "-d", "test-external-volume-driver", "--name", "abc")
390396
out, _ := dockerCmd(c, "volume", "ls")
391397
ls := strings.Split(strings.TrimSpace(out), "\n")
@@ -399,7 +405,7 @@ func (s *DockerExternalVolumeSuite) TestStartExternalVolumeDriverList(c *check.C
399405
c.Assert(s.ec.lists, check.Equals, 1)
400406
}
401407

402-
func (s *DockerExternalVolumeSuite) TestStartExternalVolumeDriverGet(c *check.C) {
408+
func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverGet(c *check.C) {
403409
out, _, err := dockerCmdWithError("volume", "inspect", "dummy")
404410
c.Assert(err, check.NotNil, check.Commentf(out))
405411
c.Assert(s.ec.gets, check.Equals, 1)

man/docker-rm.1.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,22 @@ command. The use that name as follows:
4848

4949
docker rm hopeful_morse
5050

51+
## Removing a container and all associated volumes
52+
53+
$ docker rm -v redis
54+
redis
55+
56+
This command will remove the container and any volumes associated with it.
57+
Note that if a volume was specified with a name, it will not be removed.
58+
59+
$ docker create -v awesome:/foo -v /bar --name hello redis
60+
hello
61+
$ docker rm -v hello
62+
63+
In this example, the volume for `/foo` will remain in tact, but the volume for
64+
`/bar` will be removed. The same behavior holds for volumes inherited with
65+
`--volumes-from`.
66+
5167
# HISTORY
5268
April 2014, Originally compiled by William Henry (whenry at redhat dot com)
5369
based on docker.com source material and internal work.

volume/volume.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ type MountPoint struct {
5959

6060
// Note Propagation is not used on Windows
6161
Propagation string // Mount propagation string
62+
Named bool // specifies if the mountpoint was specified by name
6263
}
6364

6465
// Setup sets up a mount point by either mounting the volume if it is

0 commit comments

Comments
 (0)