mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Windows: Enable NAT port mapping
Signed-off-by: John Howard <jhoward@microsoft.com>
This commit is contained in:
parent
b9094633f3
commit
4393be7100
8 changed files with 126 additions and 53 deletions
|
@ -55,19 +55,23 @@ func (container *Container) setupWorkingDirectory() error {
|
||||||
|
|
||||||
func populateCommand(c *Container, env []string) error {
|
func populateCommand(c *Container, env []string) error {
|
||||||
en := &execdriver.Network{
|
en := &execdriver.Network{
|
||||||
Mtu: c.daemon.config.Mtu,
|
|
||||||
Interface: nil,
|
Interface: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
|
parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
|
||||||
switch parts[0] {
|
switch parts[0] {
|
||||||
|
|
||||||
case "none":
|
case "none":
|
||||||
case "default", "": // empty string to support existing containers
|
case "default", "": // empty string to support existing containers
|
||||||
if !c.Config.NetworkDisabled {
|
if !c.Config.NetworkDisabled {
|
||||||
en.Interface = &execdriver.NetworkInterface{
|
en.Interface = &execdriver.NetworkInterface{
|
||||||
MacAddress: c.Config.MacAddress,
|
MacAddress: c.Config.MacAddress,
|
||||||
Bridge: c.daemon.config.Bridge.VirtualSwitchName,
|
Bridge: c.daemon.config.Bridge.VirtualSwitchName,
|
||||||
|
PortBindings: c.hostConfig.PortBindings,
|
||||||
|
|
||||||
|
// TODO Windows. Include IPAddress. There already is a
|
||||||
|
// property IPAddress on execDrive.CommonNetworkInterface,
|
||||||
|
// but there is no CLI option in docker to pass through
|
||||||
|
// an IPAddress on docker run.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -91,15 +91,6 @@ type Driver interface {
|
||||||
Stats(id string) (*ResourceStats, error)
|
Stats(id string) (*ResourceStats, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Network settings of the container
|
|
||||||
type Network struct {
|
|
||||||
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.
|
|
||||||
NamespacePath string `json:"namespace_path"`
|
|
||||||
HostNetworking bool `json:"host_networking"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ipc settings of the container
|
// Ipc settings of the container
|
||||||
// It is for IPC namespace setting. Usually different containers
|
// It is for IPC namespace setting. Usually different containers
|
||||||
// have their own IPC namespace, however this specifies to use
|
// have their own IPC namespace, however this specifies to use
|
||||||
|
@ -130,20 +121,6 @@ type UTS struct {
|
||||||
HostUTS bool `json:"host_uts"`
|
HostUTS bool `json:"host_uts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkInterface contains all network configs for a driver
|
|
||||||
type NetworkInterface struct {
|
|
||||||
Gateway string `json:"gateway"`
|
|
||||||
IPAddress string `json:"ip"`
|
|
||||||
IPPrefixLen int `json:"ip_prefix_len"`
|
|
||||||
MacAddress string `json:"mac"`
|
|
||||||
Bridge string `json:"bridge"`
|
|
||||||
GlobalIPv6Address string `json:"global_ipv6"`
|
|
||||||
LinkLocalIPv6Address string `json:"link_local_ipv6"`
|
|
||||||
GlobalIPv6PrefixLen int `json:"global_ipv6_prefix_len"`
|
|
||||||
IPv6Gateway string `json:"ipv6_gateway"`
|
|
||||||
HairpinMode bool `json:"hairpin_mode"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resources contains all resource configs for a driver.
|
// Resources contains all resource configs for a driver.
|
||||||
// Currently these are all for cgroup configs.
|
// Currently these are all for cgroup configs.
|
||||||
// TODO Windows: Factor out ulimit.Rlimit
|
// TODO Windows: Factor out ulimit.Rlimit
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
package execdriver
|
package execdriver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -15,6 +17,14 @@ import (
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Network settings of the container
|
||||||
|
type Network struct {
|
||||||
|
Mtu int `json:"mtu"`
|
||||||
|
ContainerID string `json:"container_id"` // id of the container to join network.
|
||||||
|
NamespacePath string `json:"namespace_path"`
|
||||||
|
HostNetworking bool `json:"host_networking"`
|
||||||
|
}
|
||||||
|
|
||||||
// InitContainer is the initialization of a container config.
|
// InitContainer is the initialization of a container config.
|
||||||
// It returns the initial configs for a container. It's mostly
|
// It returns the initial configs for a container. It's mostly
|
||||||
// defined by the default template.
|
// defined by the default template.
|
20
daemon/execdriver/driver_windows.go
Normal file
20
daemon/execdriver/driver_windows.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package execdriver
|
||||||
|
|
||||||
|
import "github.com/docker/docker/pkg/nat"
|
||||||
|
|
||||||
|
// Network settings of the container
|
||||||
|
type Network struct {
|
||||||
|
Interface *NetworkInterface `json:"interface"`
|
||||||
|
ContainerID string `json:"container_id"` // id of the container to join network.
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkInterface contains network configs for a driver
|
||||||
|
type NetworkInterface struct {
|
||||||
|
MacAddress string `json:"mac"`
|
||||||
|
Bridge string `json:"bridge"`
|
||||||
|
IPAddress string `json:"ip"`
|
||||||
|
|
||||||
|
// PortBindings is the port mapping between the exposed port in the
|
||||||
|
// container and the port on the host.
|
||||||
|
PortBindings nat.PortMap `json:"port_bindings"`
|
||||||
|
}
|
|
@ -128,17 +128,6 @@ lxc.{{$value}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{if .Network.Interface}}
|
|
||||||
{{if .Network.Interface.IPAddress}}
|
|
||||||
lxc.network.ipv4 = {{.Network.Interface.IPAddress}}/{{.Network.Interface.IPPrefixLen}}
|
|
||||||
{{end}}
|
|
||||||
{{if .Network.Interface.Gateway}}
|
|
||||||
lxc.network.ipv4.gateway = {{.Network.Interface.Gateway}}
|
|
||||||
{{end}}
|
|
||||||
{{if .Network.Interface.MacAddress}}
|
|
||||||
lxc.network.hwaddr = {{.Network.Interface.MacAddress}}
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
{{if .ProcessConfig.Env}}
|
{{if .ProcessConfig.Env}}
|
||||||
lxc.utsname = {{getHostname .ProcessConfig.Env}}
|
lxc.utsname = {{getHostname .ProcessConfig.Env}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -50,8 +50,7 @@ func TestLXCConfig(t *testing.T) {
|
||||||
CPUShares: int64(cpu),
|
CPUShares: int64(cpu),
|
||||||
},
|
},
|
||||||
Network: &execdriver.Network{
|
Network: &execdriver.Network{
|
||||||
Mtu: 1500,
|
Mtu: 1500,
|
||||||
Interface: nil,
|
|
||||||
},
|
},
|
||||||
AllowedDevices: make([]*configs.Device, 0),
|
AllowedDevices: make([]*configs.Device, 0),
|
||||||
ProcessConfig: execdriver.ProcessConfig{},
|
ProcessConfig: execdriver.ProcessConfig{},
|
||||||
|
@ -90,8 +89,7 @@ func TestCustomLxcConfig(t *testing.T) {
|
||||||
"lxc.cgroup.cpuset.cpus = 0,1",
|
"lxc.cgroup.cpuset.cpus = 0,1",
|
||||||
},
|
},
|
||||||
Network: &execdriver.Network{
|
Network: &execdriver.Network{
|
||||||
Mtu: 1500,
|
Mtu: 1500,
|
||||||
Interface: nil,
|
|
||||||
},
|
},
|
||||||
ProcessConfig: processConfig,
|
ProcessConfig: processConfig,
|
||||||
}
|
}
|
||||||
|
@ -222,8 +220,7 @@ func TestCustomLxcConfigMounts(t *testing.T) {
|
||||||
"lxc.cgroup.cpuset.cpus = 0,1",
|
"lxc.cgroup.cpuset.cpus = 0,1",
|
||||||
},
|
},
|
||||||
Network: &execdriver.Network{
|
Network: &execdriver.Network{
|
||||||
Mtu: 1500,
|
Mtu: 1500,
|
||||||
Interface: nil,
|
|
||||||
},
|
},
|
||||||
Mounts: mounts,
|
Mounts: mounts,
|
||||||
ProcessConfig: processConfig,
|
ProcessConfig: processConfig,
|
||||||
|
@ -264,8 +261,7 @@ func TestCustomLxcConfigMisc(t *testing.T) {
|
||||||
"lxc.cgroup.cpuset.cpus = 0,1",
|
"lxc.cgroup.cpuset.cpus = 0,1",
|
||||||
},
|
},
|
||||||
Network: &execdriver.Network{
|
Network: &execdriver.Network{
|
||||||
Mtu: 1500,
|
Mtu: 1500,
|
||||||
Interface: nil,
|
|
||||||
},
|
},
|
||||||
ProcessConfig: processConfig,
|
ProcessConfig: processConfig,
|
||||||
CapAdd: []string{"net_admin", "syslog"},
|
CapAdd: []string{"net_admin", "syslog"},
|
||||||
|
@ -317,8 +313,7 @@ func TestCustomLxcConfigMiscOverride(t *testing.T) {
|
||||||
"lxc.network.ipv4 = 172.0.0.1",
|
"lxc.network.ipv4 = 172.0.0.1",
|
||||||
},
|
},
|
||||||
Network: &execdriver.Network{
|
Network: &execdriver.Network{
|
||||||
Mtu: 1500,
|
Mtu: 1500,
|
||||||
Interface: nil,
|
|
||||||
},
|
},
|
||||||
ProcessConfig: processConfig,
|
ProcessConfig: processConfig,
|
||||||
CapAdd: []string{"NET_ADMIN", "SYSLOG"},
|
CapAdd: []string{"NET_ADMIN", "SYSLOG"},
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
|
@ -16,6 +18,10 @@ import (
|
||||||
"github.com/natefinch/npipe"
|
"github.com/natefinch/npipe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// defaultContainerNAT is the default name of the container NAT device that is
|
||||||
|
// preconfigured on the server.
|
||||||
|
const defaultContainerNAT = "ContainerNAT"
|
||||||
|
|
||||||
type layer struct {
|
type layer struct {
|
||||||
ID string
|
ID string
|
||||||
Path string
|
Path string
|
||||||
|
@ -25,9 +31,23 @@ type defConfig struct {
|
||||||
DefFile string
|
DefFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type portBinding struct {
|
||||||
|
Protocol string
|
||||||
|
InternalPort int
|
||||||
|
ExternalPort int
|
||||||
|
}
|
||||||
|
|
||||||
|
type natSettings struct {
|
||||||
|
Name string
|
||||||
|
PortBindings []portBinding
|
||||||
|
}
|
||||||
|
|
||||||
type networkConnection struct {
|
type networkConnection struct {
|
||||||
NetworkName string
|
NetworkName string
|
||||||
EnableNat bool
|
// TODO Windows: Add Ip4Address string to this structure when hooked up in
|
||||||
|
// docker CLI. This is present in the HCS JSON handler.
|
||||||
|
EnableNat bool
|
||||||
|
Nat natSettings
|
||||||
}
|
}
|
||||||
type networkSettings struct {
|
type networkSettings struct {
|
||||||
MacAddress string
|
MacAddress string
|
||||||
|
@ -81,12 +101,72 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Windows. At some point, when there is CLI on docker run to
|
||||||
|
// enable the IP Address of the container to be passed into docker run,
|
||||||
|
// the IP Address needs to be wired through to HCS in the JSON. It
|
||||||
|
// would be present in c.Network.Interface.IPAddress. See matching
|
||||||
|
// TODO in daemon\container_windows.go, function populateCommand.
|
||||||
|
|
||||||
if c.Network.Interface != nil {
|
if c.Network.Interface != nil {
|
||||||
|
|
||||||
|
var pbs []portBinding
|
||||||
|
|
||||||
|
// Enumerate through the port bindings specified by the user and convert
|
||||||
|
// them into the internal structure matching the JSON blob that can be
|
||||||
|
// understood by the HCS.
|
||||||
|
for i, v := range c.Network.Interface.PortBindings {
|
||||||
|
proto := strings.ToUpper(i.Proto())
|
||||||
|
if proto != "TCP" && proto != "UDP" {
|
||||||
|
return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("invalid protocol %s", i.Proto())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(v) > 1 {
|
||||||
|
return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("Windows does not support more than one host port in NAT settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v2 := range v {
|
||||||
|
var (
|
||||||
|
iPort, ePort int
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if len(v2.HostIP) != 0 {
|
||||||
|
return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("Windows does not support host IP addresses in NAT settings")
|
||||||
|
}
|
||||||
|
if ePort, err = strconv.Atoi(v2.HostPort); err != nil {
|
||||||
|
return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("invalid container port %s: %s", v2.HostPort, err)
|
||||||
|
}
|
||||||
|
if iPort, err = strconv.Atoi(i.Port()); err != nil {
|
||||||
|
return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("invalid internal port %s: %s", i.Port(), err)
|
||||||
|
}
|
||||||
|
if iPort < 0 || iPort > 65535 || ePort < 0 || ePort > 65535 {
|
||||||
|
return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("specified NAT port is not in allowed range")
|
||||||
|
}
|
||||||
|
pbs = append(pbs,
|
||||||
|
portBinding{ExternalPort: ePort,
|
||||||
|
InternalPort: iPort,
|
||||||
|
Protocol: proto})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Windows: TP3 workaround. Allow the user to override the name of
|
||||||
|
// the Container NAT device through an environment variable. This will
|
||||||
|
// ultimately be a global daemon parameter on Windows, similar to -b
|
||||||
|
// for the name of the virtual switch (aka bridge).
|
||||||
|
cn := os.Getenv("DOCKER_CONTAINER_NAT")
|
||||||
|
if len(cn) == 0 {
|
||||||
|
cn = defaultContainerNAT
|
||||||
|
}
|
||||||
|
|
||||||
dev := device{
|
dev := device{
|
||||||
DeviceType: "Network",
|
DeviceType: "Network",
|
||||||
Connection: &networkConnection{
|
Connection: &networkConnection{
|
||||||
NetworkName: c.Network.Interface.Bridge,
|
NetworkName: c.Network.Interface.Bridge,
|
||||||
EnableNat: false,
|
// TODO Windows: Fixme, next line. Needs HCS fix.
|
||||||
|
EnableNat: false,
|
||||||
|
Nat: natSettings{
|
||||||
|
Name: cn,
|
||||||
|
PortBindings: pbs,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,9 +177,6 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
MacAddress: windowsStyleMAC,
|
MacAddress: windowsStyleMAC,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf("Virtual switch '%s', mac='%s'", c.Network.Interface.Bridge, c.Network.Interface.MacAddress)
|
|
||||||
|
|
||||||
cu.Devices = append(cu.Devices, dev)
|
cu.Devices = append(cu.Devices, dev)
|
||||||
} else {
|
} else {
|
||||||
logrus.Debugln("No network interface")
|
logrus.Debugln("No network interface")
|
||||||
|
|
|
@ -9,6 +9,7 @@ type Address struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Settings stores configuration details about the daemon network config
|
// Settings stores configuration details about the daemon network config
|
||||||
|
// TODO Windows. Many of these fields can be factored out.,
|
||||||
type Settings struct {
|
type Settings struct {
|
||||||
Bridge string
|
Bridge string
|
||||||
EndpointID string
|
EndpointID string
|
||||||
|
|
Loading…
Add table
Reference in a new issue