mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #35467 from kolyshkin/dup-mnt
Fix "duplicate mount point" when --tmpfs /dev/shm is used
This commit is contained in:
commit
d032264e13
2 changed files with 68 additions and 10 deletions
|
@ -65,12 +65,11 @@ func (container *Container) NetworkMounts() []Mount {
|
||||||
if _, err := os.Stat(container.ResolvConfPath); err != nil {
|
if _, err := os.Stat(container.ResolvConfPath); err != nil {
|
||||||
logrus.Warnf("ResolvConfPath set to %q, but can't stat this filename (err = %v); skipping", container.ResolvConfPath, err)
|
logrus.Warnf("ResolvConfPath set to %q, but can't stat this filename (err = %v); skipping", container.ResolvConfPath, err)
|
||||||
} else {
|
} else {
|
||||||
if !container.HasMountFor("/etc/resolv.conf") {
|
|
||||||
label.Relabel(container.ResolvConfPath, container.MountLabel, shared)
|
|
||||||
}
|
|
||||||
writable := !container.HostConfig.ReadonlyRootfs
|
writable := !container.HostConfig.ReadonlyRootfs
|
||||||
if m, exists := container.MountPoints["/etc/resolv.conf"]; exists {
|
if m, exists := container.MountPoints["/etc/resolv.conf"]; exists {
|
||||||
writable = m.RW
|
writable = m.RW
|
||||||
|
} else {
|
||||||
|
label.Relabel(container.ResolvConfPath, container.MountLabel, shared)
|
||||||
}
|
}
|
||||||
mounts = append(mounts, Mount{
|
mounts = append(mounts, Mount{
|
||||||
Source: container.ResolvConfPath,
|
Source: container.ResolvConfPath,
|
||||||
|
@ -84,12 +83,11 @@ func (container *Container) NetworkMounts() []Mount {
|
||||||
if _, err := os.Stat(container.HostnamePath); err != nil {
|
if _, err := os.Stat(container.HostnamePath); err != nil {
|
||||||
logrus.Warnf("HostnamePath set to %q, but can't stat this filename (err = %v); skipping", container.HostnamePath, err)
|
logrus.Warnf("HostnamePath set to %q, but can't stat this filename (err = %v); skipping", container.HostnamePath, err)
|
||||||
} else {
|
} else {
|
||||||
if !container.HasMountFor("/etc/hostname") {
|
|
||||||
label.Relabel(container.HostnamePath, container.MountLabel, shared)
|
|
||||||
}
|
|
||||||
writable := !container.HostConfig.ReadonlyRootfs
|
writable := !container.HostConfig.ReadonlyRootfs
|
||||||
if m, exists := container.MountPoints["/etc/hostname"]; exists {
|
if m, exists := container.MountPoints["/etc/hostname"]; exists {
|
||||||
writable = m.RW
|
writable = m.RW
|
||||||
|
} else {
|
||||||
|
label.Relabel(container.HostnamePath, container.MountLabel, shared)
|
||||||
}
|
}
|
||||||
mounts = append(mounts, Mount{
|
mounts = append(mounts, Mount{
|
||||||
Source: container.HostnamePath,
|
Source: container.HostnamePath,
|
||||||
|
@ -103,12 +101,11 @@ func (container *Container) NetworkMounts() []Mount {
|
||||||
if _, err := os.Stat(container.HostsPath); err != nil {
|
if _, err := os.Stat(container.HostsPath); err != nil {
|
||||||
logrus.Warnf("HostsPath set to %q, but can't stat this filename (err = %v); skipping", container.HostsPath, err)
|
logrus.Warnf("HostsPath set to %q, but can't stat this filename (err = %v); skipping", container.HostsPath, err)
|
||||||
} else {
|
} else {
|
||||||
if !container.HasMountFor("/etc/hosts") {
|
|
||||||
label.Relabel(container.HostsPath, container.MountLabel, shared)
|
|
||||||
}
|
|
||||||
writable := !container.HostConfig.ReadonlyRootfs
|
writable := !container.HostConfig.ReadonlyRootfs
|
||||||
if m, exists := container.MountPoints["/etc/hosts"]; exists {
|
if m, exists := container.MountPoints["/etc/hosts"]; exists {
|
||||||
writable = m.RW
|
writable = m.RW
|
||||||
|
} else {
|
||||||
|
label.Relabel(container.HostsPath, container.MountLabel, shared)
|
||||||
}
|
}
|
||||||
mounts = append(mounts, Mount{
|
mounts = append(mounts, Mount{
|
||||||
Source: container.HostsPath,
|
Source: container.HostsPath,
|
||||||
|
@ -160,7 +157,18 @@ func (container *Container) ShmResourcePath() (string, error) {
|
||||||
// HasMountFor checks if path is a mountpoint
|
// HasMountFor checks if path is a mountpoint
|
||||||
func (container *Container) HasMountFor(path string) bool {
|
func (container *Container) HasMountFor(path string) bool {
|
||||||
_, exists := container.MountPoints[path]
|
_, exists := container.MountPoints[path]
|
||||||
return exists
|
if exists {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also search among the tmpfs mounts
|
||||||
|
for dest := range container.HostConfig.Tmpfs {
|
||||||
|
if dest == path {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmountIpcMount uses the provided unmount function to unmount shm if it was mounted
|
// UnmountIpcMount uses the provided unmount function to unmount shm if it was mounted
|
||||||
|
|
50
daemon/oci_linux_test.go
Normal file
50
daemon/oci_linux_test.go
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
containertypes "github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/container"
|
||||||
|
"github.com/docker/docker/daemon/config"
|
||||||
|
"github.com/docker/docker/oci"
|
||||||
|
"github.com/docker/docker/pkg/idtools"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestTmpfsDevShmNoDupMount checks that a user-specified /dev/shm tmpfs
|
||||||
|
// mount (as in "docker run --tmpfs /dev/shm:rw,size=NNN") does not result
|
||||||
|
// in "Duplicate mount point" error from the engine.
|
||||||
|
// https://github.com/moby/moby/issues/35455
|
||||||
|
func TestTmpfsDevShmNoDupMount(t *testing.T) {
|
||||||
|
d := Daemon{
|
||||||
|
// some empty structs to avoid getting a panic
|
||||||
|
// caused by a null pointer dereference
|
||||||
|
idMappings: &idtools.IDMappings{},
|
||||||
|
configStore: &config.Config{},
|
||||||
|
}
|
||||||
|
c := &container.Container{
|
||||||
|
ShmPath: "foobar", // non-empty, for c.IpcMounts() to work
|
||||||
|
HostConfig: &containertypes.HostConfig{
|
||||||
|
IpcMode: containertypes.IpcMode("shareable"), // default mode
|
||||||
|
// --tmpfs /dev/shm:rw,exec,size=NNN
|
||||||
|
Tmpfs: map[string]string{
|
||||||
|
"/dev/shm": "rw,exec,size=1g",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mimick the code flow of daemon.createSpec(), enough to reproduce the issue
|
||||||
|
ms, err := d.setupMounts(c)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
ms = append(ms, c.IpcMounts()...)
|
||||||
|
|
||||||
|
tmpfsMounts, err := c.TmpfsMounts()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
ms = append(ms, tmpfsMounts...)
|
||||||
|
|
||||||
|
s := oci.DefaultSpec()
|
||||||
|
err = setMounts(&d, &s, c, ms)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue