Skip to content

Commit

Permalink
docker run: specify cgroup namespace mode with --cgroupns
Browse files Browse the repository at this point in the history
Signed-off-by: Rob Gulewich <rgulewich@netflix.com>
  • Loading branch information
rgulewich committed Jan 29, 2020
1 parent 2079e74 commit 5ad1d4d
Show file tree
Hide file tree
Showing 15 changed files with 112 additions and 36 deletions.
13 changes: 13 additions & 0 deletions cli/command/container/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ type containerOptions struct {
pidMode string
utsMode string
usernsMode string
cgroupnsMode string
publishAll bool
stdin bool
tty bool
Expand Down Expand Up @@ -198,6 +199,12 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
flags.BoolVar(&copts.privileged, "privileged", false, "Give extended privileges to this container")
flags.Var(&copts.securityOpt, "security-opt", "Security Options")
flags.StringVar(&copts.usernsMode, "userns", "", "User namespace to use")
flags.StringVar(&copts.cgroupnsMode, "cgroupns", "", `Cgroup namespace to use (host|private)
'host': Run the container in the Docker host's cgroup namespace
'private': Run the container in its own private cgroup namespace
'': Use the cgroup namespace as configured by the
default-cgroupns-mode option on the daemon (default)`)
flags.SetAnnotation("cgroupns", "version", []string{"1.41"})

// Network and port publishing flag
flags.Var(&copts.extraHosts, "add-host", "Add a custom host-to-IP mapping (host:ip)")
Expand Down Expand Up @@ -469,6 +476,11 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
return nil, errors.Errorf("--userns: invalid USER mode")
}

cgroupnsMode := container.CgroupnsMode(copts.cgroupnsMode)
if !cgroupnsMode.Valid() {
return nil, errors.Errorf("--cgroupns: invalid CGROUP mode")
}

restartPolicy, err := opts.ParseRestartPolicy(copts.restartPolicy)
if err != nil {
return nil, err
Expand Down Expand Up @@ -620,6 +632,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
PidMode: pidMode,
UTSMode: utsMode,
UsernsMode: usernsMode,
CgroupnsMode: cgroupnsMode,
CapAdd: strslice.StrSlice(copts.capAdd.GetAll()),
CapDrop: strslice.StrSlice(copts.capDrop.GetAll()),
GroupAdd: copts.groupAdd.GetAll(),
Expand Down
1 change: 1 addition & 0 deletions cli/command/system/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ var sampleInfoNoSwarm = types.Info{
NEventsListener: 0,
KernelVersion: "4.4.0-87-generic",
OperatingSystem: "Ubuntu 16.04.3 LTS",
OSVersion: "",
OSType: "linux",
Architecture: "x86_64",
IndexServerAddress: "https://index.docker.io/v1/",
Expand Down
72 changes: 36 additions & 36 deletions cli/compose/schema/bindata.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cli/compose/schema/data/config_schema_v3.9.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
},
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"cgroupns_mode": {"type": "string"},
"cgroup_parent": {"type": "string"},
"command": {
"oneOf": [
Expand Down
2 changes: 2 additions & 0 deletions cli/compose/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ var UnsupportedProperties = []string{
"build",
"cap_add",
"cap_drop",
"cgroupns_mode",
"cgroup_parent",
"devices",
"domainname",
Expand Down Expand Up @@ -159,6 +160,7 @@ type ServiceConfig struct {
Build BuildConfig `yaml:",omitempty" json:"build,omitempty"`
CapAdd []string `mapstructure:"cap_add" yaml:"cap_add,omitempty" json:"cap_add,omitempty"`
CapDrop []string `mapstructure:"cap_drop" yaml:"cap_drop,omitempty" json:"cap_drop,omitempty"`
CgroupNSMode string `mapstructure:"cgroupns_mode" yaml:"cgroupns_mode,omitempty" json:"cgroupns_mode,omitempty"`
CgroupParent string `mapstructure:"cgroup_parent" yaml:"cgroup_parent,omitempty" json:"cgroup_parent,omitempty"`
Command ShellCommand `yaml:",omitempty" json:"command,omitempty"`
Configs []ServiceConfigObjConfig `yaml:",omitempty" json:"configs,omitempty"`
Expand Down
5 changes: 5 additions & 0 deletions contrib/completion/bash/docker
Original file line number Diff line number Diff line change
Expand Up @@ -1865,6 +1865,7 @@ _docker_container_run_and_create() {
--blkio-weight-device
--cap-add
--cap-drop
--cgroupns
--cgroup-parent
--cidfile
--cpu-period
Expand Down Expand Up @@ -2022,6 +2023,10 @@ _docker_container_run_and_create() {
_filedir
return
;;
--cgroupns)
COMPREPLY=( $( compgen -W "host private" -- "$cur" ) )
return
;;
--device|--tmpfs|--volume|-v)
case "$cur" in
*:*)
Expand Down
2 changes: 2 additions & 0 deletions contrib/completion/fish/docker.fish
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l blkio-weight
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l blkio-weight-device -d 'Block IO weight (relative device weight)'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cap-add -d 'Add Linux capabilities'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cap-drop -d 'Drop Linux capabilities'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cgroupns -d 'Cgroup namespace mode to use'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cgroup-parent -d 'Optional parent cgroup for the container'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cidfile -d 'Write the container ID to the file'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cpu-count -d 'CPU count (Windows only)'
Expand Down Expand Up @@ -458,6 +459,7 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s c -l cpu-shares
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l cap-add -d 'Add Linux capabilities'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l cap-drop -d 'Drop Linux capabilities'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l cidfile -d 'Write the container ID to the file'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l cgroupns -d 'Cgroup namespace mode to use'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l cpuset -d 'CPUs in which to allow execution (0-3, 0,1)'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s d -l detach -d 'Detached mode: run the container in the background and print the new container ID'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l device -d 'Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm)'
Expand Down
1 change: 1 addition & 0 deletions contrib/completion/zsh/_docker
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ __docker_container_subcommand() {
"($help)*--blkio-weight-device=[Block IO (relative device weight)]:device:Block IO weight: "
"($help)*--cap-add=[Add Linux capabilities]:capability: "
"($help)*--cap-drop=[Drop Linux capabilities]:capability: "
"($help)--cgroupns=[Cgroup namespace mode to use]:cgroup namespace mode: "
"($help)--cgroup-parent=[Parent cgroup for the container]:cgroup: "
"($help)--cidfile=[Write the container ID to the file]:CID file:_files"
"($help)--cpus=[Number of CPUs (default 0.000)]:cpus: "
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/commandline/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ Options:
--blkio-weight-device value Block IO weight (relative device weight) (default [])
--cap-add value Add Linux capabilities (default [])
--cap-drop value Drop Linux capabilities (default [])
--cgroupns string Cgroup namespace to use
'host': Run the container in the Docker host's cgroup namespace
'private': Run the container in its own private cgroup namespace
'': Use the default Docker daemon cgroup namespace specified by the `--default-cgroupns-mode` option
--cgroup-parent string Optional parent cgroup for the container
--cidfile string Write the container ID to the file
--cpu-count int The number of CPUs available for execution by the container.
Expand Down
2 changes: 2 additions & 0 deletions docs/reference/commandline/dockerd.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Options:
--cpu-rt-runtime int Limit the CPU real-time runtime in microseconds
--data-root string Root directory of persistent Docker state (default "/var/lib/docker")
-D, --debug Enable debug mode
--default-cgroupns-mode string Container default cgroup namespace mode (default "host")
--default-gateway ip Container default gateway IPv4 address
--default-gateway-v6 ip Container default gateway IPv6 address
--default-address-pool Set the default address pool for local node networks
Expand Down Expand Up @@ -1299,6 +1300,7 @@ This is a full example of the allowed configuration options on Linux:
{
"authorization-plugins": [],
"data-root": "",
"default-cgroupns-mode": "private",
"dns": [],
"dns-opts": [],
"dns-search": [],
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/commandline/run.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ Options:
--blkio-weight-device value Block IO weight (relative device weight) (default [])
--cap-add value Add Linux capabilities (default [])
--cap-drop value Drop Linux capabilities (default [])
--cgroupns string Cgroup namespace to use
'host': Run the container in the Docker host's cgroup namespace
'private': Run the container in its own private cgroup namespace
'': Use the default Docker daemon cgroup namespace specified by the `--default-cgroupns-mode` option
--cgroup-parent string Optional parent cgroup for the container
--cidfile string Write the container ID to the file
--cpu-count int The number of CPUs available for execution by the container.
Expand Down
9 changes: 9 additions & 0 deletions e2e/container/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,12 @@ func createRemoteImage(t *testing.T) string {
icmd.RunCommand("docker", "rmi", image).Assert(t, icmd.Success)
return image
}

func TestRunWithCgroupNamespace(t *testing.T) {
environment.SkipIfDaemonNotLinux(t)
environment.SkipIfCgroupNamespacesNotSupported(t)

result := icmd.RunCommand("docker", "run", "--cgroupns=private", "--rm", fixtures.AlpineImage,
"/bin/grep", "-q", "':memory:/$'", "/proc/1/cgroup")
result.Assert(t, icmd.Success)
}
20 changes: 20 additions & 0 deletions internal/test/environment/testenv.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package environment

import (
"fmt"
"os"
"strings"
"testing"
Expand Down Expand Up @@ -88,3 +89,22 @@ func SkipIfNotExperimentalDaemon(t *testing.T) {
experimentalBuild := strings.TrimSpace(result.Stdout()) == "true"
skip.If(t, !experimentalBuild, "running against a non-experimental daemon")
}

// SkipIfDaemonNotLinux skips the test unless the running docker daemon is on Linux
func SkipIfDaemonNotLinux(t *testing.T) {
t.Helper()
result := icmd.RunCmd(icmd.Command("docker", "info", "--format", "{{.OSType}}"))
result.Assert(t, icmd.Expected{Err: icmd.None})
isLinux := strings.TrimSpace(result.Stdout()) == "linux"
skip.If(t, !isLinux, "running against a Linux daemon")
}

// SkipIfCgroupNamespacesNotSupported skips the test if the running docker daemon doesn't support cgroup namespaces
func SkipIfCgroupNamespacesNotSupported(t *testing.T) {
t.Helper()
result := icmd.RunCmd(icmd.Command("docker", "info", "--format", "{{.SecurityOptions}}"))
result.Assert(t, icmd.Expected{Err: icmd.None})
cgroupNsFound := strings.Contains(result.Stdout(), "name=cgroupns")

skip.If(t, !cgroupNsFound, fmt.Sprintf("running against a daemon that doesn't support cgroup namespaces (security options: %s)", result.Stdout()))
}
7 changes: 7 additions & 0 deletions man/docker-run.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ docker-run - Run a command in a new container
[**--cpu-shares**[=*0*]]
[**--cap-add**[=*[]*]]
[**--cap-drop**[=*[]*]]
[**--cgroupns**[=*[]*]]
[**--cgroup-parent**[=*CGROUP-PATH*]]
[**--cidfile**[=*CIDFILE*]]
[**--cpu-count**[=*0*]]
Expand Down Expand Up @@ -173,6 +174,12 @@ division of CPU shares:
**--cap-drop**=[]
Drop Linux capabilities

**--cgroupns**=""
Set the cgroup namespace mode for the container.
**host**: run the container in the host's cgroup namespace
**private**: run the container in its own private cgroup namespace
**""**: (unset) run the container in the host's cgroup namespace

**--cgroup-parent**=""
Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist.

Expand Down
5 changes: 5 additions & 0 deletions man/dockerd.8.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dockerd - Enable daemon mode
[**--containerd**[=*SOCKET-PATH*]]
[**--data-root**[=*/var/lib/docker*]]
[**-D**|**--debug**]
[**--default-cgroupns-mode**[=*host*]]
[**--default-gateway**[=*DEFAULT-GATEWAY*]]
[**--default-gateway-v6**[=*DEFAULT-GATEWAY-V6*]]
[**--default-address-pool**[=*DEFAULT-ADDRESS-POOL*]]
Expand Down Expand Up @@ -178,6 +179,10 @@ $ sudo dockerd --add-runtime runc=runc --add-runtime custom=/usr/local/bin/my-ru
**-D**, **--debug**=*true*|*false*
Enable debug mode. Default is false.

**--default-cgroupns-mode**="**host**|**private**"
Set the default cgroup namespace mode for newly created containers. The argument
can either be **host** or **private**. If unset, this defaults to `host`.

**--default-gateway**=""
IPv4 address of the container default gateway; this address must be part of
the bridge subnet (which is defined by \-b or \--bip)
Expand Down

0 comments on commit 5ad1d4d

Please sign in to comment.