Fix: https://github.com/moby/moby/issues/34307
Signed-off-by: Chen Min <chenmin46@huawei.com>
... | ... |
@@ -64,6 +64,10 @@ const ( |
64 | 64 |
cgroupSystemdDriver = "systemd" |
65 | 65 |
) |
66 | 66 |
|
67 |
+type containerGetter interface { |
|
68 |
+ GetContainer(string) (*container.Container, error) |
|
69 |
+} |
|
70 |
+ |
|
67 | 71 |
func getMemoryResources(config containertypes.Resources) *specs.LinuxMemory { |
68 | 72 |
memory := specs.LinuxMemory{} |
69 | 73 |
|
... | ... |
@@ -285,6 +289,8 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf |
285 | 285 |
hostConfig.IpcMode = containertypes.IpcMode(m) |
286 | 286 |
} |
287 | 287 |
|
288 |
+ adaptSharedNamespaceContainer(daemon, hostConfig) |
|
289 |
+ |
|
288 | 290 |
var err error |
289 | 291 |
opts, err := daemon.generateSecurityOpt(hostConfig) |
290 | 292 |
if err != nil { |
... | ... |
@@ -299,6 +305,36 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf |
299 | 299 |
return nil |
300 | 300 |
} |
301 | 301 |
|
302 |
+// adaptSharedNamespaceContainer replaces container name with its ID in hostConfig. |
|
303 |
+// To be more precisely, it modifies `container:name` to `container:ID` of PidMode, IpcMode |
|
304 |
+// and NetworkMode. |
|
305 |
+// |
|
306 |
+// When a container shares its namespace with another container, use ID can keep the namespace |
|
307 |
+// sharing connection between the two containers even the another container is renamed. |
|
308 |
+func adaptSharedNamespaceContainer(daemon containerGetter, hostConfig *containertypes.HostConfig) { |
|
309 |
+ containerPrefix := "container:" |
|
310 |
+ if hostConfig.PidMode.IsContainer() { |
|
311 |
+ pidContainer := hostConfig.PidMode.Container() |
|
312 |
+ // if there is any error returned here, we just ignore it and leave it to be |
|
313 |
+ // handled in the following logic |
|
314 |
+ if c, err := daemon.GetContainer(pidContainer); err == nil { |
|
315 |
+ hostConfig.PidMode = containertypes.PidMode(containerPrefix + c.ID) |
|
316 |
+ } |
|
317 |
+ } |
|
318 |
+ if hostConfig.IpcMode.IsContainer() { |
|
319 |
+ ipcContainer := hostConfig.IpcMode.Container() |
|
320 |
+ if c, err := daemon.GetContainer(ipcContainer); err == nil { |
|
321 |
+ hostConfig.IpcMode = containertypes.IpcMode(containerPrefix + c.ID) |
|
322 |
+ } |
|
323 |
+ } |
|
324 |
+ if hostConfig.NetworkMode.IsContainer() { |
|
325 |
+ netContainer := hostConfig.NetworkMode.ConnectedContainer() |
|
326 |
+ if c, err := daemon.GetContainer(netContainer); err == nil { |
|
327 |
+ hostConfig.NetworkMode = containertypes.NetworkMode(containerPrefix + c.ID) |
|
328 |
+ } |
|
329 |
+ } |
|
330 |
+} |
|
331 |
+ |
|
302 | 332 |
func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo, update bool) ([]string, error) { |
303 | 333 |
warnings := []string{} |
304 | 334 |
fixMemorySwappiness(resources) |
... | ... |
@@ -3,6 +3,7 @@ |
3 | 3 |
package daemon |
4 | 4 |
|
5 | 5 |
import ( |
6 |
+ "errors" |
|
6 | 7 |
"io/ioutil" |
7 | 8 |
"os" |
8 | 9 |
"path/filepath" |
... | ... |
@@ -18,6 +19,44 @@ import ( |
18 | 18 |
"github.com/docker/docker/volume/store" |
19 | 19 |
) |
20 | 20 |
|
21 |
+type fakeContainerGetter struct { |
|
22 |
+ containers map[string]*container.Container |
|
23 |
+} |
|
24 |
+ |
|
25 |
+func (f *fakeContainerGetter) GetContainer(cid string) (*container.Container, error) { |
|
26 |
+ container, ok := f.containers[cid] |
|
27 |
+ if !ok { |
|
28 |
+ return nil, errors.New("container not found") |
|
29 |
+ } |
|
30 |
+ return container, nil |
|
31 |
+} |
|
32 |
+ |
|
33 |
+// Unix test as uses settings which are not available on Windows |
|
34 |
+func TestAdjustSharedNamespaceContainerName(t *testing.T) { |
|
35 |
+ fakeID := "abcdef1234567890" |
|
36 |
+ hostConfig := &containertypes.HostConfig{ |
|
37 |
+ IpcMode: containertypes.IpcMode("container:base"), |
|
38 |
+ PidMode: containertypes.PidMode("container:base"), |
|
39 |
+ NetworkMode: containertypes.NetworkMode("container:base"), |
|
40 |
+ } |
|
41 |
+ containerStore := &fakeContainerGetter{} |
|
42 |
+ containerStore.containers = make(map[string]*container.Container) |
|
43 |
+ containerStore.containers["base"] = &container.Container{ |
|
44 |
+ ID: fakeID, |
|
45 |
+ } |
|
46 |
+ |
|
47 |
+ adaptSharedNamespaceContainer(containerStore, hostConfig) |
|
48 |
+ if hostConfig.IpcMode != containertypes.IpcMode("container:"+fakeID) { |
|
49 |
+ t.Errorf("Expected IpcMode to be container:%s", fakeID) |
|
50 |
+ } |
|
51 |
+ if hostConfig.PidMode != containertypes.PidMode("container:"+fakeID) { |
|
52 |
+ t.Errorf("Expected PidMode to be container:%s", fakeID) |
|
53 |
+ } |
|
54 |
+ if hostConfig.NetworkMode != containertypes.NetworkMode("container:"+fakeID) { |
|
55 |
+ t.Errorf("Expected NetworkMode to be container:%s", fakeID) |
|
56 |
+ } |
|
57 |
+} |
|
58 |
+ |
|
21 | 59 |
// Unix test as uses settings which are not available on Windows |
22 | 60 |
func TestAdjustCPUShares(t *testing.T) { |
23 | 61 |
tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-") |