mirror of https://github.com/docker/docs.git
Merge pull request #8055 from cpuguy83/7792_fix_volume_mount_ordering
Fix #7792 - Order mounts
This commit is contained in:
commit
ed957232a1
|
@ -5,6 +5,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
@ -73,19 +74,30 @@ func setupMountsForContainer(container *Container) error {
|
||||||
// Note, these are not private because you may want propagation of (un)mounts from host
|
// 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
|
// volumes. For instance if you use -v /usr:/usr and the host later mounts /usr/share you
|
||||||
// want this new mount in the container
|
// 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{
|
mounts = append(mounts, execdriver.Mount{
|
||||||
Source: v,
|
Source: container.Volumes[path],
|
||||||
Destination: r,
|
Destination: path,
|
||||||
Writable: container.VolumesRW[r],
|
Writable: container.VolumesRW[path],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
container.command.Mounts = mounts
|
container.command.Mounts = mounts
|
||||||
|
|
||||||
return nil
|
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) {
|
func parseVolumesFromSpec(container *Container, spec string) (map[string]*Volume, error) {
|
||||||
specParts := strings.SplitN(spec, ":", 2)
|
specParts := strings.SplitN(spec, ":", 2)
|
||||||
if len(specParts) == 0 {
|
if len(specParts) == 0 {
|
||||||
|
|
|
@ -2069,3 +2069,45 @@ func TestDockerExecInteractive(t *testing.T) {
|
||||||
|
|
||||||
logDone("exec - Interactive test")
|
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")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue