Selaa lähdekoodia

Use ID rather than Name to identify a container when sharing namespace

Fix: https://github.com/moby/moby/issues/34307

Signed-off-by: Chen Min <chenmin46@huawei.com>
Chen Min 8 vuotta sitten
vanhempi
commit
b6e5ea8e57
2 muutettua tiedostoa jossa 75 lisäystä ja 0 poistoa
  1. 36 0
      daemon/daemon_unix.go
  2. 39 0
      daemon/daemon_unix_test.go

+ 36 - 0
daemon/daemon_unix.go

@@ -64,6 +64,10 @@ const (
 	cgroupSystemdDriver = "systemd"
 )
 
+type containerGetter interface {
+	GetContainer(string) (*container.Container, error)
+}
+
 func getMemoryResources(config containertypes.Resources) *specs.LinuxMemory {
 	memory := specs.LinuxMemory{}
 
@@ -285,6 +289,8 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
 		hostConfig.IpcMode = containertypes.IpcMode(m)
 	}
 
+	adaptSharedNamespaceContainer(daemon, hostConfig)
+
 	var err error
 	opts, err := daemon.generateSecurityOpt(hostConfig)
 	if err != nil {
@@ -299,6 +305,36 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
 	return nil
 }
 
+// adaptSharedNamespaceContainer replaces container name with its ID in hostConfig.
+// To be more precisely, it modifies `container:name` to `container:ID` of PidMode, IpcMode
+// and NetworkMode.
+//
+// When a container shares its namespace with another container, use ID can keep the namespace
+// sharing connection between the two containers even the another container is renamed.
+func adaptSharedNamespaceContainer(daemon containerGetter, hostConfig *containertypes.HostConfig) {
+	containerPrefix := "container:"
+	if hostConfig.PidMode.IsContainer() {
+		pidContainer := hostConfig.PidMode.Container()
+		// if there is any error returned here, we just ignore it and leave it to be
+		// handled in the following logic
+		if c, err := daemon.GetContainer(pidContainer); err == nil {
+			hostConfig.PidMode = containertypes.PidMode(containerPrefix + c.ID)
+		}
+	}
+	if hostConfig.IpcMode.IsContainer() {
+		ipcContainer := hostConfig.IpcMode.Container()
+		if c, err := daemon.GetContainer(ipcContainer); err == nil {
+			hostConfig.IpcMode = containertypes.IpcMode(containerPrefix + c.ID)
+		}
+	}
+	if hostConfig.NetworkMode.IsContainer() {
+		netContainer := hostConfig.NetworkMode.ConnectedContainer()
+		if c, err := daemon.GetContainer(netContainer); err == nil {
+			hostConfig.NetworkMode = containertypes.NetworkMode(containerPrefix + c.ID)
+		}
+	}
+}
+
 func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo, update bool) ([]string, error) {
 	warnings := []string{}
 	fixMemorySwappiness(resources)

+ 39 - 0
daemon/daemon_unix_test.go

@@ -3,6 +3,7 @@
 package daemon
 
 import (
+	"errors"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -18,6 +19,44 @@ import (
 	"github.com/docker/docker/volume/store"
 )
 
+type fakeContainerGetter struct {
+	containers map[string]*container.Container
+}
+
+func (f *fakeContainerGetter) GetContainer(cid string) (*container.Container, error) {
+	container, ok := f.containers[cid]
+	if !ok {
+		return nil, errors.New("container not found")
+	}
+	return container, nil
+}
+
+// Unix test as uses settings which are not available on Windows
+func TestAdjustSharedNamespaceContainerName(t *testing.T) {
+	fakeID := "abcdef1234567890"
+	hostConfig := &containertypes.HostConfig{
+		IpcMode:     containertypes.IpcMode("container:base"),
+		PidMode:     containertypes.PidMode("container:base"),
+		NetworkMode: containertypes.NetworkMode("container:base"),
+	}
+	containerStore := &fakeContainerGetter{}
+	containerStore.containers = make(map[string]*container.Container)
+	containerStore.containers["base"] = &container.Container{
+		ID: fakeID,
+	}
+
+	adaptSharedNamespaceContainer(containerStore, hostConfig)
+	if hostConfig.IpcMode != containertypes.IpcMode("container:"+fakeID) {
+		t.Errorf("Expected IpcMode to be container:%s", fakeID)
+	}
+	if hostConfig.PidMode != containertypes.PidMode("container:"+fakeID) {
+		t.Errorf("Expected PidMode to be container:%s", fakeID)
+	}
+	if hostConfig.NetworkMode != containertypes.NetworkMode("container:"+fakeID) {
+		t.Errorf("Expected NetworkMode to be container:%s", fakeID)
+	}
+}
+
 // Unix test as uses settings which are not available on Windows
 func TestAdjustCPUShares(t *testing.T) {
 	tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-")