Browse code

Fixes re-creating volume on (re)start

When a container is restarted all the volume configs are parsed again.
Even if the volume was already handled in a previous start it was still
calling "FindOrCreateVolume" on the volume repo causing a new volume to
be created.

This wasn't being detected because as part of the mount initialization
it checks to see if the the _mount_ was already initialized, but this
happens after the parsing of the configs.
So a check is added during parsing to skip a volume which was already
created for that container.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Brian Goff authored on 2014/10/09 04:01:25
Showing 4 changed files
... ...
@@ -131,6 +131,11 @@ func (container *Container) parseVolumeMountConfig() (map[string]*Mount, error)
131 131
 			continue
132 132
 		}
133 133
 
134
+		// Check if this has already been created
135
+		if _, exists := container.Volumes[path]; exists {
136
+			continue
137
+		}
138
+
134 139
 		vol, err := container.daemon.volumes.FindOrCreateVolume("", true)
135 140
 		if err != nil {
136 141
 			return nil, err
... ...
@@ -2339,3 +2339,40 @@ func TestVolumesNoCopyData(t *testing.T) {
2339 2339
 
2340 2340
 	logDone("run - volumes do not copy data for volumes-from and bindmounts")
2341 2341
 }
2342
+
2343
+func TestRunVolumesNotRecreatedOnStart(t *testing.T) {
2344
+	// Clear out any remnants from other tests
2345
+	deleteAllContainers()
2346
+	info, err := ioutil.ReadDir(volumesConfigPath)
2347
+	if err != nil {
2348
+		t.Fatal(err)
2349
+	}
2350
+	if len(info) > 0 {
2351
+		for _, f := range info {
2352
+			if err := os.RemoveAll(volumesConfigPath + "/" + f.Name()); err != nil {
2353
+				t.Fatal(err)
2354
+			}
2355
+		}
2356
+	}
2357
+
2358
+	defer deleteAllContainers()
2359
+	cmd := exec.Command(dockerBinary, "run", "-v", "/foo", "--name", "lone_starr", "busybox")
2360
+	if _, err := runCommand(cmd); err != nil {
2361
+		t.Fatal(err)
2362
+	}
2363
+
2364
+	cmd = exec.Command(dockerBinary, "start", "lone_starr")
2365
+	if _, err := runCommand(cmd); err != nil {
2366
+		t.Fatal(err)
2367
+	}
2368
+
2369
+	info, err = ioutil.ReadDir(volumesConfigPath)
2370
+	if err != nil {
2371
+		t.Fatal(err)
2372
+	}
2373
+	if len(info) != 1 {
2374
+		t.Fatalf("Expected only 1 volume have %v", len(info))
2375
+	}
2376
+
2377
+	logDone("run - volumes not recreated on start")
2378
+}
... ...
@@ -6,18 +6,21 @@ import (
6 6
 	"os/exec"
7 7
 )
8 8
 
9
-// the docker binary to use
10
-var dockerBinary = "docker"
9
+var (
10
+	// the docker binary to use
11
+	dockerBinary = "docker"
11 12
 
12
-// the private registry image to use for tests involving the registry
13
-var registryImageName = "registry"
13
+	// the private registry image to use for tests involving the registry
14
+	registryImageName = "registry"
14 15
 
15
-// the private registry to use for tests
16
-var privateRegistryURL = "127.0.0.1:5000"
16
+	// the private registry to use for tests
17
+	privateRegistryURL = "127.0.0.1:5000"
17 18
 
18
-var execDriverPath = "/var/lib/docker/execdriver/native"
19
+	execDriverPath    = "/var/lib/docker/execdriver/native"
20
+	volumesConfigPath = "/var/lib/docker/volumes"
19 21
 
20
-var workingDirectory string
22
+	workingDirectory string
23
+)
21 24
 
22 25
 func init() {
23 26
 	if dockerBin := os.Getenv("DOCKER_BINARY"); dockerBin != "" {
... ...
@@ -267,7 +267,7 @@ func deleteContainer(container string) error {
267 267
 	killSplitArgs := strings.Split(killArgs, " ")
268 268
 	killCmd := exec.Command(dockerBinary, killSplitArgs...)
269 269
 	runCommand(killCmd)
270
-	rmArgs := fmt.Sprintf("rm %v", container)
270
+	rmArgs := fmt.Sprintf("rm -v %v", container)
271 271
 	rmSplitArgs := strings.Split(rmArgs, " ")
272 272
 	rmCmd := exec.Command(dockerBinary, rmSplitArgs...)
273 273
 	exitCode, err := runCommand(rmCmd)