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>
This commit is contained in:
Chen Min 2017-08-02 03:04:37 +08:00
parent db73f3daee
commit b6e5ea8e57
2 changed files with 75 additions and 0 deletions

View File

@ -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)

View File

@ -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-")