Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docker run: specify cgroup namespace mode with --cgroupns #2024

Merged
merged 1 commit into from
Feb 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")
thaJeztah marked this conversation as resolved.
Show resolved Hide resolved
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() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this; I'm a bit on the fence if we should validate this on the client side, or just leave it to the daemon to return an error if an invalid value was provided. OTOH, these values likely won't change in future, so perhaps it's ok

@kolyshkin wdyt?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's ok for now, given that it likely won't change in future, but I'll open a follow-up issue after this is merged to discuss this

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
thaJeztah marked this conversation as resolved.
Show resolved Hide resolved
'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

thaJeztah marked this conversation as resolved.
Show resolved Hide resolved
**--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