ipc: Share /dev/shm and /dev/mqueue when --ipc container:<id/name> is used
| ... | ... |
@@ -293,10 +293,17 @@ func (container *Container) Start() (err error) {
|
| 293 | 293 |
return err |
| 294 | 294 |
} |
| 295 | 295 |
|
| 296 |
+ if !(container.hostConfig.IpcMode.IsContainer() || container.hostConfig.IpcMode.IsHost()) {
|
|
| 297 |
+ if err := container.setupIpcDirs(); err != nil {
|
|
| 298 |
+ return err |
|
| 299 |
+ } |
|
| 300 |
+ } |
|
| 301 |
+ |
|
| 296 | 302 |
mounts, err := container.setupMounts() |
| 297 | 303 |
if err != nil {
|
| 298 | 304 |
return err |
| 299 | 305 |
} |
| 306 |
+ mounts = append(mounts, container.ipcMounts()...) |
|
| 300 | 307 |
|
| 301 | 308 |
container.command.Mounts = mounts |
| 302 | 309 |
return container.waitForStart() |
| ... | ... |
@@ -355,6 +362,10 @@ func (container *Container) isNetworkAllocated() bool {
|
| 355 | 355 |
func (container *Container) cleanup() {
|
| 356 | 356 |
container.ReleaseNetwork() |
| 357 | 357 |
|
| 358 |
+ if err := container.unmountIpcMounts(); err != nil {
|
|
| 359 |
+ logrus.Errorf("%v: Failed to umount ipc filesystems: %v", container.ID, err)
|
|
| 360 |
+ } |
|
| 361 |
+ |
|
| 358 | 362 |
if err := container.Unmount(); err != nil {
|
| 359 | 363 |
logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err)
|
| 360 | 364 |
} |
| ... | ... |
@@ -45,6 +45,8 @@ type Container struct {
|
| 45 | 45 |
AppArmorProfile string |
| 46 | 46 |
HostnamePath string |
| 47 | 47 |
HostsPath string |
| 48 |
+ ShmPath string |
|
| 49 |
+ MqueuePath string |
|
| 48 | 50 |
MountPoints map[string]*mountPoint |
| 49 | 51 |
ResolvConfPath string |
| 50 | 52 |
UpdateDns bool |
| ... | ... |
@@ -184,6 +186,16 @@ func populateCommand(c *Container, env []string) error {
|
| 184 | 184 |
} |
| 185 | 185 |
|
| 186 | 186 |
ipc := &execdriver.Ipc{}
|
| 187 |
+ var err error |
|
| 188 |
+ c.ShmPath, err = c.shmPath() |
|
| 189 |
+ if err != nil {
|
|
| 190 |
+ return err |
|
| 191 |
+ } |
|
| 192 |
+ |
|
| 193 |
+ c.MqueuePath, err = c.mqueuePath() |
|
| 194 |
+ if err != nil {
|
|
| 195 |
+ return err |
|
| 196 |
+ } |
|
| 187 | 197 |
|
| 188 | 198 |
if c.hostConfig.IpcMode.IsContainer() {
|
| 189 | 199 |
ic, err := c.getIpcContainer() |
| ... | ... |
@@ -191,8 +203,14 @@ func populateCommand(c *Container, env []string) error {
|
| 191 | 191 |
return err |
| 192 | 192 |
} |
| 193 | 193 |
ipc.ContainerID = ic.ID |
| 194 |
+ c.ShmPath = ic.ShmPath |
|
| 195 |
+ c.MqueuePath = ic.MqueuePath |
|
| 194 | 196 |
} else {
|
| 195 | 197 |
ipc.HostIpc = c.hostConfig.IpcMode.IsHost() |
| 198 |
+ if ipc.HostIpc {
|
|
| 199 |
+ c.ShmPath = "/dev/shm" |
|
| 200 |
+ c.MqueuePath = "/dev/mqueue" |
|
| 201 |
+ } |
|
| 196 | 202 |
} |
| 197 | 203 |
|
| 198 | 204 |
pid := &execdriver.Pid{}
|
| ... | ... |
@@ -1199,3 +1217,85 @@ func (container *Container) removeMountPoints() error {
|
| 1199 | 1199 |
} |
| 1200 | 1200 |
return nil |
| 1201 | 1201 |
} |
| 1202 |
+ |
|
| 1203 |
+func (container *Container) shmPath() (string, error) {
|
|
| 1204 |
+ return container.GetRootResourcePath("shm")
|
|
| 1205 |
+} |
|
| 1206 |
+func (container *Container) mqueuePath() (string, error) {
|
|
| 1207 |
+ return container.GetRootResourcePath("mqueue")
|
|
| 1208 |
+} |
|
| 1209 |
+ |
|
| 1210 |
+func (container *Container) setupIpcDirs() error {
|
|
| 1211 |
+ shmPath, err := container.shmPath() |
|
| 1212 |
+ if err != nil {
|
|
| 1213 |
+ return err |
|
| 1214 |
+ } |
|
| 1215 |
+ |
|
| 1216 |
+ if err := os.MkdirAll(shmPath, 0700); err != nil {
|
|
| 1217 |
+ return err |
|
| 1218 |
+ } |
|
| 1219 |
+ |
|
| 1220 |
+ if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel("mode=1777,size=65536k", container.GetMountLabel())); err != nil {
|
|
| 1221 |
+ return fmt.Errorf("mounting shm tmpfs: %s", err)
|
|
| 1222 |
+ } |
|
| 1223 |
+ |
|
| 1224 |
+ mqueuePath, err := container.mqueuePath() |
|
| 1225 |
+ if err != nil {
|
|
| 1226 |
+ return err |
|
| 1227 |
+ } |
|
| 1228 |
+ |
|
| 1229 |
+ if err := os.MkdirAll(mqueuePath, 0700); err != nil {
|
|
| 1230 |
+ return err |
|
| 1231 |
+ } |
|
| 1232 |
+ |
|
| 1233 |
+ if err := syscall.Mount("mqueue", mqueuePath, "mqueue", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), ""); err != nil {
|
|
| 1234 |
+ return fmt.Errorf("mounting mqueue mqueue : %s", err)
|
|
| 1235 |
+ } |
|
| 1236 |
+ |
|
| 1237 |
+ return nil |
|
| 1238 |
+} |
|
| 1239 |
+ |
|
| 1240 |
+func (container *Container) unmountIpcMounts() error {
|
|
| 1241 |
+ if container.hostConfig.IpcMode.IsContainer() || container.hostConfig.IpcMode.IsHost() {
|
|
| 1242 |
+ return nil |
|
| 1243 |
+ } |
|
| 1244 |
+ |
|
| 1245 |
+ shmPath, err := container.shmPath() |
|
| 1246 |
+ if err != nil {
|
|
| 1247 |
+ return fmt.Errorf("shm path does not exist %v", err)
|
|
| 1248 |
+ } |
|
| 1249 |
+ |
|
| 1250 |
+ if err := syscall.Unmount(shmPath, syscall.MNT_DETACH); err != nil {
|
|
| 1251 |
+ return fmt.Errorf("failed to umount %s filesystem %v", shmPath, err)
|
|
| 1252 |
+ } |
|
| 1253 |
+ |
|
| 1254 |
+ mqueuePath, err := container.mqueuePath() |
|
| 1255 |
+ if err != nil {
|
|
| 1256 |
+ return fmt.Errorf("mqueue path does not exist %v", err)
|
|
| 1257 |
+ } |
|
| 1258 |
+ |
|
| 1259 |
+ if err := syscall.Unmount(mqueuePath, syscall.MNT_DETACH); err != nil {
|
|
| 1260 |
+ return fmt.Errorf("failed to umount %s filesystem %v", mqueuePath, err)
|
|
| 1261 |
+ } |
|
| 1262 |
+ |
|
| 1263 |
+ return nil |
|
| 1264 |
+} |
|
| 1265 |
+ |
|
| 1266 |
+func (container *Container) ipcMounts() []execdriver.Mount {
|
|
| 1267 |
+ var mounts []execdriver.Mount |
|
| 1268 |
+ label.SetFileLabel(container.ShmPath, container.MountLabel) |
|
| 1269 |
+ mounts = append(mounts, execdriver.Mount{
|
|
| 1270 |
+ Source: container.ShmPath, |
|
| 1271 |
+ Destination: "/dev/shm", |
|
| 1272 |
+ Writable: true, |
|
| 1273 |
+ Private: true, |
|
| 1274 |
+ }) |
|
| 1275 |
+ label.SetFileLabel(container.MqueuePath, container.MountLabel) |
|
| 1276 |
+ mounts = append(mounts, execdriver.Mount{
|
|
| 1277 |
+ Source: container.MqueuePath, |
|
| 1278 |
+ Destination: "/dev/mqueue", |
|
| 1279 |
+ Writable: true, |
|
| 1280 |
+ Private: true, |
|
| 1281 |
+ }) |
|
| 1282 |
+ return mounts |
|
| 1283 |
+} |
| ... | ... |
@@ -172,3 +172,15 @@ func (container *Container) prepareMountPoints() error {
|
| 172 | 172 |
func (container *Container) removeMountPoints() error {
|
| 173 | 173 |
return nil |
| 174 | 174 |
} |
| 175 |
+ |
|
| 176 |
+func (container *Container) setupIpcDirs() error {
|
|
| 177 |
+ return nil |
|
| 178 |
+} |
|
| 179 |
+ |
|
| 180 |
+func (container *Container) unmountIpcMounts() error {
|
|
| 181 |
+ return nil |
|
| 182 |
+} |
|
| 183 |
+ |
|
| 184 |
+func (container *Container) ipcMounts() []execdriver.Mount {
|
|
| 185 |
+ return nil |
|
| 186 |
+} |
| ... | ... |
@@ -746,6 +746,10 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo |
| 746 | 746 |
return nil, err |
| 747 | 747 |
} |
| 748 | 748 |
|
| 749 |
+ if err := d.cleanupMounts(); err != nil {
|
|
| 750 |
+ return nil, err |
|
| 751 |
+ } |
|
| 752 |
+ |
|
| 749 | 753 |
return d, nil |
| 750 | 754 |
} |
| 751 | 755 |
|
| ... | ... |
@@ -791,6 +795,10 @@ func (daemon *Daemon) Shutdown() error {
|
| 791 | 791 |
} |
| 792 | 792 |
} |
| 793 | 793 |
|
| 794 |
+ if err := daemon.cleanupMounts(); err != nil {
|
|
| 795 |
+ return err |
|
| 796 |
+ } |
|
| 797 |
+ |
|
| 794 | 798 |
return nil |
| 795 | 799 |
} |
| 796 | 800 |
|
| 797 | 801 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,44 @@ |
| 0 |
+package daemon |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bufio" |
|
| 4 |
+ "os" |
|
| 5 |
+ "path/filepath" |
|
| 6 |
+ "strings" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/Sirupsen/logrus" |
|
| 9 |
+ "github.com/docker/docker/pkg/mount" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+// cleanupMounts umounts shm/mqueue mounts for old containers |
|
| 13 |
+func (daemon *Daemon) cleanupMounts() error {
|
|
| 14 |
+ logrus.Debugf("Cleaning up old shm/mqueue mounts: start.")
|
|
| 15 |
+ f, err := os.Open("/proc/self/mountinfo")
|
|
| 16 |
+ if err != nil {
|
|
| 17 |
+ return err |
|
| 18 |
+ } |
|
| 19 |
+ defer f.Close() |
|
| 20 |
+ |
|
| 21 |
+ sc := bufio.NewScanner(f) |
|
| 22 |
+ for sc.Scan() {
|
|
| 23 |
+ line := sc.Text() |
|
| 24 |
+ fields := strings.Split(line, " ") |
|
| 25 |
+ if strings.HasPrefix(fields[4], daemon.repository) {
|
|
| 26 |
+ mnt := fields[4] |
|
| 27 |
+ mountBase := filepath.Base(mnt) |
|
| 28 |
+ if mountBase == "mqueue" || mountBase == "shm" {
|
|
| 29 |
+ logrus.Debugf("Unmounting %+v", mnt)
|
|
| 30 |
+ if err := mount.Unmount(mnt); err != nil {
|
|
| 31 |
+ return err |
|
| 32 |
+ } |
|
| 33 |
+ } |
|
| 34 |
+ } |
|
| 35 |
+ } |
|
| 36 |
+ |
|
| 37 |
+ if err := sc.Err(); err != nil {
|
|
| 38 |
+ return err |
|
| 39 |
+ } |
|
| 40 |
+ |
|
| 41 |
+ logrus.Debugf("Cleaning up old shm/mqueue mounts: done.")
|
|
| 42 |
+ return nil |
|
| 43 |
+} |
| ... | ... |
@@ -62,19 +62,6 @@ func New() *configs.Config {
|
| 62 | 62 |
Data: "newinstance,ptmxmode=0666,mode=0620,gid=5", |
| 63 | 63 |
}, |
| 64 | 64 |
{
|
| 65 |
- Device: "tmpfs", |
|
| 66 |
- Source: "shm", |
|
| 67 |
- Destination: "/dev/shm", |
|
| 68 |
- Data: "mode=1777,size=65536k", |
|
| 69 |
- Flags: defaultMountFlags, |
|
| 70 |
- }, |
|
| 71 |
- {
|
|
| 72 |
- Source: "mqueue", |
|
| 73 |
- Destination: "/dev/mqueue", |
|
| 74 |
- Device: "mqueue", |
|
| 75 |
- Flags: defaultMountFlags, |
|
| 76 |
- }, |
|
| 77 |
- {
|
|
| 78 | 65 |
Source: "sysfs", |
| 79 | 66 |
Destination: "/sys", |
| 80 | 67 |
Device: "sysfs", |
| ... | ... |
@@ -1889,7 +1889,7 @@ func (s *DockerSuite) TestRunModeIpcHost(c *check.C) {
|
| 1889 | 1889 |
func (s *DockerSuite) TestRunModeIpcContainer(c *check.C) {
|
| 1890 | 1890 |
testRequires(c, SameHostDaemon) |
| 1891 | 1891 |
|
| 1892 |
- out, _ := dockerCmd(c, "run", "-d", "busybox", "top") |
|
| 1892 |
+ out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "echo -n test > /dev/shm/test && top") |
|
| 1893 | 1893 |
|
| 1894 | 1894 |
id := strings.TrimSpace(out) |
| 1895 | 1895 |
state, err := inspectField(id, "State.Running") |
| ... | ... |
@@ -1910,6 +1910,11 @@ func (s *DockerSuite) TestRunModeIpcContainer(c *check.C) {
|
| 1910 | 1910 |
if parentContainerIpc != out {
|
| 1911 | 1911 |
c.Fatalf("IPC different with --ipc=container:%s %s != %s\n", id, parentContainerIpc, out)
|
| 1912 | 1912 |
} |
| 1913 |
+ |
|
| 1914 |
+ catOutput, _ := dockerCmd(c, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "cat", "/dev/shm/test")
|
|
| 1915 |
+ if catOutput != "test" {
|
|
| 1916 |
+ c.Fatalf("Output of /dev/shm/test expected test but found: %s", catOutput)
|
|
| 1917 |
+ } |
|
| 1913 | 1918 |
} |
| 1914 | 1919 |
|
| 1915 | 1920 |
func (s *DockerSuite) TestRunModeIpcContainerNotExists(c *check.C) {
|