diff --git a/daemon/create.go b/daemon/create.go index 385618c7b4..637363489b 100644 --- a/daemon/create.go +++ b/daemon/create.go @@ -63,6 +63,7 @@ func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.Hos if err := daemon.mergeAndVerifyConfig(config, img); err != nil { return nil, nil, err } + if hostConfig == nil { hostConfig = &runconfig.HostConfig{} } @@ -89,7 +90,7 @@ func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.Hos } defer container.Unmount() - if err := createContainerPlatformSpecificSettings(container, config); err != nil { + if err := createContainerPlatformSpecificSettings(container, config, img); err != nil { return nil, nil, err } diff --git a/daemon/create_unix.go b/daemon/create_unix.go index 124cec0a10..98bb2414ce 100644 --- a/daemon/create_unix.go +++ b/daemon/create_unix.go @@ -8,13 +8,15 @@ import ( "path/filepath" "strings" + "github.com/docker/docker/image" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/runconfig" + "github.com/docker/docker/volume" "github.com/opencontainers/runc/libcontainer/label" ) // createContainerPlatformSpecificSettings performs platform specific container create functionality -func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config) error { +func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, img *image.Image) error { for spec := range config.Volumes { var ( name, destination string @@ -42,7 +44,17 @@ func createContainerPlatformSpecificSettings(container *Container, config *runco return fmt.Errorf("cannot mount volume over existing file, file exists %s", path) } - v, err := createVolume(name, config.VolumeDriver) + volumeDriver := config.VolumeDriver + if destination != "" && img != nil { + if _, ok := img.ContainerConfig.Volumes[destination]; ok { + // check for whether bind is not specified and then set to local + if _, ok := container.MountPoints[destination]; !ok { + volumeDriver = volume.DefaultDriverName + } + } + } + + v, err := createVolume(name, volumeDriver) if err != nil { return err } @@ -50,8 +62,11 @@ func createContainerPlatformSpecificSettings(container *Container, config *runco return err } - if err := container.copyImagePathContent(v, destination); err != nil { - return err + // never attempt to copy existing content in a container FS to a shared volume + if volumeDriver == volume.DefaultDriverName || volumeDriver == "" { + if err := container.copyImagePathContent(v, destination); err != nil { + return err + } } container.addMountPointWithVolume(destination, v, true) diff --git a/daemon/create_windows.go b/daemon/create_windows.go index 401d68d8c5..27a5d8361f 100644 --- a/daemon/create_windows.go +++ b/daemon/create_windows.go @@ -1,10 +1,11 @@ package daemon import ( + "github.com/docker/docker/image" "github.com/docker/docker/runconfig" ) // createContainerPlatformSpecificSettings performs platform specific container create functionality -func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config) error { +func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, img *image.Image) error { return nil } diff --git a/integration-cli/docker_cli_start_volume_driver_unix_test.go b/integration-cli/docker_cli_start_volume_driver_unix_test.go index 71f9f2d540..6c431f11a9 100644 --- a/integration-cli/docker_cli_start_volume_driver_unix_test.go +++ b/integration-cli/docker_cli_start_volume_driver_unix_test.go @@ -244,3 +244,38 @@ func (s DockerExternalVolumeSuite) TestStartExternalVolumeDriverDeleteContainer( func hostVolumePath(name string) string { return fmt.Sprintf("/var/lib/docker/volumes/%s", name) } + +func (s *DockerExternalVolumeSuite) TestStartExternalNamedVolumeDriverCheckBindLocalVolume(c *check.C) { + if err := s.d.StartWithBusybox(); err != nil { + c.Fatal(err) + } + + expected := s.server.URL + + dockerfile := fmt.Sprintf(`FROM busybox:latest + RUN mkdir /nobindthenlocalvol + RUN echo %s > /nobindthenlocalvol/test + VOLUME ["/nobindthenlocalvol"]`, expected) + + img := "test-checkbindlocalvolume" + + args := []string{"--host", s.d.sock()} + buildOut, err := buildImageArgs(args, img, dockerfile, true) + fmt.Println(buildOut) + + out, err := s.d.Cmd("run", "--rm", "--name", "test-data-nobind", "-v", "external-volume-test:/tmp/external-volume-test", "--volume-driver", "test-external-volume-driver", img, "cat", "/nobindthenlocalvol/test") + if err != nil { + fmt.Println(out) + c.Fatal(err) + } + + if !strings.Contains(out, expected) { + c.Fatalf("External volume mount failed. Output: %s\n", out) + } + + c.Assert(s.ec.activations, check.Equals, 1) + c.Assert(s.ec.creations, check.Equals, 1) + c.Assert(s.ec.removals, check.Equals, 1) + c.Assert(s.ec.mounts, check.Equals, 1) + c.Assert(s.ec.unmounts, check.Equals, 1) +} diff --git a/integration-cli/docker_utils.go b/integration-cli/docker_utils.go index 3c9cd48195..fcfc7ac232 100644 --- a/integration-cli/docker_utils.go +++ b/integration-cli/docker_utils.go @@ -1353,3 +1353,33 @@ func createTmpFile(c *check.C, content string) string { return filename } + +func buildImageArgs(args []string, name, dockerfile string, useCache bool) (string, error) { + id, _, err := buildImageWithOutArgs(args, name, dockerfile, useCache) + return id, err +} + +func buildImageWithOutArgs(args []string, name, dockerfile string, useCache bool) (string, string, error) { + buildCmd := buildImageCmdArgs(args, name, dockerfile, useCache) + out, exitCode, err := runCommandWithOutput(buildCmd) + if err != nil || exitCode != 0 { + return "", out, fmt.Errorf("failed to build the image: %s", out) + } + id, err := getIDByName(name) + if err != nil { + return "", out, err + } + return id, out, nil +} + +func buildImageCmdArgs(args []string, name, dockerfile string, useCache bool) *exec.Cmd { + args = append(args, []string{"-D", "build", "-t", name}...) + if !useCache { + args = append(args, "--no-cache") + } + args = append(args, "-") + buildCmd := exec.Command(dockerBinary, args...) + buildCmd.Stdin = strings.NewReader(dockerfile) + return buildCmd + +}