Merge pull request #4441 from crosbymichael/add-net-flag

Add --net flag to docker run and allow host network stack
Upstream-commit: 70fef1460a9d253bdf164d70d7057ec4ee497e08
Component: engine
This commit is contained in:
Guillaume J. Charmes
2014-05-05 13:54:55 -07:00
9 changed files with 209 additions and 30 deletions
+91 -14
View File
@@ -325,7 +325,7 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
})
}
func populateCommand(c *Container, env []string) {
func populateCommand(c *Container, env []string) error {
var (
en *execdriver.Network
context = make(map[string][]string)
@@ -338,14 +338,29 @@ func populateCommand(c *Container, env []string) {
Interface: nil,
}
if !c.Config.NetworkDisabled {
network := c.NetworkSettings
en.Interface = &execdriver.NetworkInterface{
Gateway: network.Gateway,
Bridge: network.Bridge,
IPAddress: network.IPAddress,
IPPrefixLen: network.IPPrefixLen,
parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
switch parts[0] {
case "none":
case "host":
en.HostNetworking = true
case "bridge", "": // empty string to support existing containers
if !c.Config.NetworkDisabled {
network := c.NetworkSettings
en.Interface = &execdriver.NetworkInterface{
Gateway: network.Gateway,
Bridge: network.Bridge,
IPAddress: network.IPAddress,
IPPrefixLen: network.IPPrefixLen,
}
}
case "container":
nc, err := c.getNetworkedContainer()
if err != nil {
return err
}
en.ContainerID = nc.ID
default:
return fmt.Errorf("invalid network mode: %s", c.hostConfig.NetworkMode)
}
// TODO: this can be removed after lxc-conf is fully deprecated
@@ -372,6 +387,7 @@ func populateCommand(c *Container, env []string) {
}
c.command.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
c.command.Env = env
return nil
}
func (container *Container) Start() (err error) {
@@ -415,7 +431,9 @@ func (container *Container) Start() (err error) {
if err := container.setupWorkingDirectory(); err != nil {
return err
}
populateCommand(container, env)
if err := populateCommand(container, env); err != nil {
return err
}
if err := setupMountsForContainer(container); err != nil {
return err
}
@@ -485,9 +503,18 @@ func (container *Container) StderrLogPipe() io.ReadCloser {
return utils.NewBufReader(reader)
}
func (container *Container) buildHostnameAndHostsFiles(IP string) {
func (container *Container) buildHostname() {
container.HostnamePath = path.Join(container.root, "hostname")
ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
if container.Config.Domainname != "" {
ioutil.WriteFile(container.HostnamePath, []byte(fmt.Sprintf("%s.%s\n", container.Config.Hostname, container.Config.Domainname)), 0644)
} else {
ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
}
}
func (container *Container) buildHostnameAndHostsFiles(IP string) {
container.buildHostname()
hostsContent := []byte(`
127.0.0.1 localhost
@@ -505,12 +532,12 @@ ff02::2 ip6-allrouters
} else if !container.Config.NetworkDisabled {
hostsContent = append([]byte(fmt.Sprintf("%s\t%s\n", IP, container.Config.Hostname)), hostsContent...)
}
ioutil.WriteFile(container.HostsPath, hostsContent, 0644)
}
func (container *Container) allocateNetwork() error {
if container.Config.NetworkDisabled {
mode := container.hostConfig.NetworkMode
if container.Config.NetworkDisabled || mode.IsContainer() || mode.IsHost() {
return nil
}
@@ -963,14 +990,22 @@ func (container *Container) setupContainerDns() error {
if container.ResolvConfPath != "" {
return nil
}
var (
config = container.hostConfig
daemon = container.daemon
)
if config.NetworkMode == "host" {
container.ResolvConfPath = "/etc/resolv.conf"
return nil
}
resolvConf, err := utils.GetResolvConf()
if err != nil {
return err
}
// If custom dns exists, then create a resolv.conf for the container
if len(config.Dns) > 0 || len(daemon.config.Dns) > 0 || len(config.DnsSearch) > 0 || len(daemon.config.DnsSearch) > 0 {
var (
@@ -1010,7 +1045,32 @@ func (container *Container) setupContainerDns() error {
}
func (container *Container) initializeNetworking() error {
if container.daemon.config.DisableNetwork {
var err error
if container.hostConfig.NetworkMode.IsHost() {
container.Config.Hostname, err = os.Hostname()
if err != nil {
return err
}
parts := strings.SplitN(container.Config.Hostname, ".", 2)
if len(parts) > 1 {
container.Config.Hostname = parts[0]
container.Config.Domainname = parts[1]
}
container.HostsPath = "/etc/hosts"
container.buildHostname()
} else if container.hostConfig.NetworkMode.IsContainer() {
// we need to get the hosts files from the container to join
nc, err := container.getNetworkedContainer()
if err != nil {
return err
}
container.HostsPath = nc.HostsPath
container.ResolvConfPath = nc.ResolvConfPath
container.Config.Hostname = nc.Config.Hostname
container.Config.Domainname = nc.Config.Domainname
} else if container.daemon.config.DisableNetwork {
container.Config.NetworkDisabled = true
container.buildHostnameAndHostsFiles("127.0.1.1")
} else {
@@ -1219,3 +1279,20 @@ func (container *Container) GetMountLabel() string {
}
return container.MountLabel
}
func (container *Container) getNetworkedContainer() (*Container, error) {
parts := strings.SplitN(string(container.hostConfig.NetworkMode), ":", 2)
switch parts[0] {
case "container":
nc := container.daemon.Get(parts[1])
if nc == nil {
return nil, fmt.Errorf("no such container to join network: %s", parts[1])
}
if !nc.State.IsRunning() {
return nil, fmt.Errorf("cannot join network of a non running container: %s", parts[1])
}
return nc, nil
default:
return nil, fmt.Errorf("network mode not set to container")
}
}
@@ -89,8 +89,10 @@ type Driver interface {
// Network settings of the container
type Network struct {
Interface *NetworkInterface `json:"interface"` // if interface is nil then networking is disabled
Mtu int `json:"mtu"`
Interface *NetworkInterface `json:"interface"` // if interface is nil then networking is disabled
Mtu int `json:"mtu"`
ContainerID string `json:"container_id"` // id of the container to join network.
HostNetworking bool `json:"host_networking"`
}
type NetworkInterface struct {
@@ -3,15 +3,16 @@ package lxc
import (
"encoding/json"
"fmt"
"github.com/dotcloud/docker/daemon/execdriver"
"github.com/dotcloud/docker/pkg/netlink"
"github.com/dotcloud/docker/pkg/user"
"github.com/syndtr/gocapability/capability"
"io/ioutil"
"net"
"os"
"strings"
"syscall"
"github.com/dotcloud/docker/daemon/execdriver"
"github.com/dotcloud/docker/pkg/netlink"
"github.com/dotcloud/docker/pkg/user"
"github.com/syndtr/gocapability/capability"
)
// Clear environment pollution introduced by lxc-start
@@ -14,12 +14,13 @@ const LxcTemplate = `
lxc.network.type = veth
lxc.network.link = {{.Network.Interface.Bridge}}
lxc.network.name = eth0
{{else}}
lxc.network.mtu = {{.Network.Mtu}}
{{else if not .Network.HostNetworking}}
# network is disabled (-n=false)
lxc.network.type = empty
lxc.network.flags = up
{{end}}
lxc.network.mtu = {{.Network.Mtu}}
{{end}}
# root filesystem
{{$ROOTFS := .Rootfs}}
@@ -3,6 +3,7 @@ package native
import (
"fmt"
"os"
"path/filepath"
"github.com/dotcloud/docker/daemon/execdriver"
"github.com/dotcloud/docker/daemon/execdriver/native/configuration"
@@ -52,6 +53,10 @@ func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Container
}
func (d *driver) createNetwork(container *libcontainer.Container, c *execdriver.Command) error {
if c.Network.HostNetworking {
container.Namespaces.Get("NEWNET").Enabled = false
return nil
}
container.Networks = []*libcontainer.Network{
{
Mtu: c.Network.Mtu,
@@ -75,6 +80,20 @@ func (d *driver) createNetwork(container *libcontainer.Container, c *execdriver.
}
container.Networks = append(container.Networks, &vethNetwork)
}
if c.Network.ContainerID != "" {
cmd := d.activeContainers[c.Network.ContainerID]
if cmd == nil || cmd.Process == nil {
return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
}
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
}