Browse code

daemon/populateVolumes: Support volume subpath

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>

Paweł Gronowski authored on 2023/06/10 03:19:34
Showing 2 changed files
... ...
@@ -15,8 +15,6 @@ import (
15 15
 	"github.com/docker/docker/api/types/events"
16 16
 	mounttypes "github.com/docker/docker/api/types/mount"
17 17
 	swarmtypes "github.com/docker/docker/api/types/swarm"
18
-	"github.com/docker/docker/pkg/stringid"
19
-	"github.com/docker/docker/volume"
20 18
 	volumemounts "github.com/docker/docker/volume/mounts"
21 19
 	"github.com/moby/sys/mount"
22 20
 	"github.com/opencontainers/selinux/go-selinux/label"
... ...
@@ -129,34 +127,11 @@ func (container *Container) NetworkMounts() []Mount {
129 129
 }
130 130
 
131 131
 // CopyImagePathContent copies files in destination to the volume.
132
-func (container *Container) CopyImagePathContent(v volume.Volume, destination string) error {
133
-	rootfs, err := container.GetResourcePath(destination)
134
-	if err != nil {
135
-		return err
136
-	}
137
-
138
-	if _, err := os.Stat(rootfs); err != nil {
139
-		if os.IsNotExist(err) {
140
-			return nil
141
-		}
142
-		return err
143
-	}
144
-
145
-	id := stringid.GenerateRandomID()
146
-	path, err := v.Mount(id)
147
-	if err != nil {
148
-		return err
149
-	}
150
-
151
-	defer func() {
152
-		if err := v.Unmount(id); err != nil {
153
-			log.G(context.TODO()).Warnf("error while unmounting volume %s: %v", v.Name(), err)
154
-		}
155
-	}()
156
-	if err := label.Relabel(path, container.MountLabel, true); err != nil && !errors.Is(err, syscall.ENOTSUP) {
132
+func (container *Container) CopyImagePathContent(volumePath, destination string) error {
133
+	if err := label.Relabel(volumePath, container.MountLabel, true); err != nil && !errors.Is(err, syscall.ENOTSUP) {
157 134
 		return err
158 135
 	}
159
-	return copyExistingContents(rootfs, path)
136
+	return copyExistingContents(destination, volumePath)
160 137
 }
161 138
 
162 139
 // ShmResourcePath returns path to shm
... ...
@@ -12,9 +12,12 @@ import (
12 12
 	containertypes "github.com/docker/docker/api/types/container"
13 13
 	mounttypes "github.com/docker/docker/api/types/mount"
14 14
 	"github.com/docker/docker/container"
15
+	"github.com/docker/docker/errdefs"
15 16
 	"github.com/docker/docker/oci"
17
+	volumemounts "github.com/docker/docker/volume/mounts"
16 18
 	volumeopts "github.com/docker/docker/volume/service/opts"
17 19
 	"github.com/opencontainers/selinux/go-selinux/label"
20
+	"github.com/pkg/errors"
18 21
 )
19 22
 
20 23
 // createContainerOSSpecificSettings performs host-OS specific container create functionality
... ...
@@ -85,10 +88,41 @@ func (daemon *Daemon) populateVolumes(c *container.Container) error {
85 85
 			continue
86 86
 		}
87 87
 
88
-		log.G(context.TODO()).Debugf("copying image data from %s:%s, to %s", c.ID, mnt.Destination, mnt.Name)
89
-		if err := c.CopyImagePathContent(mnt.Volume, mnt.Destination); err != nil {
88
+		if err := daemon.populateVolume(c, mnt); err != nil {
90 89
 			return err
91 90
 		}
92 91
 	}
93 92
 	return nil
94 93
 }
94
+
95
+func (daemon *Daemon) populateVolume(c *container.Container, mnt *volumemounts.MountPoint) error {
96
+	ctrDestPath, err := c.GetResourcePath(mnt.Destination)
97
+	if err != nil {
98
+		return err
99
+	}
100
+
101
+	if _, err := os.Stat(ctrDestPath); err != nil {
102
+		if os.IsNotExist(err) {
103
+			return nil
104
+		}
105
+		return err
106
+	}
107
+
108
+	volumePath, cleanup, err := mnt.Setup(c.MountLabel, daemon.idMapping.RootPair(), nil)
109
+	if err != nil {
110
+		if errdefs.IsNotFound(err) {
111
+			return nil
112
+		}
113
+		log.G(context.TODO()).WithError(err).Debugf("can't copy data from %s:%s, to %s", c.ID, mnt.Destination, volumePath)
114
+		return errors.Wrapf(err, "failed to populate volume")
115
+	}
116
+	defer mnt.Cleanup()
117
+	defer cleanup()
118
+
119
+	log.G(context.TODO()).Debugf("copying image data from %s:%s, to %s", c.ID, mnt.Destination, volumePath)
120
+	if err := c.CopyImagePathContent(volumePath, ctrDestPath); err != nil {
121
+		return err
122
+	}
123
+
124
+	return nil
125
+}