mirror of
https://github.com/moby/moby.git
synced 2025-12-24 13:21:20 +03:00
We now have one place that keeps track of (most) devices that are allowed and created within the container. That place is pkg/libcontainer/devices/devices.go This fixes several inconsistencies between which devices were created in the lxc backend and the native backend. It also fixes inconsistencies between wich devices were created and which were allowed. For example, /dev/full was being created but it was not allowed within the cgroup. It also declares the file modes and permissions of the default devices, rather than copying them from the host. This is in line with docker's philosphy of not being host dependent. Docker-DCO-1.1-Signed-off-by: Timothy Hobbs <timothyhobbs@seznam.cz> (github: https://github.com/timthelion)
148 lines
4.2 KiB
Go
148 lines
4.2 KiB
Go
package native
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
|
|
"github.com/dotcloud/docker/daemon/execdriver"
|
|
"github.com/dotcloud/docker/daemon/execdriver/native/configuration"
|
|
"github.com/dotcloud/docker/daemon/execdriver/native/template"
|
|
"github.com/dotcloud/docker/pkg/apparmor"
|
|
"github.com/dotcloud/docker/pkg/libcontainer"
|
|
)
|
|
|
|
// createContainer populates and configures the container type with the
|
|
// data provided by the execdriver.Command
|
|
func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Container, error) {
|
|
container := template.New()
|
|
|
|
container.Hostname = getEnv("HOSTNAME", c.Env)
|
|
container.Tty = c.Tty
|
|
container.User = c.User
|
|
container.WorkingDir = c.WorkingDir
|
|
container.Env = c.Env
|
|
container.Cgroups.Name = c.ID
|
|
container.Cgroups.AllowedDevices = c.AllowedDevices
|
|
container.DeviceNodes = c.AutoCreatedDevices
|
|
// check to see if we are running in ramdisk to disable pivot root
|
|
container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
|
|
container.Context["restrictions"] = "true"
|
|
|
|
if err := d.createNetwork(container, c); err != nil {
|
|
return nil, err
|
|
}
|
|
if c.Privileged {
|
|
if err := d.setPrivileged(container); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if err := d.setupCgroups(container, c); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := d.setupMounts(container, c); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := d.setupLabels(container, c); err != nil {
|
|
return nil, err
|
|
}
|
|
cmds := make(map[string]*exec.Cmd)
|
|
for k, v := range d.activeContainers {
|
|
cmds[k] = v.cmd
|
|
}
|
|
if err := configuration.ParseConfiguration(container, cmds, c.Config["native"]); err != nil {
|
|
return nil, err
|
|
}
|
|
return container, nil
|
|
}
|
|
|
|
func (d *driver) createNetwork(container *libcontainer.Container, c *execdriver.Command) error {
|
|
if c.Network.HostNetworking {
|
|
container.Namespaces["NEWNET"] = false
|
|
return nil
|
|
}
|
|
container.Networks = []*libcontainer.Network{
|
|
{
|
|
Mtu: c.Network.Mtu,
|
|
Address: fmt.Sprintf("%s/%d", "127.0.0.1", 0),
|
|
Gateway: "localhost",
|
|
Type: "loopback",
|
|
Context: libcontainer.Context{},
|
|
},
|
|
}
|
|
|
|
if c.Network.Interface != nil {
|
|
vethNetwork := libcontainer.Network{
|
|
Mtu: c.Network.Mtu,
|
|
Address: fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
|
|
Gateway: c.Network.Interface.Gateway,
|
|
Type: "veth",
|
|
Context: libcontainer.Context{
|
|
"prefix": "veth",
|
|
"bridge": c.Network.Interface.Bridge,
|
|
},
|
|
}
|
|
container.Networks = append(container.Networks, &vethNetwork)
|
|
}
|
|
|
|
if c.Network.ContainerID != "" {
|
|
active := d.activeContainers[c.Network.ContainerID]
|
|
if active == nil || active.cmd.Process == nil {
|
|
return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
|
|
}
|
|
cmd := active.cmd
|
|
|
|
nspath := filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "net")
|
|
container.Networks = append(container.Networks, &libcontainer.Network{
|
|
Type: "netns",
|
|
Context: libcontainer.Context{
|
|
"nspath": nspath,
|
|
},
|
|
})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *driver) setPrivileged(container *libcontainer.Container) (err error) {
|
|
container.Capabilities = libcontainer.GetAllCapabilities()
|
|
container.Cgroups.AllowAllDevices = true
|
|
|
|
delete(container.Context, "restrictions")
|
|
|
|
if apparmor.IsEnabled() {
|
|
container.Context["apparmor_profile"] = "unconfined"
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *driver) setupCgroups(container *libcontainer.Container, c *execdriver.Command) error {
|
|
if c.Resources != nil {
|
|
container.Cgroups.CpuShares = c.Resources.CpuShares
|
|
container.Cgroups.Memory = c.Resources.Memory
|
|
container.Cgroups.MemoryReservation = c.Resources.Memory
|
|
container.Cgroups.MemorySwap = c.Resources.MemorySwap
|
|
container.Cgroups.CpusetCpus = c.Resources.Cpuset
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *driver) setupMounts(container *libcontainer.Container, c *execdriver.Command) error {
|
|
for _, m := range c.Mounts {
|
|
container.Mounts = append(container.Mounts, libcontainer.Mount{
|
|
Type: "bind",
|
|
Source: m.Source,
|
|
Destination: m.Destination,
|
|
Writable: m.Writable,
|
|
Private: m.Private,
|
|
})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *driver) setupLabels(container *libcontainer.Container, c *execdriver.Command) error {
|
|
container.Context["process_label"] = c.Config["process_label"][0]
|
|
container.Context["mount_label"] = c.Config["mount_label"][0]
|
|
return nil
|
|
}
|