Signed-off-by: Sylvain Baubeau <sbaubeau@redhat.com>
| ... | ... |
@@ -58,6 +58,8 @@ func (config *Config) InstallFlags() {
|
| 58 | 58 |
flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
|
| 59 | 59 |
flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
|
| 60 | 60 |
flag.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
|
| 61 |
+ flag.StringVar(&config.Bridge.DefaultGatewayIPv4, []string{"-default-gateway"}, "", "Container default gateway IPv4 address")
|
|
| 62 |
+ flag.StringVar(&config.Bridge.DefaultGatewayIPv6, []string{"-default-gateway-v6"}, "", "Container default gateway IPv6 address")
|
|
| 61 | 63 |
flag.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
|
| 62 | 64 |
flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Storage driver to use")
|
| 63 | 65 |
flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Exec driver to use")
|
| ... | ... |
@@ -77,8 +77,10 @@ var ( |
| 77 | 77 |
|
| 78 | 78 |
bridgeIface string |
| 79 | 79 |
bridgeIPv4Network *net.IPNet |
| 80 |
+ gatewayIPv4 net.IP |
|
| 80 | 81 |
bridgeIPv6Addr net.IP |
| 81 | 82 |
globalIPv6Network *net.IPNet |
| 83 |
+ gatewayIPv6 net.IP |
|
| 82 | 84 |
portMapper *portmapper.PortMapper |
| 83 | 85 |
once sync.Once |
| 84 | 86 |
|
| ... | ... |
@@ -103,6 +105,8 @@ type Config struct {
|
| 103 | 103 |
IP string |
| 104 | 104 |
FixedCIDR string |
| 105 | 105 |
FixedCIDRv6 string |
| 106 |
+ DefaultGatewayIPv4 string |
|
| 107 |
+ DefaultGatewayIPv6 string |
|
| 106 | 108 |
InterContainerCommunication bool |
| 107 | 109 |
} |
| 108 | 110 |
|
| ... | ... |
@@ -278,6 +282,12 @@ func InitDriver(config *Config) error {
|
| 278 | 278 |
} |
| 279 | 279 |
} |
| 280 | 280 |
|
| 281 |
+ if gateway, err := requestDefaultGateway(config.DefaultGatewayIPv4, bridgeIPv4Network); err != nil {
|
|
| 282 |
+ return err |
|
| 283 |
+ } else {
|
|
| 284 |
+ gatewayIPv4 = gateway |
|
| 285 |
+ } |
|
| 286 |
+ |
|
| 281 | 287 |
if config.FixedCIDRv6 != "" {
|
| 282 | 288 |
_, subnet, err := net.ParseCIDR(config.FixedCIDRv6) |
| 283 | 289 |
if err != nil {
|
| ... | ... |
@@ -289,6 +299,12 @@ func InitDriver(config *Config) error {
|
| 289 | 289 |
return err |
| 290 | 290 |
} |
| 291 | 291 |
globalIPv6Network = subnet |
| 292 |
+ |
|
| 293 |
+ if gateway, err := requestDefaultGateway(config.DefaultGatewayIPv6, globalIPv6Network); err != nil {
|
|
| 294 |
+ return err |
|
| 295 |
+ } else {
|
|
| 296 |
+ gatewayIPv6 = gateway |
|
| 297 |
+ } |
|
| 292 | 298 |
} |
| 293 | 299 |
|
| 294 | 300 |
// Block BridgeIP in IP allocator |
| ... | ... |
@@ -473,6 +489,24 @@ func setupIPv6Bridge(bridgeIPv6 string) error {
|
| 473 | 473 |
return nil |
| 474 | 474 |
} |
| 475 | 475 |
|
| 476 |
+func requestDefaultGateway(requestedGateway string, network *net.IPNet) (gateway net.IP, err error) {
|
|
| 477 |
+ if requestedGateway != "" {
|
|
| 478 |
+ gateway = net.ParseIP(requestedGateway) |
|
| 479 |
+ |
|
| 480 |
+ if gateway == nil {
|
|
| 481 |
+ return nil, fmt.Errorf("Bad parameter: invalid gateway ip %s", requestedGateway)
|
|
| 482 |
+ } |
|
| 483 |
+ |
|
| 484 |
+ if !network.Contains(gateway) {
|
|
| 485 |
+ return nil, fmt.Errorf("Gateway ip %s must be part of the network %s", requestedGateway, network.String())
|
|
| 486 |
+ } |
|
| 487 |
+ |
|
| 488 |
+ ipAllocator.RequestIP(network, gateway) |
|
| 489 |
+ } |
|
| 490 |
+ |
|
| 491 |
+ return gateway, nil |
|
| 492 |
+} |
|
| 493 |
+ |
|
| 476 | 494 |
func createBridgeIface(name string) error {
|
| 477 | 495 |
kv, err := kernel.GetKernelVersion() |
| 478 | 496 |
// Only set the bridge's mac address if the kernel version is > 3.3 |
| ... | ... |
@@ -522,10 +556,12 @@ func linkLocalIPv6FromMac(mac string) (string, error) {
|
| 522 | 522 |
// Allocate a network interface |
| 523 | 523 |
func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Settings, error) {
|
| 524 | 524 |
var ( |
| 525 |
- ip net.IP |
|
| 526 |
- mac net.HardwareAddr |
|
| 527 |
- err error |
|
| 528 |
- globalIPv6 net.IP |
|
| 525 |
+ ip net.IP |
|
| 526 |
+ mac net.HardwareAddr |
|
| 527 |
+ err error |
|
| 528 |
+ globalIPv6 net.IP |
|
| 529 |
+ defaultGWIPv4 net.IP |
|
| 530 |
+ defaultGWIPv6 net.IP |
|
| 529 | 531 |
) |
| 530 | 532 |
|
| 531 | 533 |
ip, err = ipAllocator.RequestIP(bridgeIPv4Network, net.ParseIP(requestedIP)) |
| ... | ... |
@@ -560,6 +596,18 @@ func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Set |
| 560 | 560 |
|
| 561 | 561 |
maskSize, _ := bridgeIPv4Network.Mask.Size() |
| 562 | 562 |
|
| 563 |
+ if gatewayIPv4 != nil {
|
|
| 564 |
+ defaultGWIPv4 = gatewayIPv4 |
|
| 565 |
+ } else {
|
|
| 566 |
+ defaultGWIPv4 = bridgeIPv4Network.IP |
|
| 567 |
+ } |
|
| 568 |
+ |
|
| 569 |
+ if gatewayIPv6 != nil {
|
|
| 570 |
+ defaultGWIPv6 = gatewayIPv6 |
|
| 571 |
+ } else {
|
|
| 572 |
+ defaultGWIPv6 = bridgeIPv6Addr |
|
| 573 |
+ } |
|
| 574 |
+ |
|
| 563 | 575 |
// If linklocal IPv6 |
| 564 | 576 |
localIPv6Net, err := linkLocalIPv6FromMac(mac.String()) |
| 565 | 577 |
if err != nil {
|
| ... | ... |
@@ -569,7 +617,7 @@ func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Set |
| 569 | 569 |
|
| 570 | 570 |
networkSettings := &network.Settings{
|
| 571 | 571 |
IPAddress: ip.String(), |
| 572 |
- Gateway: bridgeIPv4Network.IP.String(), |
|
| 572 |
+ Gateway: defaultGWIPv4.String(), |
|
| 573 | 573 |
MacAddress: mac.String(), |
| 574 | 574 |
Bridge: bridgeIface, |
| 575 | 575 |
IPPrefixLen: maskSize, |
| ... | ... |
@@ -580,7 +628,7 @@ func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Set |
| 580 | 580 |
networkSettings.GlobalIPv6Address = globalIPv6.String() |
| 581 | 581 |
maskV6Size, _ := globalIPv6Network.Mask.Size() |
| 582 | 582 |
networkSettings.GlobalIPv6PrefixLen = maskV6Size |
| 583 |
- networkSettings.IPv6Gateway = bridgeIPv6Addr.String() |
|
| 583 |
+ networkSettings.IPv6Gateway = defaultGWIPv6.String() |
|
| 584 | 584 |
} |
| 585 | 585 |
|
| 586 | 586 |
currentInterfaces.Set(id, &networkInterface{
|
| ... | ... |
@@ -41,6 +41,12 @@ To see the man page for a command run **man docker <command>**. |
| 41 | 41 |
**-d**, **--daemon**=*true*|*false* |
| 42 | 42 |
Enable daemon mode. Default is false. |
| 43 | 43 |
|
| 44 |
+**--default-gateway**="" |
|
| 45 |
+ IPv4 address of the container default gateway; this address must be part of the bridge subnet (which is defined by \-b or \--bip) |
|
| 46 |
+ |
|
| 47 |
+**--default-gateway-v6**="" |
|
| 48 |
+ IPv6 address of the container default gateway |
|
| 49 |
+ |
|
| 44 | 50 |
**--dns**="" |
| 45 | 51 |
Force Docker to use specific DNS servers |
| 46 | 52 |
|
| ... | ... |
@@ -56,6 +56,12 @@ server when it starts up, and cannot be changed once it is running: |
| 56 | 56 |
* `--bip=CIDR` — see |
| 57 | 57 |
[Customizing docker0](#docker0) |
| 58 | 58 |
|
| 59 |
+ * `--default-gateway=IP_ADDRESS` — see |
|
| 60 |
+ [How Docker networks a container](#container-networking) |
|
| 61 |
+ |
|
| 62 |
+ * `--default-gateway-v6=IP_ADDRESS` — see |
|
| 63 |
+ [IPv6](#ipv6) |
|
| 64 |
+ |
|
| 59 | 65 |
* `--fixed-cidr` — see |
| 60 | 66 |
[Customizing docker0](#docker0) |
| 61 | 67 |
|
| ... | ... |
@@ -499,7 +505,9 @@ want to configure `eth0` via Router Advertisements you should set: |
| 499 | 499 |
 |
| 500 | 500 |
|
| 501 | 501 |
Every new container will get an IPv6 address from the defined subnet. Further |
| 502 |
-a default route will be added via the gateway `fe80::1` on `eth0`: |
|
| 502 |
+a default route will be added on `eth0` in the container via the address |
|
| 503 |
+specified by the daemon option `--default-gateway-v6` if present, otherwise |
|
| 504 |
+via `fe80::1`: |
|
| 503 | 505 |
|
| 504 | 506 |
docker run -it ubuntu bash -c "ip -6 addr show dev eth0; ip -6 route show" |
| 505 | 507 |
|
| ... | ... |
@@ -865,12 +873,13 @@ The steps with which Docker configures a container are: |
| 865 | 865 |
parameter or generate a random one. |
| 866 | 866 |
|
| 867 | 867 |
5. Give the container's `eth0` a new IP address from within the |
| 868 |
- bridge's range of network addresses, and set its default route to |
|
| 869 |
- the IP address that the Docker host owns on the bridge. The MAC |
|
| 870 |
- address is generated from the IP address unless otherwise specified. |
|
| 871 |
- This prevents ARP cache invalidation problems, when a new container |
|
| 872 |
- comes up with an IP used in the past by another container with another |
|
| 873 |
- MAC. |
|
| 868 |
+ bridge's range of network addresses. The default route is set to the |
|
| 869 |
+ IP address passed to the Docker daemon using the `--default-gateway` |
|
| 870 |
+ option if specified, otherwise to the IP address that the Docker host |
|
| 871 |
+ owns on the bridge. The MAC address is generated from the IP address |
|
| 872 |
+ unless otherwise specified. This prevents ARP cache invalidation |
|
| 873 |
+ problems, when a new container comes up with an IP used in the past by |
|
| 874 |
+ another container with another MAC. |
|
| 874 | 875 |
|
| 875 | 876 |
With these steps complete, the container now possesses an `eth0` |
| 876 | 877 |
(virtual) network card and will find itself able to communicate with |
| ... | ... |
@@ -116,6 +116,8 @@ expect an integer, and they can only be specified once. |
| 116 | 116 |
--bip="" Specify network bridge IP |
| 117 | 117 |
-D, --debug=false Enable debug mode |
| 118 | 118 |
-d, --daemon=false Enable daemon mode |
| 119 |
+ --default-gateway="" Container default gateway IPv4 address |
|
| 120 |
+ --default-gateway-v6="" Container default gateway IPv6 address |
|
| 119 | 121 |
--dns=[] DNS server to use |
| 120 | 122 |
--dns-search=[] DNS search domains to use |
| 121 | 123 |
-e, --exec-driver="native" Exec driver to use |