diff --git a/daemon/volumes.go b/daemon/volumes.go index 867bbb44ef..b9d622990d 100644 --- a/daemon/volumes.go +++ b/daemon/volumes.go @@ -21,6 +21,7 @@ type Mount struct { container *Container volume *volumes.Volume Writable bool + copyData bool } func (container *Container) prepareVolumes() error { @@ -75,7 +76,7 @@ func (m *Mount) initialize() error { m.container.VolumesRW[m.MountToPath] = m.Writable m.container.Volumes[m.MountToPath] = m.volume.Path m.volume.AddContainer(m.container.ID) - if m.Writable && !m.volume.IsBindMount { + if m.Writable && m.copyData { // Copy whatever is in the container at the mntToPath to the volume copyExistingContents(containerMntPath, m.volume.Path) } @@ -115,7 +116,12 @@ func (container *Container) parseVolumeMountConfig() (map[string]*Mount, error) if err != nil { return nil, err } - mounts[mountToPath] = &Mount{container: container, volume: vol, MountToPath: mountToPath, Writable: writable} + mounts[mountToPath] = &Mount{ + container: container, + volume: vol, + MountToPath: mountToPath, + Writable: writable, + } } // Get the rest of the volumes @@ -129,7 +135,13 @@ func (container *Container) parseVolumeMountConfig() (map[string]*Mount, error) if err != nil { return nil, err } - mounts[path] = &Mount{container: container, MountToPath: path, volume: vol, Writable: true} + mounts[path] = &Mount{ + container: container, + MountToPath: path, + volume: vol, + Writable: true, + copyData: true, + } } return mounts, nil diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 397bd91e77..43a6d65e8a 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -2303,3 +2303,39 @@ func TestRunReuseBindVolumeThatIsSymlink(t *testing.T) { deleteAllContainers() logDone("run - can remount old bindmount volume") } + +func TestVolumesNoCopyData(t *testing.T) { + defer deleteImages("dataimage") + defer deleteAllContainers() + if _, err := buildImage("dataimage", + `FROM busybox + RUN mkdir -p /foo + RUN touch /foo/bar`, + true); err != nil { + t.Fatal(err) + } + + cmd := exec.Command(dockerBinary, "run", "--name", "test", "-v", "/foo", "busybox") + if _, err := runCommand(cmd); err != nil { + t.Fatal(err) + } + + cmd = exec.Command(dockerBinary, "run", "--volumes-from", "test", "dataimage", "ls", "-lh", "/foo/bar") + if out, _, err := runCommandWithOutput(cmd); err == nil || !strings.Contains(out, "No such file or directory") { + t.Fatalf("Data was copied on volumes-from but shouldn't be:\n%q", out) + } + + tmpDir, err := ioutil.TempDir("", "docker_test_bind_mount_copy_data") + if err != nil { + t.Fatal(err) + } + + defer os.RemoveAll(tmpDir) + + cmd = exec.Command(dockerBinary, "run", "-v", tmpDir+":/foo", "dataimage", "ls", "-lh", "/foo/bar") + if out, _, err := runCommandWithOutput(cmd); err == nil || !strings.Contains(out, "No such file or directory") { + t.Fatalf("Data was copied on bind-mount but shouldn't be:\n%q", out) + } + + logDone("run - volumes do not copy data for volumes-from and bindmounts") +}