diff --git a/daemon/volumes.go b/daemon/volumes.go index 03bfda6f5d..d5d31b260c 100644 --- a/daemon/volumes.go +++ b/daemon/volumes.go @@ -207,6 +207,9 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo }); ok { mp.Source = cv.CachedPath() } + if mp.Driver == volume.DefaultDriverName { + setBindModeIfNull(mp) + } } binds[mp.Destination] = true diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index 173d5f80b0..cd3566f4b4 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -11,6 +11,7 @@ import ( "os" "path/filepath" "regexp" + "runtime" "strconv" "strings" "time" @@ -1901,33 +1902,37 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *check.C) { } type testCase struct { - cfg mounttypes.Mount + spec mounttypes.Mount expected types.MountPoint } + var selinuxSharedLabel string + if runtime.GOOS == "linux" { + selinuxSharedLabel = "z" + } + cases := []testCase{ // use literal strings here for `Type` instead of the defined constants in the volume package to keep this honest // Validation of the actual `Mount` struct is done in another test is not needed here - {mounttypes.Mount{Type: "volume", Target: destPath}, types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath}}, - {mounttypes.Mount{Type: "volume", Target: destPath + slash}, types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath}}, - {mounttypes.Mount{Type: "volume", Target: destPath, Source: "test1"}, types.MountPoint{Type: "volume", Name: "test1", RW: true, Destination: destPath}}, - {mounttypes.Mount{Type: "volume", Target: destPath, ReadOnly: true, Source: "test2"}, types.MountPoint{Type: "volume", Name: "test2", RW: false, Destination: destPath}}, { - mounttypes.Mount{ - Type: "volume", - Target: destPath, - Source: "test3", - VolumeOptions: &mounttypes.VolumeOptions{ - DriverConfig: &mounttypes.Driver{Name: volume.DefaultDriverName}, - }, - }, - types.MountPoint{ - Driver: volume.DefaultDriverName, - Type: "volume", - Name: "test3", - RW: true, - Destination: destPath, - }, + spec: mounttypes.Mount{Type: "volume", Target: destPath}, + expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel}, + }, + { + spec: mounttypes.Mount{Type: "volume", Target: destPath + slash}, + expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel}, + }, + { + spec: mounttypes.Mount{Type: "volume", Target: destPath, Source: "test1"}, + expected: types.MountPoint{Type: "volume", Name: "test1", RW: true, Destination: destPath, Mode: selinuxSharedLabel}, + }, + { + spec: mounttypes.Mount{Type: "volume", Target: destPath, ReadOnly: true, Source: "test2"}, + expected: types.MountPoint{Type: "volume", Name: "test2", RW: false, Destination: destPath, Mode: selinuxSharedLabel}, + }, + { + spec: mounttypes.Mount{Type: "volume", Target: destPath, Source: "test3", VolumeOptions: &mounttypes.VolumeOptions{DriverConfig: &mounttypes.Driver{Name: volume.DefaultDriverName}}}, + expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", Name: "test3", RW: true, Destination: destPath, Mode: selinuxSharedLabel}, }, } @@ -1938,19 +1943,22 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *check.C) { defer os.RemoveAll(tmpDir1) cases = append(cases, []testCase{ { - mounttypes.Mount{ + spec: mounttypes.Mount{ Type: "bind", Source: tmpDir1, Target: destPath, }, - types.MountPoint{ + expected: types.MountPoint{ Type: "bind", RW: true, Destination: destPath, Source: tmpDir1, }, }, - {mounttypes.Mount{Type: "bind", Source: tmpDir1, Target: destPath, ReadOnly: true}, types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir1}}, + { + spec: mounttypes.Mount{Type: "bind", Source: tmpDir1, Target: destPath, ReadOnly: true}, + expected: types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir1}, + }, }...) // for modes only supported on Linux @@ -1963,19 +1971,40 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *check.C) { c.Assert(mount.ForceMount("", tmpDir3, "none", "shared"), checker.IsNil) cases = append(cases, []testCase{ - {mounttypes.Mount{Type: "bind", Source: tmpDir3, Target: destPath}, types.MountPoint{Type: "bind", RW: true, Destination: destPath, Source: tmpDir3}}, - {mounttypes.Mount{Type: "bind", Source: tmpDir3, Target: destPath, ReadOnly: true}, types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir3}}, - {mounttypes.Mount{Type: "bind", Source: tmpDir3, Target: destPath, ReadOnly: true, BindOptions: &mounttypes.BindOptions{Propagation: "shared"}}, types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir3, Propagation: "shared"}}, + { + spec: mounttypes.Mount{Type: "bind", Source: tmpDir3, Target: destPath}, + expected: types.MountPoint{Type: "bind", RW: true, Destination: destPath, Source: tmpDir3}, + }, + { + spec: mounttypes.Mount{Type: "bind", Source: tmpDir3, Target: destPath, ReadOnly: true}, + expected: types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir3}, + }, + { + spec: mounttypes.Mount{Type: "bind", Source: tmpDir3, Target: destPath, ReadOnly: true, BindOptions: &mounttypes.BindOptions{Propagation: "shared"}}, + expected: types.MountPoint{Type: "bind", RW: false, Destination: destPath, Source: tmpDir3, Propagation: "shared"}, + }, }...) } } if testEnv.DaemonPlatform() != "windows" { // Windows does not support volume populate cases = append(cases, []testCase{ - {mounttypes.Mount{Type: "volume", Target: destPath, VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}}, types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath}}, - {mounttypes.Mount{Type: "volume", Target: destPath + slash, VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}}, types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath}}, - {mounttypes.Mount{Type: "volume", Target: destPath, Source: "test4", VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}}, types.MountPoint{Type: "volume", Name: "test4", RW: true, Destination: destPath}}, - {mounttypes.Mount{Type: "volume", Target: destPath, Source: "test5", ReadOnly: true, VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}}, types.MountPoint{Type: "volume", Name: "test5", RW: false, Destination: destPath}}, + { + spec: mounttypes.Mount{Type: "volume", Target: destPath, VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}}, + expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel}, + }, + { + spec: mounttypes.Mount{Type: "volume", Target: destPath + slash, VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}}, + expected: types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", RW: true, Destination: destPath, Mode: selinuxSharedLabel}, + }, + { + spec: mounttypes.Mount{Type: "volume", Target: destPath, Source: "test4", VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}}, + expected: types.MountPoint{Type: "volume", Name: "test4", RW: true, Destination: destPath, Mode: selinuxSharedLabel}, + }, + { + spec: mounttypes.Mount{Type: "volume", Target: destPath, Source: "test5", ReadOnly: true, VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}}, + expected: types.MountPoint{Type: "volume", Name: "test5", RW: false, Destination: destPath, Mode: selinuxSharedLabel}, + }, }...) } @@ -1990,11 +2019,11 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *check.C) { ctx := context.Background() apiclient := testEnv.APIClient() for i, x := range cases { - c.Logf("case %d - config: %v", i, x.cfg) + c.Logf("case %d - config: %v", i, x.spec) container, err := apiclient.ContainerCreate( ctx, &containertypes.Config{Image: testImg}, - &containertypes.HostConfig{Mounts: []mounttypes.Mount{x.cfg}}, + &containertypes.HostConfig{Mounts: []mounttypes.Mount{x.spec}}, &networktypes.NetworkingConfig{}, "") require.NoError(c, err) @@ -2035,12 +2064,12 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *check.C) { switch { // Named volumes still exist after the container is removed - case x.cfg.Type == "volume" && len(x.cfg.Source) > 0: + case x.spec.Type == "volume" && len(x.spec.Source) > 0: _, err := apiclient.VolumeInspect(ctx, mountPoint.Name) require.NoError(c, err) // Bind mounts are never removed with the container - case x.cfg.Type == "bind": + case x.spec.Type == "bind": // anonymous volumes are removed default: diff --git a/volume/local/local.go b/volume/local/local.go index c85122d63a..b37c45e61e 100644 --- a/volume/local/local.go +++ b/volume/local/local.go @@ -334,6 +334,11 @@ func (v *localVolume) Path() string { return v.path } +// CachedPath returns the data location +func (v *localVolume) CachedPath() string { + return v.path +} + // Mount implements the localVolume interface, returning the data location. // If there are any provided mount options, the resources will be mounted at this point func (v *localVolume) Mount(id string) (string, error) {