Просмотр исходного кода

daemon/populateVolumes: Support volume subpath

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Paweł Gronowski 2 лет назад
Родитель
Сommit
cb1af229f2
2 измененных файлов с 39 добавлено и 30 удалено
  1. 3 28
      container/container_unix.go
  2. 36 2
      daemon/create_unix.go

+ 3 - 28
container/container_unix.go

@@ -15,8 +15,6 @@ import (
 	"github.com/docker/docker/api/types/events"
 	mounttypes "github.com/docker/docker/api/types/mount"
 	swarmtypes "github.com/docker/docker/api/types/swarm"
-	"github.com/docker/docker/pkg/stringid"
-	"github.com/docker/docker/volume"
 	volumemounts "github.com/docker/docker/volume/mounts"
 	"github.com/moby/sys/mount"
 	"github.com/opencontainers/selinux/go-selinux/label"
@@ -129,34 +127,11 @@ func (container *Container) NetworkMounts() []Mount {
 }
 
 // CopyImagePathContent copies files in destination to the volume.
-func (container *Container) CopyImagePathContent(v volume.Volume, destination string) error {
-	rootfs, err := container.GetResourcePath(destination)
-	if err != nil {
-		return err
-	}
-
-	if _, err := os.Stat(rootfs); err != nil {
-		if os.IsNotExist(err) {
-			return nil
-		}
-		return err
-	}
-
-	id := stringid.GenerateRandomID()
-	path, err := v.Mount(id)
-	if err != nil {
-		return err
-	}
-
-	defer func() {
-		if err := v.Unmount(id); err != nil {
-			log.G(context.TODO()).Warnf("error while unmounting volume %s: %v", v.Name(), err)
-		}
-	}()
-	if err := label.Relabel(path, container.MountLabel, true); err != nil && !errors.Is(err, syscall.ENOTSUP) {
+func (container *Container) CopyImagePathContent(volumePath, destination string) error {
+	if err := label.Relabel(volumePath, container.MountLabel, true); err != nil && !errors.Is(err, syscall.ENOTSUP) {
 		return err
 	}
-	return copyExistingContents(rootfs, path)
+	return copyExistingContents(destination, volumePath)
 }
 
 // ShmResourcePath returns path to shm

+ 36 - 2
daemon/create_unix.go

@@ -12,9 +12,12 @@ import (
 	containertypes "github.com/docker/docker/api/types/container"
 	mounttypes "github.com/docker/docker/api/types/mount"
 	"github.com/docker/docker/container"
+	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/oci"
+	volumemounts "github.com/docker/docker/volume/mounts"
 	volumeopts "github.com/docker/docker/volume/service/opts"
 	"github.com/opencontainers/selinux/go-selinux/label"
+	"github.com/pkg/errors"
 )
 
 // createContainerOSSpecificSettings performs host-OS specific container create functionality
@@ -85,10 +88,41 @@ func (daemon *Daemon) populateVolumes(c *container.Container) error {
 			continue
 		}
 
-		log.G(context.TODO()).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 {
+		if err := daemon.populateVolume(c, mnt); err != nil {
 			return err
 		}
 	}
 	return nil
 }
+
+func (daemon *Daemon) populateVolume(c *container.Container, mnt *volumemounts.MountPoint) error {
+	ctrDestPath, err := c.GetResourcePath(mnt.Destination)
+	if err != nil {
+		return err
+	}
+
+	if _, err := os.Stat(ctrDestPath); err != nil {
+		if os.IsNotExist(err) {
+			return nil
+		}
+		return err
+	}
+
+	volumePath, cleanup, err := mnt.Setup(c.MountLabel, daemon.idMapping.RootPair(), nil)
+	if err != nil {
+		if errdefs.IsNotFound(err) {
+			return nil
+		}
+		log.G(context.TODO()).WithError(err).Debugf("can't copy data from %s:%s, to %s", c.ID, mnt.Destination, volumePath)
+		return errors.Wrapf(err, "failed to populate volume")
+	}
+	defer mnt.Cleanup()
+	defer cleanup()
+
+	log.G(context.TODO()).Debugf("copying image data from %s:%s, to %s", c.ID, mnt.Destination, volumePath)
+	if err := c.CopyImagePathContent(volumePath, ctrDestPath); err != nil {
+		return err
+	}
+
+	return nil
+}