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:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user