Skip to content

Commit

Permalink
Fix #7792 - Order mounts
Browse files Browse the repository at this point in the history
Docker-DCO-1.1-Signed-off-by: Brian Goff <cpuguy83@gmail.com> (github: cpuguy83)
  • Loading branch information
cpuguy83 committed Sep 16, 2014
1 parent 51b2685 commit 0a3211f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 5 deletions.
22 changes: 17 additions & 5 deletions daemon/volumes.go
Expand Up @@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"syscall"

Expand Down Expand Up @@ -73,19 +74,30 @@ func setupMountsForContainer(container *Container) error {
// Note, these are not private because you may want propagation of (un)mounts from host
// volumes. For instance if you use -v /usr:/usr and the host later mounts /usr/share you
// want this new mount in the container
for r, v := range container.Volumes {
// These mounts must be ordered based on the length of the path that it is being mounted to (lexicographic)
for _, path := range container.sortedVolumeMounts() {
mounts = append(mounts, execdriver.Mount{
Source: v,
Destination: r,
Writable: container.VolumesRW[r],
Source: container.Volumes[path],
Destination: path,
Writable: container.VolumesRW[path],
})
}

container.command.Mounts = mounts

return nil
}

// sortedVolumeMounts returns the list of container volume mount points sorted in lexicographic order
func (container *Container) sortedVolumeMounts() []string {
var mountPaths []string
for path := range container.Volumes {
mountPaths = append(mountPaths, path)
}

sort.Strings(mountPaths)
return mountPaths
}

func parseVolumesFromSpec(container *Container, spec string) (map[string]*Volume, error) {
specParts := strings.SplitN(spec, ":", 2)
if len(specParts) == 0 {
Expand Down
42 changes: 42 additions & 0 deletions integration-cli/docker_cli_run_test.go
Expand Up @@ -2069,3 +2069,45 @@ func TestDockerExecInteractive(t *testing.T) {

logDone("exec - Interactive test")
}

// Regression test for #7792
func TestMountOrdering(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "docker_nested_mount_test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)

tmpDir2, err := ioutil.TempDir("", "docker_nested_mount_test2")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir2)

// Create a temporary tmpfs mount.
fooDir := filepath.Join(tmpDir, "foo")
if err := os.MkdirAll(filepath.Join(tmpDir, "foo"), 0755); err != nil {
t.Fatalf("failed to mkdir at %s - %s", fooDir, err)
}

if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", fooDir), []byte{}, 0644); err != nil {
t.Fatal(err)
}

if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", tmpDir), []byte{}, 0644); err != nil {
t.Fatal(err)
}

if err := ioutil.WriteFile(fmt.Sprintf("%s/touch-me", tmpDir2), []byte{}, 0644); err != nil {
t.Fatal(err)
}

cmd := exec.Command(dockerBinary, "run", "-v", fmt.Sprintf("%s:/tmp", tmpDir), "-v", fmt.Sprintf("%s:/tmp/foo", fooDir), "-v", fmt.Sprintf("%s:/tmp/tmp2", tmpDir2), "-v", fmt.Sprintf("%s:/tmp/tmp2/foo", fooDir), "busybox:latest", "sh", "-c", "ls /tmp/touch-me && ls /tmp/foo/touch-me && ls /tmp/tmp2/touch-me && ls /tmp/tmp2/foo/touch-me")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
}

deleteAllContainers()
logDone("run - volumes are mounted in the correct order")
}

0 comments on commit 0a3211f

Please sign in to comment.