Skip to content

Commit 10d57fd

Browse files
committed
volume/mounts: fix anonymous volume not being labeled
`Parser.ParseMountRaw()` labels anonymous volumes with a `AnonymousLabel` label (`com.docker.volume.anonymous`) label based on whether a volume has a name (named volume) or no name (anonymous) (see [1]). However both `VolumesService.Create()` (see [1]) and `Parser.ParseMountRaw()` (see [2], [3]) were generating a random name for anonymous volumes. The latter is called before `VolumesService.Create()` is called, resulting in such volumes not being labeled as anonymous. Generating the name was originally done in Create (fc7b904), but duplicated in b3b7eb2 with the introduction of the new Mounts field in HostConfig. Duplicating this effort didn't have a real effect until (`Create` would just skip generating the name), until 618f26c introduced the `AnonymousLabel` in (v24.0.0, backported to v23.0.0). Parsing generally should not fill in defaults / generate names, so this patch; - Removes generating volume names from `Parser.ParseMountRaw()` - Adds a debug-log entry to `VolumesService.Create()` - Touches up some logs to use structured logs for easier correlating logs With this patch applied: docker run --rm --mount=type=volume,target=/toto hello-world DEBU[2024-10-24T22:50:36.359990376Z] creating anonymous volume volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02 DEBU[2024-10-24T22:50:36.360069209Z] probing all drivers for volume volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02 DEBU[2024-10-24T22:50:36.360341209Z] Registering new volume reference driver=local volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02 [1]: https://github.com/moby/moby/blob/032721ff75fe4a71a45b4a7a9b7e7c4c80c6431b/volume/service/service.go#L72-L83 [2]: https://github.com/moby/moby/blob/032721ff75fe4a71a45b4a7a9b7e7c4c80c6431b/volume/mounts/linux_parser.go#L330-L336 [3]: https://github.com/moby/moby/blob/032721ff75fe4a71a45b4a7a9b7e7c4c80c6431b/volume/mounts/windows_parser.go#L394-L400 Signed-off-by: Sebastiaan van Stijn <[email protected]>
1 parent 032721f commit 10d57fd

5 files changed

Lines changed: 39 additions & 9 deletions

File tree

integration/container/mounts_linux_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,37 @@ func TestContainerVolumesMountedAsSlave(t *testing.T) {
393393
}
394394
}
395395

396+
// TestContainerVolumeAnonymous verifies that anonymous volumes created through
397+
// the Mounts API get a random name generated, and have the "AnonymousLabel"
398+
// (com.docker.volume.anonymous) label set.
399+
//
400+
// regression test for https://github.com/moby/moby/issues/48748
401+
func TestContainerVolumeAnonymous(t *testing.T) {
402+
skip.If(t, testEnv.IsRemoteDaemon)
403+
404+
ctx := setupTest(t)
405+
406+
mntOpts := mounttypes.Mount{Type: mounttypes.TypeVolume, Target: "/foo"}
407+
408+
apiClient := testEnv.APIClient()
409+
cID := container.Create(ctx, t, apiClient, container.WithMount(mntOpts))
410+
411+
inspect := container.Inspect(ctx, t, apiClient, cID)
412+
assert.Assert(t, is.Len(inspect.HostConfig.Mounts, 1))
413+
assert.Check(t, is.Equal(inspect.HostConfig.Mounts[0], mntOpts))
414+
415+
assert.Assert(t, is.Len(inspect.Mounts, 1))
416+
volName := inspect.Mounts[0].Name
417+
assert.Check(t, is.Len(volName, 64), "volume name should be 64 bytes (from stringid.GenerateRandomID())")
418+
419+
volInspect, err := apiClient.VolumeInspect(ctx, volName)
420+
assert.NilError(t, err)
421+
422+
// see [daemon.AnonymousLabel]; we don't want to import the daemon package here.
423+
const expectedAnonymousLabel = "com.docker.volume.anonymous"
424+
assert.Check(t, is.Contains(volInspect.Labels, expectedAnonymousLabel))
425+
}
426+
396427
// Regression test for #38995 and #43390.
397428
func TestContainerCopyLeaksMounts(t *testing.T) {
398429
ctx := setupTest(t)

volume/mounts/linux_parser.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"strings"
99

1010
"github.com/docker/docker/api/types/mount"
11-
"github.com/docker/docker/pkg/stringid"
1211
"github.com/docker/docker/volume"
1312
)
1413

@@ -329,9 +328,8 @@ func (p *linuxParser) parseMountSpec(cfg mount.Mount, validateBindSourceExists b
329328

330329
switch cfg.Type {
331330
case mount.TypeVolume:
332-
if cfg.Source == "" {
333-
mp.Name = stringid.GenerateRandomID()
334-
} else {
331+
if cfg.Source != "" {
332+
// non-anonymous volume
335333
mp.Name = cfg.Source
336334
}
337335
mp.CopyData = p.DefaultCopyMode()

volume/mounts/windows_parser.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"strings"
1111

1212
"github.com/docker/docker/api/types/mount"
13-
"github.com/docker/docker/pkg/stringid"
1413
)
1514

1615
// NewWindowsParser creates a parser with Windows semantics.
@@ -393,9 +392,8 @@ func (p *windowsParser) parseMountSpec(cfg mount.Mount, convertTargetToBackslash
393392

394393
switch cfg.Type {
395394
case mount.TypeVolume:
396-
if cfg.Source == "" {
397-
mp.Name = stringid.GenerateRandomID()
398-
} else {
395+
if cfg.Source != "" {
396+
// non-anonymous volume
399397
mp.Name = cfg.Source
400398
}
401399
mp.CopyData = p.DefaultCopyMode()

volume/service/service.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ func (s *VolumesService) Create(ctx context.Context, name, driverName string, op
7373
if name == "" {
7474
name = stringid.GenerateRandomID()
7575
options = append(options, opts.WithCreateLabel(AnonymousLabel, ""))
76+
log.G(ctx).WithField("volume-name", name).Error("Creating anonymous volume")
77+
} else {
78+
log.G(ctx).WithField("volume-name", name).Error("Creating named volume")
7679
}
7780
v, err := s.vs.Create(ctx, name, driverName, options...)
7881
if err != nil {

volume/service/store.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ func (s *VolumeStore) getVolume(ctx context.Context, name, driverName string) (v
732732
return volumeWrapper{vol, meta.Labels, scope, meta.Options}, nil
733733
}
734734

735-
log.G(ctx).Debugf("Probing all drivers for volume with name: %s", name)
735+
log.G(ctx).WithField("volume-name", name).Debugf("Probing all drivers for volume")
736736
drvrs, err := s.drivers.GetAllDrivers()
737737
if err != nil {
738738
return nil, err

0 commit comments

Comments
 (0)