|
@@ -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")
|
|
|
+ }
|
|
|
+}
|