Переглянути джерело

runconfig: add -net container:name option

Docker-DCO-1.1-Signed-off-by: Johan Euphrosine <proppy@google.com> (github: proppy)
Johan Euphrosine 11 роки тому
батько
коміт
a60159f3b1

+ 13 - 2
daemon/container.go

@@ -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)
@@ -351,6 +351,14 @@ func populateCommand(c *Container, env []string) {
 	// TODO: this can be removed after lxc-conf is fully deprecated
 	mergeLxcConfIntoOptions(c.hostConfig, context)
 
+	if netContainer := c.hostConfig.UseContainerNetwork; netContainer != "" {
+		nc := c.daemon.Get(netContainer)
+		if nc == nil {
+			return fmt.Errorf("no such container to join network: %q", netContainer)
+		}
+		en.ContainerID = nc.ID
+	}
+
 	resources := &execdriver.Resources{
 		Memory:     c.Config.Memory,
 		MemorySwap: c.Config.MemorySwap,
@@ -372,6 +380,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 +424,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
 	}

+ 3 - 2
daemon/execdriver/driver.go

@@ -89,8 +89,9 @@ 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.
 }
 
 type NetworkInterface struct {

+ 16 - 0
daemon/execdriver/native/create.go

@@ -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"
@@ -75,6 +76,21 @@ 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
 }
 

+ 14 - 10
runconfig/hostconfig.go

@@ -7,16 +7,17 @@ import (
 )
 
 type HostConfig struct {
-	Binds           []string
-	ContainerIDFile string
-	LxcConf         []utils.KeyValuePair
-	Privileged      bool
-	PortBindings    nat.PortMap
-	Links           []string
-	PublishAllPorts bool
-	Dns             []string
-	DnsSearch       []string
-	VolumesFrom     []string
+	Binds               []string
+	ContainerIDFile     string
+	LxcConf             []utils.KeyValuePair
+	Privileged          bool
+	PortBindings        nat.PortMap
+	Links               []string
+	PublishAllPorts     bool
+	Dns                 []string
+	DnsSearch           []string
+	VolumesFrom         []string
+	UseContainerNetwork string
 }
 
 func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
@@ -42,5 +43,8 @@ func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
 	if VolumesFrom := job.GetenvList("VolumesFrom"); VolumesFrom != nil {
 		hostConfig.VolumesFrom = VolumesFrom
 	}
+	if UseContainerNetwork := job.Getenv("UseContainerNetwork"); UseContainerNetwork != "" {
+		hostConfig.UseContainerNetwork = UseContainerNetwork
+	}
 	return hostConfig
 }

+ 38 - 15
runconfig/parse.go

@@ -2,14 +2,15 @@ package runconfig
 
 import (
 	"fmt"
+	"io/ioutil"
+	"path"
+	"strings"
+
 	"github.com/dotcloud/docker/nat"
 	"github.com/dotcloud/docker/opts"
 	flag "github.com/dotcloud/docker/pkg/mflag"
 	"github.com/dotcloud/docker/pkg/sysinfo"
 	"github.com/dotcloud/docker/utils"
-	"io/ioutil"
-	"path"
-	"strings"
 )
 
 var (
@@ -61,7 +62,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
 		flUser            = cmd.String([]string{"u", "-user"}, "", "Username or UID")
 		flWorkingDir      = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
 		flCpuShares       = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
-
+		flNetMode         = cmd.String([]string{"#net", "-net"}, "bridge", "Set the Network mode for the container ('bridge': creates a new network stack for the container on the docker bridge, 'disable': disable networking for this container, 'container:name_or_id': reuses another container network stack)")
 		// For documentation purpose
 		_ = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)")
 		_ = cmd.String([]string{"#name", "-name"}, "", "Assign a name to the container")
@@ -197,6 +198,11 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
 	// boo, there's no debug output for docker run
 	//utils.Debugf("Environment variables for the container: %#v", envVariables)
 
+	netMode, useContainerNetwork, err := parseNetMode(*flNetMode)
+	if err != nil {
+		return nil, nil, cmd, fmt.Errorf("-net: invalid net mode: %v", err)
+	}
+
 	config := &Config{
 		Hostname:        hostname,
 		Domainname:      domainname,
@@ -204,7 +210,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
 		ExposedPorts:    ports,
 		User:            *flUser,
 		Tty:             *flTty,
-		NetworkDisabled: !*flNetwork,
+		NetworkDisabled: !*flNetwork || netMode == "disable",
 		OpenStdin:       *flStdin,
 		Memory:          flMemory,
 		CpuShares:       *flCpuShares,
@@ -220,16 +226,17 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
 	}
 
 	hostConfig := &HostConfig{
-		Binds:           binds,
-		ContainerIDFile: *flContainerIDFile,
-		LxcConf:         lxcConf,
-		Privileged:      *flPrivileged,
-		PortBindings:    portBindings,
-		Links:           flLinks.GetAll(),
-		PublishAllPorts: *flPublishAll,
-		Dns:             flDns.GetAll(),
-		DnsSearch:       flDnsSearch.GetAll(),
-		VolumesFrom:     flVolumesFrom.GetAll(),
+		Binds:               binds,
+		ContainerIDFile:     *flContainerIDFile,
+		LxcConf:             lxcConf,
+		Privileged:          *flPrivileged,
+		PortBindings:        portBindings,
+		Links:               flLinks.GetAll(),
+		PublishAllPorts:     *flPublishAll,
+		Dns:                 flDns.GetAll(),
+		DnsSearch:           flDnsSearch.GetAll(),
+		VolumesFrom:         flVolumesFrom.GetAll(),
+		UseContainerNetwork: useContainerNetwork,
 	}
 
 	if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit {
@@ -274,3 +281,19 @@ func parseKeyValueOpts(opts opts.ListOpts) ([]utils.KeyValuePair, error) {
 	}
 	return out, nil
 }
+
+func parseNetMode(netMode string) (string, string, error) {
+	parts := strings.Split(netMode, ":")
+	if len(parts) < 1 {
+		return "", "", fmt.Errorf("'netmode' cannot be empty", netMode)
+	}
+	mode := parts[0]
+	var container string
+	if mode == "container" {
+		if len(parts) < 2 {
+			return "", "", fmt.Errorf("'container:' netmode requires a container id or name", netMode)
+		}
+		container = parts[1]
+	}
+	return mode, container, nil
+}