diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index f1936bcecb..01a3f57638 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -2221,3 +2221,34 @@ func TestRunRedirectStdout(t *testing.T) { logDone("run - redirect stdout") } + +// Regression test for https://github.com/docker/docker/issues/8259 +func TestRunReuseBindVolumeThatIsSymlink(t *testing.T) { + tmpDir, err := ioutil.TempDir(os.TempDir(), "testlink") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + linkPath := os.TempDir() + "/testlink2" + if err := os.Symlink(tmpDir, linkPath); err != nil { + t.Fatal(err) + } + defer os.RemoveAll(linkPath) + + // Create first container + cmd := exec.Command(dockerBinary, "run", "-v", fmt.Sprintf("%s:/tmp/test", linkPath), "busybox", "ls", "-lh", "/tmp/test") + if _, err := runCommand(cmd); err != nil { + t.Fatal(err) + } + + // Create second container with same symlinked path + // This will fail if the referenced issue is hit with a "Volume exists" error + cmd = exec.Command(dockerBinary, "run", "-v", fmt.Sprintf("%s:/tmp/test", linkPath), "busybox", "ls", "-lh", "/tmp/test") + if out, _, err := runCommandWithOutput(cmd); err != nil { + t.Fatal(err, out) + } + + deleteAllContainers() + logDone("run - can remount old bindmount volume") +} diff --git a/volumes/repository.go b/volumes/repository.go index 1c5de96bb3..b09af8de26 100644 --- a/volumes/repository.go +++ b/volumes/repository.go @@ -97,12 +97,16 @@ func (r *Repository) restore() error { func (r *Repository) Get(path string) *Volume { r.lock.Lock() - vol := r.volumes[path] + vol := r.get(path) r.lock.Unlock() return vol } func (r *Repository) get(path string) *Volume { + path, err := filepath.EvalSymlinks(path) + if err != nil { + return nil + } return r.volumes[path] } @@ -129,6 +133,10 @@ func (r *Repository) remove(volume *Volume) { func (r *Repository) Delete(path string) error { r.lock.Lock() defer r.lock.Unlock() + path, err := filepath.EvalSymlinks(path) + if err != nil { + return err + } volume := r.get(path) if volume == nil { return fmt.Errorf("Volume %s does not exist", path)