Merge pull request #22481 from mrunalp/pid_container
Add support for --pid=container:<id>
This commit is contained in:
commit
ebeb5a0422
9 changed files with 154 additions and 13 deletions
|
@ -1832,6 +1832,21 @@ _docker_run() {
|
|||
esac
|
||||
return
|
||||
;;
|
||||
--pid)
|
||||
case "$cur" in
|
||||
*:*)
|
||||
cur="${cur#*:}"
|
||||
__docker_complete_containers_running
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) )
|
||||
if [ "$COMPREPLY" = "container:" ]; then
|
||||
__docker_nospace
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
return
|
||||
;;
|
||||
--security-opt)
|
||||
COMPREPLY=( $( compgen -W "apparmor= label= no-new-privileges seccomp=" -- "$cur") )
|
||||
if [ "${COMPREPLY[*]}" != "no-new-privileges" ] ; then
|
||||
|
|
|
@ -699,7 +699,7 @@ __docker_subcommand() {
|
|||
"($help)--pids-limit[Tune container pids limit (set -1 for unlimited)]"
|
||||
"($help -P --publish-all)"{-P,--publish-all}"[Publish all exposed ports]"
|
||||
"($help)*"{-p=,--publish=}"[Expose a container's port to the host]:port:_ports"
|
||||
"($help)--pid=[PID namespace to use]:PID: "
|
||||
"($help)--pid=[PID namespace to use]:PID namespace: "
|
||||
"($help)--privileged[Give extended privileges to this container]"
|
||||
"($help)--read-only[Mount the container's root filesystem as read only]"
|
||||
"($help)*--security-opt=[Security options]:security option: "
|
||||
|
|
|
@ -169,6 +169,21 @@ func (daemon *Daemon) getIpcContainer(container *container.Container) (*containe
|
|||
return c, nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) getPidContainer(container *container.Container) (*container.Container, error) {
|
||||
containerID := container.HostConfig.PidMode.Container()
|
||||
c, err := daemon.GetContainer(containerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !c.IsRunning() {
|
||||
return nil, fmt.Errorf("cannot join PID of a non running container: %s", containerID)
|
||||
}
|
||||
if c.IsRestarting() {
|
||||
return nil, errContainerIsRestarting(container.ID)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
|
||||
var err error
|
||||
|
||||
|
|
|
@ -142,13 +142,40 @@ func (daemon *Daemon) generateSecurityOpt(ipcMode containertypes.IpcMode, pidMod
|
|||
if ipcMode.IsHost() || pidMode.IsHost() {
|
||||
return label.DisableSecOpt(), nil
|
||||
}
|
||||
if ipcContainer := ipcMode.Container(); ipcContainer != "" {
|
||||
|
||||
var ipcLabel []string
|
||||
var pidLabel []string
|
||||
ipcContainer := ipcMode.Container()
|
||||
pidContainer := pidMode.Container()
|
||||
if ipcContainer != "" {
|
||||
c, err := daemon.GetContainer(ipcContainer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipcLabel = label.DupSecOpt(c.ProcessLabel)
|
||||
if pidContainer == "" {
|
||||
return ipcLabel, err
|
||||
}
|
||||
}
|
||||
if pidContainer != "" {
|
||||
c, err := daemon.GetContainer(pidContainer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return label.DupSecOpt(c.ProcessLabel), nil
|
||||
pidLabel = label.DupSecOpt(c.ProcessLabel)
|
||||
if ipcContainer == "" {
|
||||
return pidLabel, err
|
||||
}
|
||||
}
|
||||
|
||||
if pidLabel != nil && ipcLabel != nil {
|
||||
for i := 0; i < len(pidLabel); i++ {
|
||||
if pidLabel[i] != ipcLabel[i] {
|
||||
return nil, fmt.Errorf("--ipc and --pid containers SELinux labels aren't the same")
|
||||
}
|
||||
}
|
||||
return pidLabel, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -296,8 +296,25 @@ func setNamespaces(daemon *Daemon, s *specs.Spec, c *container.Container) error
|
|||
setNamespace(s, ns)
|
||||
}
|
||||
// pid
|
||||
if c.HostConfig.PidMode.IsHost() {
|
||||
if c.HostConfig.PidMode.IsContainer() {
|
||||
ns := specs.Namespace{Type: "pid"}
|
||||
pc, err := daemon.getPidContainer(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ns.Path = fmt.Sprintf("/proc/%d/ns/pid", pc.State.GetPID())
|
||||
setNamespace(s, ns)
|
||||
if userNS {
|
||||
// to share an PID namespace, they must also share a user namespace
|
||||
nsUser := specs.Namespace{Type: "user"}
|
||||
nsUser.Path = fmt.Sprintf("/proc/%d/ns/user", pc.State.GetPID())
|
||||
setNamespace(s, nsUser)
|
||||
}
|
||||
} else if c.HostConfig.PidMode.IsHost() {
|
||||
delNamespace(s, specs.NamespaceType("pid"))
|
||||
} else {
|
||||
ns := specs.Namespace{Type: "pid"}
|
||||
setNamespace(s, ns)
|
||||
}
|
||||
// uts
|
||||
if c.HostConfig.UTSMode.IsHost() {
|
||||
|
|
|
@ -193,7 +193,8 @@ the digest value is predictable and referenceable.
|
|||
## PID settings (--pid)
|
||||
|
||||
--pid="" : Set the PID (Process) Namespace mode for the container,
|
||||
'host': use the host's PID namespace inside the container
|
||||
'container:<name|id>': joins another container's PID namespace
|
||||
'host': use the host's PID namespace inside the container
|
||||
|
||||
By default, all containers have the PID namespace enabled.
|
||||
|
||||
|
@ -229,6 +230,23 @@ Use the following command to run `htop` inside a container:
|
|||
$ docker run -it --rm --pid=host myhtop
|
||||
```
|
||||
|
||||
Joining another container's pid namespace can be used for debugging that container.
|
||||
|
||||
### Example
|
||||
|
||||
Start a container running a redis server:
|
||||
|
||||
```bash
|
||||
$ docker run --name my-redis -d redis
|
||||
```
|
||||
|
||||
Debug the redis container by running another container that has strace in it:
|
||||
|
||||
```bash
|
||||
$ docker run --it --pid=container:my-redis bash
|
||||
$ strace -p 1
|
||||
```
|
||||
|
||||
## UTS settings (--uts)
|
||||
|
||||
--uts="" : Set the UTS namespace mode for the container,
|
||||
|
|
|
@ -2443,6 +2443,53 @@ func (s *DockerSuite) TestRunModeIpcContainerNotRunning(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunModePidContainer(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "top")
|
||||
|
||||
id := strings.TrimSpace(out)
|
||||
state := inspectField(c, id, "State.Running")
|
||||
if state != "true" {
|
||||
c.Fatal("Container state is 'not running'")
|
||||
}
|
||||
pid1 := inspectField(c, id, "State.Pid")
|
||||
|
||||
parentContainerPid, err := os.Readlink(fmt.Sprintf("/proc/%s/ns/pid", pid1))
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
out, _ = dockerCmd(c, "run", fmt.Sprintf("--pid=container:%s", id), "busybox", "readlink", "/proc/self/ns/pid")
|
||||
out = strings.Trim(out, "\n")
|
||||
if parentContainerPid != out {
|
||||
c.Fatalf("PID different with --pid=container:%s %s != %s\n", id, parentContainerPid, out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunModePidContainerNotExists(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, DaemonIsLinux)
|
||||
out, _, err := dockerCmdWithError("run", "-d", "--pid", "container:abcd1234", "busybox", "top")
|
||||
if !strings.Contains(out, "abcd1234") || err == nil {
|
||||
c.Fatalf("run PID from a non exists container should with correct error out")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunModePidContainerNotRunning(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
|
||||
out, _ := dockerCmd(c, "create", "busybox")
|
||||
|
||||
id := strings.TrimSpace(out)
|
||||
out, _, err := dockerCmdWithError("run", fmt.Sprintf("--pid=container:%s", id), "busybox")
|
||||
if err == nil {
|
||||
c.Fatalf("Run container with pid mode container should fail with non running container: %s\n%s", out, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunMountShmMqueueFromHost(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
|
|
|
@ -57,7 +57,7 @@ docker-create - Create a new container
|
|||
[**--oom-score-adj**[=*0*]]
|
||||
[**-P**|**--publish-all**]
|
||||
[**-p**|**--publish**[=*[]*]]
|
||||
[**--pid**[=*[]*]]
|
||||
[**--pid**[=*[PID]*]]
|
||||
[**--userns**[=*[]*]]
|
||||
[**--pids-limit**[=*PIDS_LIMIT*]]
|
||||
[**--privileged**]
|
||||
|
@ -289,10 +289,11 @@ unit, `b` is used. Set LIMIT to `-1` to enable unlimited swap.
|
|||
When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range. (e.g., `-p 1234-1236:1234-1236/tcp`)
|
||||
(use 'docker port' to see the actual mapping)
|
||||
|
||||
**--pid**=*host*
|
||||
**--pid**=""
|
||||
Set the PID mode for the container
|
||||
**host**: use the host's PID namespace inside the container.
|
||||
Note: the host mode gives the container full access to local PID and is therefore considered insecure.
|
||||
Default is to create a private PID namespace for the container
|
||||
'container:<name|id>': join another container's PID namespace
|
||||
'host': use the host's PID namespace for the container. Note: the host mode gives the container full access to local PID and is therefore considered insecure.
|
||||
|
||||
**--userns**=""
|
||||
Set the usernamespace mode for the container when `userns-remap` option is enabled.
|
||||
|
|
|
@ -59,7 +59,7 @@ docker-run - Run a command in a new container
|
|||
[**--oom-score-adj**[=*0*]]
|
||||
[**-P**|**--publish-all**]
|
||||
[**-p**|**--publish**[=*[]*]]
|
||||
[**--pid**[=*[]*]]
|
||||
[**--pid**[=*[PID]*]]
|
||||
[**--userns**[=*[]*]]
|
||||
[**--pids-limit**[=*PIDS_LIMIT*]]
|
||||
[**--privileged**]
|
||||
|
@ -420,10 +420,11 @@ but not `docker run -p 1230-1236:1230-1240 --name RangeContainerPortsBiggerThanR
|
|||
With ip: `docker run -p 127.0.0.1:$HOSTPORT:$CONTAINERPORT --name CONTAINER -t someimage`
|
||||
Use `docker port` to see the actual mapping: `docker port CONTAINER $CONTAINERPORT`
|
||||
|
||||
**--pid**=*host*
|
||||
**--pid**=""
|
||||
Set the PID mode for the container
|
||||
**host**: use the host's PID namespace inside the container.
|
||||
Note: the host mode gives the container full access to local PID and is therefore considered insecure.
|
||||
Default is to create a private PID namespace for the container
|
||||
'container:<name|id>': join another container's PID namespace
|
||||
'host': use the host's PID namespace for the container. Note: the host mode gives the container full access to local PID and is therefore considered insecure.
|
||||
|
||||
**--userns**=""
|
||||
Set the usernamespace mode for the container when `userns-remap` option is enabled.
|
||||
|
|
Loading…
Reference in a new issue