diff --git a/daemon/container.go b/daemon/container.go index 9a08f87133..123eca0263 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -338,7 +338,7 @@ func populateCommand(c *Container, env []string) error { Interface: nil, } - parts := strings.SplitN(c.hostConfig.NetworkMode, ":", 2) + parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2) switch parts[0] { case "none": case "host": @@ -354,9 +354,9 @@ func populateCommand(c *Container, env []string) error { } } case "container": - nc := c.daemon.Get(parts[1]) - if nc == nil { - return fmt.Errorf("no such container to join network: %q", parts[1]) + nc, err := c.getNetworkedContainer() + if err != nil { + return err } en.ContainerID = nc.ID default: @@ -536,7 +536,8 @@ ff02::2 ip6-allrouters } func (container *Container) allocateNetwork() error { - if container.Config.NetworkDisabled || container.hostConfig.NetworkMode == "host" { + mode := container.hostConfig.NetworkMode + if container.Config.NetworkDisabled || mode.IsContainer() || mode.IsHost() { return nil } @@ -1045,7 +1046,7 @@ func (container *Container) setupContainerDns() error { func (container *Container) initializeNetworking() error { var err error - if container.hostConfig.NetworkMode == "host" { + if container.hostConfig.NetworkMode.IsHost() { container.Config.Hostname, err = os.Hostname() if err != nil { return err @@ -1059,6 +1060,16 @@ func (container *Container) initializeNetworking() error { 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") @@ -1268,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") + } +} diff --git a/runconfig/hostconfig.go b/runconfig/hostconfig.go index 83688367e3..79ffad723b 100644 --- a/runconfig/hostconfig.go +++ b/runconfig/hostconfig.go @@ -1,11 +1,24 @@ package runconfig import ( + "strings" + "github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/nat" "github.com/dotcloud/docker/utils" ) +type NetworkMode string + +func (n NetworkMode) IsHost() bool { + return n == "host" +} + +func (n NetworkMode) IsContainer() bool { + parts := strings.SplitN(string(n), ":", 2) + return len(parts) > 1 && parts[0] == "container" +} + type HostConfig struct { Binds []string ContainerIDFile string @@ -17,7 +30,7 @@ type HostConfig struct { Dns []string DnsSearch []string VolumesFrom []string - NetworkMode string + NetworkMode NetworkMode } func ContainerHostConfigFromJob(job *engine.Job) *HostConfig { @@ -25,7 +38,7 @@ func ContainerHostConfigFromJob(job *engine.Job) *HostConfig { ContainerIDFile: job.Getenv("ContainerIDFile"), Privileged: job.GetenvBool("Privileged"), PublishAllPorts: job.GetenvBool("PublishAllPorts"), - NetworkMode: job.Getenv("NetworkMode"), + NetworkMode: NetworkMode(job.Getenv("NetworkMode")), } job.GetenvJson("LxcConf", &hostConfig.LxcConf) job.GetenvJson("PortBindings", &hostConfig.PortBindings) diff --git a/runconfig/parse.go b/runconfig/parse.go index eb9886bb97..0d511ef2ec 100644 --- a/runconfig/parse.go +++ b/runconfig/parse.go @@ -62,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"}, "bridge", "Set the Network mode for the container ('bridge': creates a new network stack for the container on the docker bridge, 'none': no networking for this container, 'container:name_or_id': reuses another container network stack)") + flNetMode = cmd.String([]string{"-net"}, "bridge", "Set the Network mode for the container ('bridge': creates a new network stack for the container on the docker bridge, 'none': no networking for this container, 'container:': 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") @@ -200,7 +200,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf netMode, err := parseNetMode(*flNetMode) if err != nil { - return nil, nil, cmd, fmt.Errorf("-net: invalid net mode: %v", err) + return nil, nil, cmd, fmt.Errorf("--net: invalid net mode: %v", err) } config := &Config{ @@ -282,19 +282,16 @@ func parseKeyValueOpts(opts opts.ListOpts) ([]utils.KeyValuePair, error) { return out, nil } -func parseNetMode(netMode string) (string, error) { +func parseNetMode(netMode string) (NetworkMode, error) { parts := strings.Split(netMode, ":") switch mode := parts[0]; mode { - case "bridge", "none": - return mode, nil + case "bridge", "none", "host": case "container": if len(parts) < 2 || parts[1] == "" { - return "", fmt.Errorf("'container:' netmode requires a container id or name", netMode) + return "", fmt.Errorf("invalid container format container:") } - return netMode, nil - case "host": - return netMode, nil default: - return "", fmt.Errorf("invalid netmode: %q", netMode) + return "", fmt.Errorf("invalid --net: %s", netMode) } + return NetworkMode(netMode), nil }