diff --git a/daemon/volumes.go b/daemon/volumes.go index 7b49733839..b1ebc76ddf 100644 --- a/daemon/volumes.go +++ b/daemon/volumes.go @@ -158,6 +158,10 @@ func (container *Container) parseVolumeMountConfig() (map[string]*Mount, error) if err != nil { return nil, err } + // Check if a bind mount has already been specified for the same container path + if m, exists := mounts[mountToPath]; exists { + return nil, fmt.Errorf("Duplicate volume %q: %q already in use, mounted from %q", path, mountToPath, m.volume.Path) + } // Check if a volume already exists for this and use it vol, err := container.daemon.volumes.FindOrCreateVolume(path, writable) if err != nil { diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 8e26a683bf..986acd8c77 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -493,6 +493,21 @@ func TestVolumesFromGetsProperMode(t *testing.T) { logDone("run - volumes from ignores `rw` if inherrited volume is `ro`") } +// Test for GH#10618 +func TestRunNoDupVolumes(t *testing.T) { + cmd := exec.Command(dockerBinary, "run", "-v", "/etc:/someplace", "-v", "/usr/lib:/someplace", "busybox", "echo", "hi") + if out, _, err := runCommandWithOutput(cmd); err == nil { + t.Fatal("Expected error about duplicate volume definitions") + } else { + if !strings.Contains(out, "Duplicate volume") { + t.Fatalf("Expected 'duplicate volume' error, got %v", err) + } + } + deleteAllContainers() + + logDone("run - don't allow multiple (bind) volumes on the same container target") +} + // Test for #1351 func TestRunApplyVolumesFromBeforeVolumes(t *testing.T) { cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test", "busybox", "touch", "/test/foo")