소스 검색

Merge pull request #5389 from tiborvass/5152-symlink-in-volume

Fixes #5152 : symlink in volume path
Michael Crosby 11 년 전
부모
커밋
934bd15565
3개의 변경된 파일62개의 추가작업 그리고 5개의 파일을 삭제
  1. 16 5
      daemon/volumes.go
  2. 43 0
      integration-cli/docker_cli_run_test.go
  3. 3 0
      integration-cli/run_tests/TestVolumeWithSymlink/Dockerfile

+ 16 - 5
daemon/volumes.go

@@ -217,15 +217,26 @@ func createVolumes(container *Container) error {
 			srcPath = p
 			srcPath = p
 		}
 		}
 
 
-		container.Volumes[volPath] = srcPath
-		container.VolumesRW[volPath] = srcRW
-
 		// Create the mountpoint
 		// Create the mountpoint
-		volPath = filepath.Join(container.basefs, volPath)
-		rootVolPath, err := utils.FollowSymlinkInScope(volPath, container.basefs)
+		rootVolPath, err := utils.FollowSymlinkInScope(filepath.Join(container.basefs, volPath), container.basefs)
+		if err != nil {
+			return err
+		}
+
+		newVolPath, err := filepath.Rel(container.basefs, rootVolPath)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
+		newVolPath = "/" + newVolPath
+
+		if volPath != newVolPath {
+			delete(container.Volumes, volPath)
+			delete(container.VolumesRW, volPath)
+		}
+
+		container.Volumes[newVolPath] = srcPath
+		container.VolumesRW[newVolPath] = srcRW
+
 		if err := createIfNotExists(rootVolPath, volIsDir); err != nil {
 		if err := createIfNotExists(rootVolPath, volIsDir); err != nil {
 			return err
 			return err
 		}
 		}

+ 43 - 0
integration-cli/docker_cli_run_test.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"fmt"
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
+	"path/filepath"
 	"regexp"
 	"regexp"
 	"sort"
 	"sort"
 	"strings"
 	"strings"
@@ -424,6 +425,48 @@ func TestCreateVolume(t *testing.T) {
 	logDone("run - create docker mangaed volume")
 	logDone("run - create docker mangaed volume")
 }
 }
 
 
+// Test that creating a volume with a symlink in its path works correctly. Test for #5152.
+// Note that this bug happens only with symlinks with a target that starts with '/'.
+func TestVolumeWithSymlink(t *testing.T) {
+	buildDirectory := filepath.Join(workingDirectory, "run_tests", "TestVolumeWithSymlink")
+	buildCmd := exec.Command(dockerBinary, "build", "-t", "docker-test-volumewithsymlink", ".")
+	buildCmd.Dir = buildDirectory
+	err := buildCmd.Run()
+	if err != nil {
+		t.Fatal("could not build 'docker-test-volumewithsymlink': %v", err)
+	}
+
+	cmd := exec.Command(dockerBinary, "run", "-v", "/bar/foo", "--name", "test-volumewithsymlink", "docker-test-volumewithsymlink", "sh", "-c", "mount | grep -q /foo/foo")
+	exitCode, err := runCommand(cmd)
+	if err != nil || exitCode != 0 {
+		t.Fatal("[run] err: %v, exitcode: %d", err, exitCode)
+	}
+
+	var volPath string
+	cmd = exec.Command(dockerBinary, "inspect", "-f", "{{range .Volumes}}{{.}}{{end}}", "test-volumewithsymlink")
+	volPath, exitCode, err = runCommandWithOutput(cmd)
+	if err != nil || exitCode != 0 {
+		t.Fatal("[inspect] err: %v, exitcode: %d", err, exitCode)
+	}
+
+	cmd = exec.Command(dockerBinary, "rm", "-v", "test-volumewithsymlink")
+	exitCode, err = runCommand(cmd)
+	if err != nil || exitCode != 0 {
+		t.Fatal("[rm] err: %v, exitcode: %d", err, exitCode)
+	}
+
+	f, err := os.Open(volPath)
+	defer f.Close()
+	if !os.IsNotExist(err) {
+		t.Fatal("[open] (expecting 'file does not exist' error) err: %v, volPath: %s", err, volPath)
+	}
+
+	deleteImages("docker-test-volumewithsymlink")
+	deleteAllContainers()
+
+	logDone("run - volume with symlink")
+}
+
 func TestExitCode(t *testing.T) {
 func TestExitCode(t *testing.T) {
 	cmd := exec.Command(dockerBinary, "run", "busybox", "/bin/sh", "-c", "exit 72")
 	cmd := exec.Command(dockerBinary, "run", "busybox", "/bin/sh", "-c", "exit 72")
 
 

+ 3 - 0
integration-cli/run_tests/TestVolumeWithSymlink/Dockerfile

@@ -0,0 +1,3 @@
+FROM busybox
+
+RUN mkdir /foo && ln -s /foo /bar