mirror of https://github.com/docker/docs.git
Merge pull request #6968 from vieux/cap_add_drop
Add support for --cap-add and --cap-drop
This commit is contained in:
commit
7ebd49c49a
|
@ -254,6 +254,8 @@ func populateCommand(c *Container, env []string) error {
|
||||||
Resources: resources,
|
Resources: resources,
|
||||||
AllowedDevices: allowedDevices,
|
AllowedDevices: allowedDevices,
|
||||||
AutoCreatedDevices: autoCreatedDevices,
|
AutoCreatedDevices: autoCreatedDevices,
|
||||||
|
CapAdd: c.hostConfig.CapAdd,
|
||||||
|
CapDrop: c.hostConfig.CapDrop,
|
||||||
}
|
}
|
||||||
c.command.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
c.command.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
||||||
c.command.Env = env
|
c.command.Env = env
|
||||||
|
|
|
@ -60,6 +60,8 @@ type InitArgs struct {
|
||||||
Console string
|
Console string
|
||||||
Pipe int
|
Pipe int
|
||||||
Root string
|
Root string
|
||||||
|
CapAdd string
|
||||||
|
CapDrop string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Driver specific information based on
|
// Driver specific information based on
|
||||||
|
@ -140,6 +142,8 @@ type Command struct {
|
||||||
Mounts []Mount `json:"mounts"`
|
Mounts []Mount `json:"mounts"`
|
||||||
AllowedDevices []*devices.Device `json:"allowed_devices"`
|
AllowedDevices []*devices.Device `json:"allowed_devices"`
|
||||||
AutoCreatedDevices []*devices.Device `json:"autocreated_devices"`
|
AutoCreatedDevices []*devices.Device `json:"autocreated_devices"`
|
||||||
|
CapAdd []string `json:"cap_add"`
|
||||||
|
CapDrop []string `json:"cap_drop"`
|
||||||
|
|
||||||
Terminal Terminal `json:"-"` // standard or tty terminal
|
Terminal Terminal `json:"-"` // standard or tty terminal
|
||||||
Console string `json:"-"` // dev/console path
|
Console string `json:"-"` // dev/console path
|
||||||
|
|
|
@ -122,6 +122,14 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
params = append(params, "-w", c.WorkingDir)
|
params = append(params, "-w", c.WorkingDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(c.CapAdd) > 0 {
|
||||||
|
params = append(params, "-cap-add", strings.Join(c.CapAdd, " "))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c.CapDrop) > 0 {
|
||||||
|
params = append(params, "-cap-drop", strings.Join(c.CapDrop, " "))
|
||||||
|
}
|
||||||
|
|
||||||
params = append(params, "--", c.Entrypoint)
|
params = append(params, "--", c.Entrypoint)
|
||||||
params = append(params, c.Arguments...)
|
params = append(params, c.Arguments...)
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ package lxc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/docker/libcontainer/namespaces"
|
"github.com/docker/libcontainer/namespaces"
|
||||||
|
@ -48,8 +49,13 @@ func finalizeNamespace(args *execdriver.InitArgs) error {
|
||||||
return fmt.Errorf("clear keep caps %s", err)
|
return fmt.Errorf("clear keep caps %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
caps, err := execdriver.TweakCapabilities(container.Capabilities, strings.Split(args.CapAdd, " "), strings.Split(args.CapDrop, " "))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// drop all other capabilities
|
// drop all other capabilities
|
||||||
if err := capabilities.DropCapabilities(container.Capabilities); err != nil {
|
if err := capabilities.DropCapabilities(caps); err != nil {
|
||||||
return fmt.Errorf("drop capabilities %s", err)
|
return fmt.Errorf("drop capabilities %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,10 @@ func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Config, e
|
||||||
if err := d.setPrivileged(container); err != nil {
|
if err := d.setPrivileged(container); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if err := d.setCapabilities(container, c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.setupCgroups(container, c); err != nil {
|
if err := d.setupCgroups(container, c); err != nil {
|
||||||
|
@ -136,6 +140,11 @@ func (d *driver) setPrivileged(container *libcontainer.Config) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *driver) setCapabilities(container *libcontainer.Config, c *execdriver.Command) (err error) {
|
||||||
|
container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (d *driver) setupCgroups(container *libcontainer.Config, c *execdriver.Command) error {
|
func (d *driver) setupCgroups(container *libcontainer.Config, c *execdriver.Command) error {
|
||||||
if c.Resources != nil {
|
if c.Resources != nil {
|
||||||
container.Cgroups.CpuShares = c.Resources.CpuShares
|
container.Cgroups.CpuShares = c.Resources.CpuShares
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
package execdriver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/libcontainer/security/capabilities"
|
||||||
|
"github.com/dotcloud/docker/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TweakCapabilities(basics, adds, drops []string) ([]string, error) {
|
||||||
|
var (
|
||||||
|
newCaps []string
|
||||||
|
allCaps = capabilities.GetAllCapabilities()
|
||||||
|
)
|
||||||
|
|
||||||
|
// look for invalid cap in the drop list
|
||||||
|
for _, cap := range drops {
|
||||||
|
if strings.ToLower(cap) == "all" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !utils.StringsContainsNoCase(allCaps, cap) {
|
||||||
|
return nil, fmt.Errorf("Unknown capability: %s", cap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle --cap-add=all
|
||||||
|
if utils.StringsContainsNoCase(adds, "all") {
|
||||||
|
basics = capabilities.GetAllCapabilities()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !utils.StringsContainsNoCase(drops, "all") {
|
||||||
|
for _, cap := range basics {
|
||||||
|
// skip `all` aready handled above
|
||||||
|
if strings.ToLower(cap) == "all" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we don't drop `all`, add back all the non-dropped caps
|
||||||
|
if !utils.StringsContainsNoCase(drops, cap) {
|
||||||
|
newCaps = append(newCaps, cap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cap := range adds {
|
||||||
|
// skip `all` aready handled above
|
||||||
|
if strings.ToLower(cap) == "all" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for invalid cap in the drop list
|
||||||
|
if !utils.StringsContainsNoCase(allCaps, cap) {
|
||||||
|
return nil, fmt.Errorf("Unknown capability: %s", cap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// add cap if not already in the list
|
||||||
|
if !utils.StringsContainsNoCase(newCaps, cap) {
|
||||||
|
newCaps = append(newCaps, cap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newCaps, nil
|
||||||
|
}
|
|
@ -43,6 +43,12 @@ You can now use the `stop` parameter to stop running containers before removal
|
||||||
**New!**
|
**New!**
|
||||||
You can now use the `kill` parameter to kill running containers before removal.
|
You can now use the `kill` parameter to kill running containers before removal.
|
||||||
|
|
||||||
|
`POST /containers/(id)/start`
|
||||||
|
|
||||||
|
**New!**
|
||||||
|
The `hostConfig` option now accepts the field `CapAdd`, which specifies a list of capabilities
|
||||||
|
to add, and the field `CapDrop`, which specifies a list of capabilities to drop.
|
||||||
|
|
||||||
## v1.13
|
## v1.13
|
||||||
|
|
||||||
### Full Documentation
|
### Full Documentation
|
||||||
|
|
|
@ -241,7 +241,9 @@ Return low-level information on the container `id`
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Links": ["/name:alias"],
|
"Links": ["/name:alias"],
|
||||||
"PublishAllPorts": false
|
"PublishAllPorts": false,
|
||||||
|
"CapAdd: ["NET_ADMIN"],
|
||||||
|
"CapDrop: ["MKNOD"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,7 +412,9 @@ Start the container `id`
|
||||||
"PublishAllPorts":false,
|
"PublishAllPorts":false,
|
||||||
"Privileged":false,
|
"Privileged":false,
|
||||||
"Dns": ["8.8.8.8"],
|
"Dns": ["8.8.8.8"],
|
||||||
"VolumesFrom": ["parent", "other:ro"]
|
"VolumesFrom": ["parent", "other:ro"],
|
||||||
|
"CapAdd: ["NET_ADMIN"],
|
||||||
|
"CapDrop: ["MKNOD"]
|
||||||
}
|
}
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
|
@ -55,7 +55,7 @@ following options.
|
||||||
- [Network Settings](#network-settings)
|
- [Network Settings](#network-settings)
|
||||||
- [Clean Up (--rm)](#clean-up-rm)
|
- [Clean Up (--rm)](#clean-up-rm)
|
||||||
- [Runtime Constraints on CPU and Memory](#runtime-constraints-on-cpu-and-memory)
|
- [Runtime Constraints on CPU and Memory](#runtime-constraints-on-cpu-and-memory)
|
||||||
- [Runtime Privilege and LXC Configuration](#runtime-privilege-and-lxc-configuration)
|
- [Runtime Privilege, Linux Capabilities, and LXC Configuration](#runtime-privilege-linux-capabilities-and-lxc-configuration)
|
||||||
|
|
||||||
## Detached vs Foreground
|
## Detached vs Foreground
|
||||||
|
|
||||||
|
@ -222,8 +222,10 @@ get the same proportion of CPU cycles, but you can tell the kernel to
|
||||||
give more shares of CPU time to one or more containers when you start
|
give more shares of CPU time to one or more containers when you start
|
||||||
them via Docker.
|
them via Docker.
|
||||||
|
|
||||||
## Runtime Privilege and LXC Configuration
|
## Runtime Privilege, Linux Capabilities, and LXC Configuration
|
||||||
|
|
||||||
|
--cap-add: Add Linux capabilities
|
||||||
|
--cap-drop: Drop Linux capabilities
|
||||||
--privileged=false: Give extended privileges to this container
|
--privileged=false: Give extended privileges to this container
|
||||||
--lxc-conf=[]: (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"
|
--lxc-conf=[]: (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"
|
||||||
|
|
||||||
|
@ -242,6 +244,16 @@ host as processes running outside containers on the host. Additional
|
||||||
information about running with `--privileged` is available on the
|
information about running with `--privileged` is available on the
|
||||||
[Docker Blog](http://blog.docker.com/2013/09/docker-can-now-run-within-docker/).
|
[Docker Blog](http://blog.docker.com/2013/09/docker-can-now-run-within-docker/).
|
||||||
|
|
||||||
|
In addition to `--privileged`, the operator can have fine grain control over the
|
||||||
|
capabilities using `--cap-add` and `--cap-drop`. By default, Docker has a default
|
||||||
|
list of capabilities that are kept. Both flags support the value `all`, so if the
|
||||||
|
operator wants to have all capabilities but `MKNOD` they could use:
|
||||||
|
|
||||||
|
$ docker run --cap-add=ALL --cap-drop=MKNOD ...
|
||||||
|
|
||||||
|
For interacting with the network stack, instead of using `--privileged` they
|
||||||
|
should use `--cap-add=NET_ADMIN` to modify the network interfaces.
|
||||||
|
|
||||||
If the Docker daemon was started using the `lxc` exec-driver
|
If the Docker daemon was started using the `lxc` exec-driver
|
||||||
(`docker -d --exec-driver=lxc`) then the operator can also specify LXC options
|
(`docker -d --exec-driver=lxc`) then the operator can also specify LXC options
|
||||||
using one or more `--lxc-conf` parameters. These can be new parameters or
|
using one or more `--lxc-conf` parameters. These can be new parameters or
|
||||||
|
|
|
@ -783,6 +783,116 @@ func TestUnPrivilegedCanMknod(t *testing.T) {
|
||||||
logDone("run - test un-privileged can mknod")
|
logDone("run - test un-privileged can mknod")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCapDropInvalid(t *testing.T) {
|
||||||
|
cmd := exec.Command(dockerBinary, "run", "--cap-drop=CHPASS", "busybox", "ls")
|
||||||
|
out, _, err := runCommandWithOutput(cmd)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
logDone("run - test --cap-drop=CHPASS invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapDropCannotMknod(t *testing.T) {
|
||||||
|
cmd := exec.Command(dockerBinary, "run", "--cap-drop=MKNOD", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
|
||||||
|
out, _, err := runCommandWithOutput(cmd)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual := strings.Trim(out, "\r\n"); actual == "ok" {
|
||||||
|
t.Fatalf("expected output not ok received %s", actual)
|
||||||
|
}
|
||||||
|
deleteAllContainers()
|
||||||
|
|
||||||
|
logDone("run - test --cap-drop=MKNOD cannot mknod")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapDropALLCannotMknod(t *testing.T) {
|
||||||
|
cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
|
||||||
|
out, _, err := runCommandWithOutput(cmd)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual := strings.Trim(out, "\r\n"); actual == "ok" {
|
||||||
|
t.Fatalf("expected output not ok received %s", actual)
|
||||||
|
}
|
||||||
|
deleteAllContainers()
|
||||||
|
|
||||||
|
logDone("run - test --cap-drop=ALL cannot mknod")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapDropALLAddMknodCannotMknod(t *testing.T) {
|
||||||
|
cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL", "--cap-add=MKNOD", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
|
||||||
|
out, _, err := runCommandWithOutput(cmd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual := strings.Trim(out, "\r\n"); actual != "ok" {
|
||||||
|
t.Fatalf("expected output ok received %s", actual)
|
||||||
|
}
|
||||||
|
deleteAllContainers()
|
||||||
|
|
||||||
|
logDone("run - test --cap-drop=ALL --cap-add=MKNOD can mknod")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapAddInvalid(t *testing.T) {
|
||||||
|
cmd := exec.Command(dockerBinary, "run", "--cap-add=CHPASS", "busybox", "ls")
|
||||||
|
out, _, err := runCommandWithOutput(cmd)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
logDone("run - test --cap-add=CHPASS invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapAddCanDownInterface(t *testing.T) {
|
||||||
|
cmd := exec.Command(dockerBinary, "run", "--cap-add=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
|
||||||
|
out, _, err := runCommandWithOutput(cmd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual := strings.Trim(out, "\r\n"); actual != "ok" {
|
||||||
|
t.Fatalf("expected output ok received %s", actual)
|
||||||
|
}
|
||||||
|
deleteAllContainers()
|
||||||
|
|
||||||
|
logDone("run - test --cap-add=NET_ADMIN can set eth0 down")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapAddALLCanDownInterface(t *testing.T) {
|
||||||
|
cmd := exec.Command(dockerBinary, "run", "--cap-add=ALL", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
|
||||||
|
out, _, err := runCommandWithOutput(cmd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual := strings.Trim(out, "\r\n"); actual != "ok" {
|
||||||
|
t.Fatalf("expected output ok received %s", actual)
|
||||||
|
}
|
||||||
|
deleteAllContainers()
|
||||||
|
|
||||||
|
logDone("run - test --cap-add=ALL can set eth0 down")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapAddALLDropNetAdminCanDownInterface(t *testing.T) {
|
||||||
|
cmd := exec.Command(dockerBinary, "run", "--cap-add=ALL", "--cap-drop=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
|
||||||
|
out, _, err := runCommandWithOutput(cmd)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual := strings.Trim(out, "\r\n"); actual == "ok" {
|
||||||
|
t.Fatalf("expected output not ok received %s", actual)
|
||||||
|
}
|
||||||
|
deleteAllContainers()
|
||||||
|
|
||||||
|
logDone("run - test --cap-add=ALL --cap-drop=NET_ADMIN cannot set eth0 down")
|
||||||
|
}
|
||||||
|
|
||||||
func TestPrivilegedCanMount(t *testing.T) {
|
func TestPrivilegedCanMount(t *testing.T) {
|
||||||
cmd := exec.Command(dockerBinary, "run", "--privileged", "busybox", "sh", "-c", "mount -t tmpfs none /tmp && echo ok")
|
cmd := exec.Command(dockerBinary, "run", "--privileged", "busybox", "sh", "-c", "mount -t tmpfs none /tmp && echo ok")
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ type HostConfig struct {
|
||||||
VolumesFrom []string
|
VolumesFrom []string
|
||||||
Devices []DeviceMapping
|
Devices []DeviceMapping
|
||||||
NetworkMode NetworkMode
|
NetworkMode NetworkMode
|
||||||
|
CapAdd []string
|
||||||
|
CapDrop []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
|
func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
|
||||||
|
@ -65,5 +67,11 @@ func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
|
||||||
if VolumesFrom := job.GetenvList("VolumesFrom"); VolumesFrom != nil {
|
if VolumesFrom := job.GetenvList("VolumesFrom"); VolumesFrom != nil {
|
||||||
hostConfig.VolumesFrom = VolumesFrom
|
hostConfig.VolumesFrom = VolumesFrom
|
||||||
}
|
}
|
||||||
|
if CapAdd := job.GetenvList("CapAdd"); CapAdd != nil {
|
||||||
|
hostConfig.CapAdd = CapAdd
|
||||||
|
}
|
||||||
|
if CapDrop := job.GetenvList("CapDrop"); CapDrop != nil {
|
||||||
|
hostConfig.CapDrop = CapDrop
|
||||||
|
}
|
||||||
return hostConfig
|
return hostConfig
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,8 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
||||||
flVolumesFrom opts.ListOpts
|
flVolumesFrom opts.ListOpts
|
||||||
flLxcOpts opts.ListOpts
|
flLxcOpts opts.ListOpts
|
||||||
flEnvFile opts.ListOpts
|
flEnvFile opts.ListOpts
|
||||||
|
flCapAdd opts.ListOpts
|
||||||
|
flCapDrop opts.ListOpts
|
||||||
|
|
||||||
flAutoRemove = cmd.Bool([]string{"#rm", "-rm"}, false, "Automatically remove the container when it exits (incompatible with -d)")
|
flAutoRemove = cmd.Bool([]string{"#rm", "-rm"}, false, "Automatically remove the container when it exits (incompatible with -d)")
|
||||||
flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Detached mode: run container in the background and print new container ID")
|
flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Detached mode: run container in the background and print new container ID")
|
||||||
|
@ -86,6 +88,9 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
||||||
cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
|
cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
|
||||||
cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "(lxc exec-driver only) Add custom lxc options --lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
|
cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "(lxc exec-driver only) Add custom lxc options --lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
|
||||||
|
|
||||||
|
cmd.Var(&flCapAdd, []string{"-cap-add"}, "Add Linux capabilities")
|
||||||
|
cmd.Var(&flCapDrop, []string{"-cap-drop"}, "Drop Linux capabilities")
|
||||||
|
|
||||||
if err := cmd.Parse(args); err != nil {
|
if err := cmd.Parse(args); err != nil {
|
||||||
return nil, nil, cmd, err
|
return nil, nil, cmd, err
|
||||||
}
|
}
|
||||||
|
@ -258,6 +263,8 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
||||||
VolumesFrom: flVolumesFrom.GetAll(),
|
VolumesFrom: flVolumesFrom.GetAll(),
|
||||||
NetworkMode: netMode,
|
NetworkMode: netMode,
|
||||||
Devices: deviceMappings,
|
Devices: deviceMappings,
|
||||||
|
CapAdd: flCapAdd.GetAll(),
|
||||||
|
CapDrop: flCapDrop.GetAll(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit {
|
if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit {
|
||||||
|
|
|
@ -3,11 +3,12 @@ package sysinit
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/dotcloud/docker/daemon/execdriver"
|
"github.com/dotcloud/docker/daemon/execdriver"
|
||||||
_ "github.com/dotcloud/docker/daemon/execdriver/lxc"
|
_ "github.com/dotcloud/docker/daemon/execdriver/lxc"
|
||||||
_ "github.com/dotcloud/docker/daemon/execdriver/native"
|
_ "github.com/dotcloud/docker/daemon/execdriver/native"
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func executeProgram(args *execdriver.InitArgs) error {
|
func executeProgram(args *execdriver.InitArgs) error {
|
||||||
|
@ -39,6 +40,8 @@ func SysInit() {
|
||||||
pipe = flag.Int("pipe", 0, "sync pipe fd")
|
pipe = flag.Int("pipe", 0, "sync pipe fd")
|
||||||
console = flag.String("console", "", "console (pty slave) path")
|
console = flag.String("console", "", "console (pty slave) path")
|
||||||
root = flag.String("root", ".", "root path for configuration files")
|
root = flag.String("root", ".", "root path for configuration files")
|
||||||
|
capAdd = flag.String("cap-add", "", "capabilities to add")
|
||||||
|
capDrop = flag.String("cap-drop", "", "capabilities to drop")
|
||||||
)
|
)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
@ -54,6 +57,8 @@ func SysInit() {
|
||||||
Console: *console,
|
Console: *console,
|
||||||
Pipe: *pipe,
|
Pipe: *pipe,
|
||||||
Root: *root,
|
Root: *root,
|
||||||
|
CapAdd: *capAdd,
|
||||||
|
CapDrop: *capDrop,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := executeProgram(args); err != nil {
|
if err := executeProgram(args); err != nil {
|
||||||
|
|
|
@ -907,3 +907,12 @@ func ValidateContextDirectory(srcPath string) error {
|
||||||
})
|
})
|
||||||
return finalError
|
return finalError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StringsContainsNoCase(slice []string, s string) bool {
|
||||||
|
for _, ss := range slice {
|
||||||
|
if strings.ToLower(s) == strings.ToLower(ss) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue