From 42dd48315fcf6a3a536e0e698396e404246b9f3f Mon Sep 17 00:00:00 2001 From: Alexandr Morozov Date: Wed, 28 May 2014 22:10:09 +0400 Subject: [PATCH 1/3] More ipallocator refactoring Now x1.5 faster Signed-off-by: Alexandr Morozov --- daemon/networkdriver/bridge/driver.go | 8 +- daemon/networkdriver/ipallocator/allocator.go | 81 ++++++++----------- .../ipallocator/allocator_test.go | 40 ++++----- 3 files changed, 58 insertions(+), 71 deletions(-) diff --git a/daemon/networkdriver/bridge/driver.go b/daemon/networkdriver/bridge/driver.go index 06cf37e79f..c4b10fe07f 100644 --- a/daemon/networkdriver/bridge/driver.go +++ b/daemon/networkdriver/bridge/driver.go @@ -317,14 +317,14 @@ func createBridgeIface(name string) error { // Allocate a network interface func Allocate(job *engine.Job) engine.Status { var ( - ip *net.IP + ip net.IP err error id = job.Args[0] requestedIP = net.ParseIP(job.Getenv("RequestedIP")) ) if requestedIP != nil { - ip, err = ipallocator.RequestIP(bridgeNetwork, &requestedIP) + ip, err = ipallocator.RequestIP(bridgeNetwork, requestedIP) } else { ip, err = ipallocator.RequestIP(bridgeNetwork, nil) } @@ -342,7 +342,7 @@ func Allocate(job *engine.Job) engine.Status { out.SetInt("IPPrefixLen", size) currentInterfaces.Set(id, &networkInterface{ - IP: *ip, + IP: ip, }) out.WriteTo(job.Stdout) @@ -367,7 +367,7 @@ func Release(job *engine.Job) engine.Status { } } - if err := ipallocator.ReleaseIP(bridgeNetwork, &containerInterface.IP); err != nil { + if err := ipallocator.ReleaseIP(bridgeNetwork, containerInterface.IP); err != nil { log.Infof("Unable to release ip %s", err) } return engine.StatusOK diff --git a/daemon/networkdriver/ipallocator/allocator.go b/daemon/networkdriver/ipallocator/allocator.go index 1bf8e1da9b..7abb3ffdf4 100644 --- a/daemon/networkdriver/ipallocator/allocator.go +++ b/daemon/networkdriver/ipallocator/allocator.go @@ -3,19 +3,30 @@ package ipallocator import ( "encoding/binary" "errors" - "github.com/docker/docker/daemon/networkdriver" "net" "sync" + + "github.com/dotcloud/docker/daemon/networkdriver" ) // allocatedMap is thread-unsafe set of allocated IP type allocatedMap struct { - p map[int32]struct{} - last int32 + p map[uint32]struct{} + last uint32 + begin uint32 + end uint32 } -func newAllocatedMap() *allocatedMap { - return &allocatedMap{p: make(map[int32]struct{})} +func newAllocatedMap(network *net.IPNet) *allocatedMap { + firstIP, lastIP := networkdriver.NetworkRange(network) + begin := ipToInt(firstIP) + 2 + end := ipToInt(lastIP) - 1 + return &allocatedMap{ + p: make(map[uint32]struct{}), + begin: begin, // - network + end: end, // - broadcast + last: begin - 1, // so first allocated will be begin + } } type networkSet map[string]*allocatedMap @@ -34,43 +45,36 @@ var ( // will return the next available ip if the ip provided is nil. If the // ip provided is not nil it will validate that the provided ip is available // for use or return an error -func RequestIP(network *net.IPNet, ip *net.IP) (*net.IP, error) { +func RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) { lock.Lock() defer lock.Unlock() key := network.String() allocated, ok := allocatedIPs[key] if !ok { - allocated = newAllocatedMap() + allocated = newAllocatedMap(network) allocatedIPs[key] = allocated } if ip == nil { - return allocated.getNextIP(network) + return allocated.getNextIP() } - return allocated.checkIP(network, ip) + return allocated.checkIP(ip) } // ReleaseIP adds the provided ip back into the pool of // available ips to be returned for use. -func ReleaseIP(network *net.IPNet, ip *net.IP) error { +func ReleaseIP(network *net.IPNet, ip net.IP) error { lock.Lock() defer lock.Unlock() if allocated, exists := allocatedIPs[network.String()]; exists { - pos := getPosition(network, ip) + pos := ipToInt(ip) delete(allocated.p, pos) } return nil } -// convert the ip into the position in the subnet. Only -// position are saved in the set -func getPosition(network *net.IPNet, ip *net.IP) int32 { - first, _ := networkdriver.NetworkRange(network) - return ipToInt(ip) - ipToInt(&first) -} - -func (allocated *allocatedMap) checkIP(network *net.IPNet, ip *net.IP) (*net.IP, error) { - pos := getPosition(network, ip) +func (allocated *allocatedMap) checkIP(ip net.IP) (net.IP, error) { + pos := ipToInt(ip) if _, ok := allocated.p[pos]; ok { return nil, ErrIPAlreadyAllocated } @@ -81,47 +85,30 @@ func (allocated *allocatedMap) checkIP(network *net.IPNet, ip *net.IP) (*net.IP, // return an available ip if one is currently available. If not, // return the next available ip for the nextwork -func (allocated *allocatedMap) getNextIP(network *net.IPNet) (*net.IP, error) { - var ( - ownIP = ipToInt(&network.IP) - first, _ = networkdriver.NetworkRange(network) - base = ipToInt(&first) - size = int(networkdriver.NetworkSize(network.Mask)) - max = int32(size - 2) // size -1 for the broadcast network, -1 for the gateway network - pos = allocated.last - ) - - var ( - firstNetIP = network.IP.To4().Mask(network.Mask) - firstAsInt = ipToInt(&firstNetIP) + 1 - ) - - for i := int32(0); i < max; i++ { - pos = pos%max + 1 - next := int32(base + pos) - - if next == ownIP || next == firstAsInt { - continue +func (allocated *allocatedMap) getNextIP() (net.IP, error) { + for pos := allocated.last + 1; pos != allocated.last; pos++ { + if pos > allocated.end { + pos = allocated.begin } if _, ok := allocated.p[pos]; ok { continue } allocated.p[pos] = struct{}{} allocated.last = pos - return intToIP(next), nil + return intToIP(pos), nil } return nil, ErrNoAvailableIPs } // Converts a 4 bytes IP into a 32 bit integer -func ipToInt(ip *net.IP) int32 { - return int32(binary.BigEndian.Uint32(ip.To4())) +func ipToInt(ip net.IP) uint32 { + return binary.BigEndian.Uint32(ip.To4()) } // Converts 32 bit integer into a 4 bytes IP address -func intToIP(n int32) *net.IP { +func intToIP(n uint32) net.IP { b := make([]byte, 4) - binary.BigEndian.PutUint32(b, uint32(n)) + binary.BigEndian.PutUint32(b, n) ip := net.IP(b) - return &ip + return ip } diff --git a/daemon/networkdriver/ipallocator/allocator_test.go b/daemon/networkdriver/ipallocator/allocator_test.go index 6897a0a44b..57575bc7bd 100644 --- a/daemon/networkdriver/ipallocator/allocator_test.go +++ b/daemon/networkdriver/ipallocator/allocator_test.go @@ -17,7 +17,7 @@ func TestRequestNewIps(t *testing.T) { Mask: []byte{255, 255, 255, 0}, } - var ip *net.IP + var ip net.IP var err error for i := 2; i < 10; i++ { ip, err = RequestIP(network, nil) @@ -106,19 +106,19 @@ func TestRequesetSpecificIp(t *testing.T) { ip := net.ParseIP("192.168.1.5") - if _, err := RequestIP(network, &ip); err != nil { + if _, err := RequestIP(network, ip); err != nil { t.Fatal(err) } } func TestConversion(t *testing.T) { ip := net.ParseIP("127.0.0.1") - i := ipToInt(&ip) + i := ipToInt(ip) if i == 0 { t.Fatal("converted to zero") } conv := intToIP(i) - if !ip.Equal(*conv) { + if !ip.Equal(conv) { t.Error(conv.String()) } } @@ -146,7 +146,7 @@ func TestIPAllocator(t *testing.T) { t.Fatal(err) } - assertIPEquals(t, &expectedIPs[i], ip) + assertIPEquals(t, expectedIPs[i], ip) } // Before loop begin // 2(f) - 3(f) - 4(f) - 5(f) - 6(f) @@ -179,19 +179,19 @@ func TestIPAllocator(t *testing.T) { } // Release some IPs in non-sequential order - if err := ReleaseIP(network, &expectedIPs[3]); err != nil { + if err := ReleaseIP(network, expectedIPs[3]); err != nil { t.Fatal(err) } // 2(u) - 3(u) - 4(u) - 5(f) - 6(u) // ↑ - if err := ReleaseIP(network, &expectedIPs[2]); err != nil { + if err := ReleaseIP(network, expectedIPs[2]); err != nil { t.Fatal(err) } // 2(u) - 3(u) - 4(f) - 5(f) - 6(u) // ↑ - if err := ReleaseIP(network, &expectedIPs[4]); err != nil { + if err := ReleaseIP(network, expectedIPs[4]); err != nil { t.Fatal(err) } // 2(u) - 3(u) - 4(f) - 5(f) - 6(f) @@ -199,7 +199,7 @@ func TestIPAllocator(t *testing.T) { // Make sure that IPs are reused in sequential order, starting // with the first released IP - newIPs := make([]*net.IP, 3) + newIPs := make([]net.IP, 3) for i := 0; i < 3; i++ { ip, err := RequestIP(network, nil) if err != nil { @@ -208,9 +208,9 @@ func TestIPAllocator(t *testing.T) { newIPs[i] = ip } - assertIPEquals(t, &expectedIPs[2], newIPs[0]) - assertIPEquals(t, &expectedIPs[3], newIPs[1]) - assertIPEquals(t, &expectedIPs[4], newIPs[2]) + assertIPEquals(t, expectedIPs[2], newIPs[0]) + assertIPEquals(t, expectedIPs[3], newIPs[1]) + assertIPEquals(t, expectedIPs[4], newIPs[2]) _, err = RequestIP(network, nil) if err == nil { @@ -226,7 +226,7 @@ func TestAllocateFirstIP(t *testing.T) { } firstIP := network.IP.To4().Mask(network.Mask) - first := ipToInt(&firstIP) + 1 + first := ipToInt(firstIP) + 1 ip, err := RequestIP(network, nil) if err != nil { @@ -247,7 +247,7 @@ func TestAllocateAllIps(t *testing.T) { } var ( - current, first *net.IP + current, first net.IP err error isFirst = true ) @@ -313,14 +313,14 @@ func TestAllocateDifferentSubnets(t *testing.T) { if err != nil { t.Fatal(err) } - assertIPEquals(t, &expectedIPs[0], ip11) - assertIPEquals(t, &expectedIPs[1], ip12) - assertIPEquals(t, &expectedIPs[2], ip21) - assertIPEquals(t, &expectedIPs[3], ip22) + assertIPEquals(t, expectedIPs[0], ip11) + assertIPEquals(t, expectedIPs[1], ip12) + assertIPEquals(t, expectedIPs[2], ip21) + assertIPEquals(t, expectedIPs[3], ip22) } -func assertIPEquals(t *testing.T, ip1, ip2 *net.IP) { - if !ip1.Equal(*ip2) { +func assertIPEquals(t *testing.T, ip1, ip2 net.IP) { + if !ip1.Equal(ip2) { t.Fatalf("Expected IP %s, got %s", ip1, ip2) } } From b101022dbe6daa36ebf11df53ad01a399a655963 Mon Sep 17 00:00:00 2001 From: Alexandr Morozov Date: Thu, 29 May 2014 00:06:23 +0400 Subject: [PATCH 2/3] Implement allocating IPs from CIDR within bridge network Fixes #4986 Signed-off-by: Alexandr Morozov --- daemon/config.go | 2 + daemon/daemon.go | 1 + daemon/networkdriver/bridge/driver.go | 11 +++ daemon/networkdriver/ipallocator/allocator.go | 35 ++++++-- .../ipallocator/allocator_test.go | 80 +++++++++++++++++++ docs/sources/reference/commandline/cli.md | 1 + 6 files changed, 125 insertions(+), 5 deletions(-) diff --git a/daemon/config.go b/daemon/config.go index 1ca8086933..20d839efa4 100644 --- a/daemon/config.go +++ b/daemon/config.go @@ -28,6 +28,7 @@ type Config struct { DefaultIp net.IP BridgeIface string BridgeIP string + FixedCIDR string InterContainerCommunication bool GraphDriver string GraphOptions []string @@ -50,6 +51,7 @@ func (config *Config) InstallFlags() { flag.BoolVar(&config.EnableIpForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward") flag.StringVar(&config.BridgeIP, []string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b") flag.StringVar(&config.BridgeIface, []string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge\nuse 'none' to disable container networking") + flag.StringVar(&config.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)\nthis subnet must be nested in bridge subnet (which is defined by -b or --bip)") flag.BoolVar(&config.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication") flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Force the Docker runtime to use a specific storage driver") flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Force the Docker runtime to use a specific exec driver") diff --git a/daemon/daemon.go b/daemon/daemon.go index 0a4d6e0bc5..8bf92be15b 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -803,6 +803,7 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine) (*Daemon, error) job.SetenvBool("EnableIpForward", config.EnableIpForward) job.Setenv("BridgeIface", config.BridgeIface) job.Setenv("BridgeIP", config.BridgeIP) + job.Setenv("FixedCIDR", config.FixedCIDR) job.Setenv("DefaultBindingIP", config.DefaultIp.String()) if err := job.Run(); err != nil { diff --git a/daemon/networkdriver/bridge/driver.go b/daemon/networkdriver/bridge/driver.go index c4b10fe07f..0ffad75fc1 100644 --- a/daemon/networkdriver/bridge/driver.go +++ b/daemon/networkdriver/bridge/driver.go @@ -83,6 +83,7 @@ func InitDriver(job *engine.Job) engine.Status { icc = job.GetenvBool("InterContainerCommunication") ipForward = job.GetenvBool("EnableIpForward") bridgeIP = job.Getenv("BridgeIP") + fixedCIDR = job.Getenv("FixedCIDR") ) if defaultIP := job.Getenv("DefaultBindingIP"); defaultIP != "" { @@ -157,6 +158,16 @@ func InitDriver(job *engine.Job) engine.Status { } bridgeNetwork = network + if fixedCIDR != "" { + _, subnet, err := net.ParseCIDR(fixedCIDR) + if err != nil { + return job.Error(err) + } + log.Debugf("Subnet: %v", subnet) + if err := ipallocator.RegisterSubnet(bridgeNetwork, subnet); err != nil { + return job.Error(err) + } + } // https://github.com/docker/docker/issues/2768 job.Eng.Hack_SetGlobalVar("httpapi.bridgeIP", bridgeNetwork.IP) diff --git a/daemon/networkdriver/ipallocator/allocator.go b/daemon/networkdriver/ipallocator/allocator.go index 7abb3ffdf4..ad7547a4a0 100644 --- a/daemon/networkdriver/ipallocator/allocator.go +++ b/daemon/networkdriver/ipallocator/allocator.go @@ -6,7 +6,7 @@ import ( "net" "sync" - "github.com/dotcloud/docker/daemon/networkdriver" + "github.com/docker/docker/daemon/networkdriver" ) // allocatedMap is thread-unsafe set of allocated IP @@ -23,8 +23,8 @@ func newAllocatedMap(network *net.IPNet) *allocatedMap { end := ipToInt(lastIP) - 1 return &allocatedMap{ p: make(map[uint32]struct{}), - begin: begin, // - network - end: end, // - broadcast + begin: begin, + end: end, last: begin - 1, // so first allocated will be begin } } @@ -32,8 +32,10 @@ func newAllocatedMap(network *net.IPNet) *allocatedMap { type networkSet map[string]*allocatedMap var ( - ErrNoAvailableIPs = errors.New("no available ip addresses on network") - ErrIPAlreadyAllocated = errors.New("ip already allocated") + ErrNoAvailableIPs = errors.New("no available ip addresses on network") + ErrIPAlreadyAllocated = errors.New("ip already allocated") + ErrNetworkAlreadyRegistered = errors.New("network already registered") + ErrBadSubnet = errors.New("network not contains specified subnet") ) var ( @@ -41,6 +43,29 @@ var ( allocatedIPs = networkSet{} ) +// RegisterSubnet registers network in global allocator with bounds +// defined by subnet. If you want to use network range you must call +// this method before first RequestIP, otherwise full network range will be used +func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error { + lock.Lock() + defer lock.Unlock() + key := network.String() + if _, ok := allocatedIPs[key]; ok { + return ErrNetworkAlreadyRegistered + } + n := newAllocatedMap(network) + beginIP, endIP := networkdriver.NetworkRange(subnet) + begin, end := ipToInt(beginIP)+1, ipToInt(endIP)-1 + if !(begin >= n.begin && end <= n.end && begin < end) { + return ErrBadSubnet + } + n.begin = begin + n.end = end + n.last = begin - 1 + allocatedIPs[key] = n + return nil +} + // RequestIP requests an available ip from the given network. It // will return the next available ip if the ip provided is nil. If the // ip provided is not nil it will validate that the provided ip is available diff --git a/daemon/networkdriver/ipallocator/allocator_test.go b/daemon/networkdriver/ipallocator/allocator_test.go index 57575bc7bd..0b5d97e605 100644 --- a/daemon/networkdriver/ipallocator/allocator_test.go +++ b/daemon/networkdriver/ipallocator/allocator_test.go @@ -318,6 +318,86 @@ func TestAllocateDifferentSubnets(t *testing.T) { assertIPEquals(t, expectedIPs[2], ip21) assertIPEquals(t, expectedIPs[3], ip22) } +func TestRegisterBadTwice(t *testing.T) { + defer reset() + network := &net.IPNet{ + IP: []byte{192, 168, 1, 1}, + Mask: []byte{255, 255, 255, 0}, + } + subnet := &net.IPNet{ + IP: []byte{192, 168, 1, 8}, + Mask: []byte{255, 255, 255, 248}, + } + + if err := RegisterSubnet(network, subnet); err != nil { + t.Fatal(err) + } + subnet = &net.IPNet{ + IP: []byte{192, 168, 1, 16}, + Mask: []byte{255, 255, 255, 248}, + } + if err := RegisterSubnet(network, subnet); err != ErrNetworkAlreadyRegistered { + t.Fatalf("Expecteded ErrNetworkAlreadyRegistered error, got %v", err) + } +} + +func TestRegisterBadRange(t *testing.T) { + defer reset() + network := &net.IPNet{ + IP: []byte{192, 168, 1, 1}, + Mask: []byte{255, 255, 255, 0}, + } + subnet := &net.IPNet{ + IP: []byte{192, 168, 1, 1}, + Mask: []byte{255, 255, 0, 0}, + } + if err := RegisterSubnet(network, subnet); err != ErrBadSubnet { + t.Fatalf("Expected ErrBadSubnet error, got %v", err) + } +} + +func TestAllocateFromRange(t *testing.T) { + defer reset() + network := &net.IPNet{ + IP: []byte{192, 168, 0, 1}, + Mask: []byte{255, 255, 255, 0}, + } + // 192.168.1.9 - 192.168.1.14 + subnet := &net.IPNet{ + IP: []byte{192, 168, 0, 8}, + Mask: []byte{255, 255, 255, 248}, + } + if err := RegisterSubnet(network, subnet); err != nil { + t.Fatal(err) + } + expectedIPs := []net.IP{ + 0: net.IPv4(192, 168, 0, 9), + 1: net.IPv4(192, 168, 0, 10), + 2: net.IPv4(192, 168, 0, 11), + 3: net.IPv4(192, 168, 0, 12), + 4: net.IPv4(192, 168, 0, 13), + 5: net.IPv4(192, 168, 0, 14), + } + for _, ip := range expectedIPs { + rip, err := RequestIP(network, nil) + if err != nil { + t.Fatal(err) + } + assertIPEquals(t, ip, rip) + } + + if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs { + t.Fatalf("Expected ErrNoAvailableIPs error, got %v", err) + } + for _, ip := range expectedIPs { + ReleaseIP(network, ip) + rip, err := RequestIP(network, nil) + if err != nil { + t.Fatal(err) + } + assertIPEquals(t, ip, rip) + } +} func assertIPEquals(t *testing.T, ip1, ip2 net.IP) { if !ip1.Equal(ip2) { diff --git a/docs/sources/reference/commandline/cli.md b/docs/sources/reference/commandline/cli.md index ef30113882..3d117fe3c9 100644 --- a/docs/sources/reference/commandline/cli.md +++ b/docs/sources/reference/commandline/cli.md @@ -54,6 +54,7 @@ expect an integer, and they can only be specified once. -b, --bridge="" Attach containers to a pre-existing network bridge use 'none' to disable container networking --bip="" Use this CIDR notation address for the network bridge's IP, not compatible with -b + --fixed-cidr="" IPv4 subnet for fixed IPs (ex: 10.20.0.0/16) -D, --debug=false Enable debug mode -d, --daemon=false Enable daemon mode --dns=[] Force Docker to use specific DNS servers From 3bb12d390a8a965e4dc680db7ecdab8c76f23990 Mon Sep 17 00:00:00 2001 From: "Frederick F. Kautz IV" Date: Mon, 21 Jul 2014 15:30:21 -0400 Subject: [PATCH 3/3] Adding additional documentation for fixed-cidr networking Docker-DCO-1.1-Signed-off-by: Frederick F. Kautz IV (github: fkautz) Signed-off-by: Alexandr Morozov --- daemon/config.go | 2 +- docs/man/docker.1.md | 4 ++++ docs/sources/articles/networking.md | 23 +++++++++++++++++------ docs/sources/reference/commandline/cli.md | 1 + 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/daemon/config.go b/daemon/config.go index 20d839efa4..f01c985036 100644 --- a/daemon/config.go +++ b/daemon/config.go @@ -51,7 +51,7 @@ func (config *Config) InstallFlags() { flag.BoolVar(&config.EnableIpForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward") flag.StringVar(&config.BridgeIP, []string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b") flag.StringVar(&config.BridgeIface, []string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge\nuse 'none' to disable container networking") - flag.StringVar(&config.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)\nthis subnet must be nested in bridge subnet (which is defined by -b or --bip)") + flag.StringVar(&config.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)\nthis subnet must be nested in the bridge subnet (which is defined by -b or --bip)") flag.BoolVar(&config.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication") flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Force the Docker runtime to use a specific storage driver") flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Force the Docker runtime to use a specific exec driver") diff --git a/docs/man/docker.1.md b/docs/man/docker.1.md index 3932097255..00b5fb6d97 100644 --- a/docs/man/docker.1.md +++ b/docs/man/docker.1.md @@ -49,6 +49,10 @@ unix://[/path/to/socket] to use. **-g**="" Path to use as the root of the Docker runtime. Default is `/var/lib/docker`. + +**--fixed-cidr**="" + IPv4 subnet for fixed IPs (ex: 10.20.0.0/16); this subnet must be nested in the bridge subnet (which is defined by \-b or \-\-bip) + **--icc**=*true*|*false* Enable inter\-container communication. Default is true. diff --git a/docs/sources/articles/networking.md b/docs/sources/articles/networking.md index d61ebd65ba..ad08b2b8be 100644 --- a/docs/sources/articles/networking.md +++ b/docs/sources/articles/networking.md @@ -54,6 +54,9 @@ server when it starts up, and cannot be changed once it is running: * `--bip=CIDR` — see [Customizing docker0](#docker0) + * `--fixed-cidr` — see + [Customizing docker0](#docker0) + * `-H SOCKET...` or `--host=SOCKET...` — This might sound like it would affect container networking, but it actually faces in the other direction: @@ -365,17 +368,25 @@ By default, the Docker server creates and configures the host system's can pass packets back and forth between other physical or virtual network interfaces so that they behave as a single Ethernet network. -Docker configures `docker0` with an IP address and netmask so the host -machine can both receive and send packets to containers connected to the -bridge, and gives it an MTU — the *maximum transmission unit* or largest -packet length that the interface will allow — of either 1,500 bytes or -else a more specific value copied from the Docker host's interface that -supports its default route. Both are configurable at server startup: +Docker configures `docker0` with an IP address, netmask and IP +allocation range. The host machine can both receive and send packets to +containers connected to the bridge, and gives it an MTU — the *maximum +transmission unit* or largest packet length that the interface will +allow — of either 1,500 bytes or else a more specific value copied from +the Docker host's interface that supports its default route. These +options are configurable at server startup: * `--bip=CIDR` — supply a specific IP address and netmask for the `docker0` bridge, using standard CIDR notation like `192.168.1.5/24`. + * `--fixed-cidr=CIDR` — restrict the IP range from the `docker0` subnet, + using the standard CIDR notation like `172.167.1.0/28`. This range must + be and IPv4 range for fixed IPs (ex: 10.20.0.0/16) and must be a subset + of the bridge IP range (`docker0` or set using `--bridge`). For example + with `--fixed-cidr=192.168.1.0/25`, IPs for your containers will be chosen + from the first half of `192.168.1.0/24` subnet. + * `--mtu=BYTES` — override the maximum packet length on `docker0`. On Ubuntu you would add these to the `DOCKER_OPTS` setting in diff --git a/docs/sources/reference/commandline/cli.md b/docs/sources/reference/commandline/cli.md index 3d117fe3c9..11373b98e0 100644 --- a/docs/sources/reference/commandline/cli.md +++ b/docs/sources/reference/commandline/cli.md @@ -55,6 +55,7 @@ expect an integer, and they can only be specified once. use 'none' to disable container networking --bip="" Use this CIDR notation address for the network bridge's IP, not compatible with -b --fixed-cidr="" IPv4 subnet for fixed IPs (ex: 10.20.0.0/16) + this subnet must be nested in the bridge subnet (which is defined by -b or --bip) -D, --debug=false Enable debug mode -d, --daemon=false Enable daemon mode --dns=[] Force Docker to use specific DNS servers