Explorar o código

Merge pull request #19175 from cpuguy83/18670_copy_data_for_named_volumes

On create, copy image data for named volumes.
Michael Crosby %!s(int64=9) %!d(string=hai) anos
pai
achega
e26974e20b
Modificáronse 3 ficheiros con 48 adicións e 6 borrados
  1. 17 6
      daemon/create_unix.go
  2. 14 0
      integration-cli/docker_cli_run_test.go
  3. 17 0
      volume/store/store.go

+ 17 - 6
daemon/create_unix.go

@@ -6,6 +6,7 @@ import (
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 
 
+	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/container"
 	derr "github.com/docker/docker/errors"
 	derr "github.com/docker/docker/errors"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/image"
@@ -60,14 +61,24 @@ func (daemon *Daemon) createContainerPlatformSpecificSettings(container *contain
 			return err
 			return err
 		}
 		}
 
 
-		// never attempt to copy existing content in a container FS to a shared volume
-		if v.DriverName() == volume.DefaultDriverName {
-			if err := container.CopyImagePathContent(v, destination); err != nil {
-				return err
-			}
+		container.AddMountPointWithVolume(destination, v, true)
+	}
+	return daemon.populateVolumes(container)
+}
+
+// populateVolumes copies data from the container's rootfs into the volume for non-binds.
+// this is only called when the container is created.
+func (daemon *Daemon) populateVolumes(c *container.Container) error {
+	for _, mnt := range c.MountPoints {
+		// skip binds and volumes referenced by other containers (ie, volumes-from)
+		if mnt.Driver == "" || mnt.Volume == nil || len(daemon.volumes.Refs(mnt.Volume)) > 1 {
+			continue
 		}
 		}
 
 
-		container.AddMountPointWithVolume(destination, v, true)
+		logrus.Debugf("copying image data from %s:%s, to %s", c.ID, mnt.Destination, mnt.Name)
+		if err := c.CopyImagePathContent(mnt.Volume, mnt.Destination); err != nil {
+			return err
+		}
 	}
 	}
 	return nil
 	return nil
 }
 }

+ 14 - 0
integration-cli/docker_cli_run_test.go

@@ -3931,5 +3931,19 @@ func (s *DockerSuite) TestRunNamedVolumesMountedAsShared(c *check.C) {
 	if expected := "Invalid volume specification"; !strings.Contains(out, expected) {
 	if expected := "Invalid volume specification"; !strings.Contains(out, expected) {
 		c.Fatalf(`Expected %q in output; got: %s`, expected, out)
 		c.Fatalf(`Expected %q in output; got: %s`, expected, out)
 	}
 	}
+}
+
+func (s *DockerSuite) TestRunNamedVolumeCopyImageData(c *check.C) {
+	testRequires(c, DaemonIsLinux)
 
 
+	testImg := "testvolumecopy"
+	_, err := buildImage(testImg, `
+	FROM busybox
+	RUN mkdir -p /foo && echo hello > /foo/hello
+	`, true)
+	c.Assert(err, check.IsNil)
+
+	dockerCmd(c, "run", "-v", "foo:/foo", testImg)
+	out, _ := dockerCmd(c, "run", "-v", "foo:/foo", "busybox", "cat", "/foo/hello")
+	c.Assert(strings.TrimSpace(out), check.Equals, "hello")
 }
 }

+ 17 - 0
volume/store/store.go

@@ -296,6 +296,23 @@ func (s *VolumeStore) Dereference(v volume.Volume, ref string) {
 	s.globalLock.Unlock()
 	s.globalLock.Unlock()
 }
 }
 
 
+// Refs gets the current list of refs for the given volume
+func (s *VolumeStore) Refs(v volume.Volume) []string {
+	s.locks.Lock(v.Name())
+	defer s.locks.Unlock(v.Name())
+
+	s.globalLock.Lock()
+	defer s.globalLock.Unlock()
+	refs, exists := s.refs[v.Name()]
+	if !exists {
+		return nil
+	}
+
+	refsOut := make([]string, len(refs))
+	copy(refsOut, refs)
+	return refsOut
+}
+
 // FilterByDriver returns the available volumes filtered by driver name
 // FilterByDriver returns the available volumes filtered by driver name
 func (s *VolumeStore) FilterByDriver(name string) ([]volume.Volume, error) {
 func (s *VolumeStore) FilterByDriver(name string) ([]volume.Volume, error) {
 	vd, err := volumedrivers.GetDriver(name)
 	vd, err := volumedrivers.GetDriver(name)