Merge pull request #1083 from docker/1042-ip-networking-config

Support ipv4_address and ipv6_address in create_endpoint_config
This commit is contained in:
Joffrey F 2016-06-13 18:02:58 -07:00 committed by GitHub
commit 080b4711f2
5 changed files with 237 additions and 31 deletions

View File

@ -1,7 +1,7 @@
import json import json
from ..errors import InvalidVersion from ..errors import InvalidVersion
from ..utils import check_resource, minimum_version, normalize_links from ..utils import check_resource, minimum_version
from ..utils import version_lt from ..utils import version_lt
@ -63,26 +63,12 @@ class NetworkApiMixin(object):
aliases=None, links=None): aliases=None, links=None):
data = { data = {
"Container": container, "Container": container,
"EndpointConfig": { "EndpointConfig": self.create_endpoint_config(
"Aliases": aliases, aliases=aliases, links=links, ipv4_address=ipv4_address,
"Links": normalize_links(links) if links else None, ipv6_address=ipv6_address
}, ),
} }
# IPv4 or IPv6 or neither:
if ipv4_address or ipv6_address:
if version_lt(self._version, '1.22'):
raise InvalidVersion('IP address assignment is not '
'supported in API version < 1.22')
data['EndpointConfig']['IPAMConfig'] = dict()
if ipv4_address:
data['EndpointConfig']['IPAMConfig']['IPv4Address'] = \
ipv4_address
if ipv6_address:
data['EndpointConfig']['IPAMConfig']['IPv6Address'] = \
ipv6_address
url = self._url("/networks/{0}/connect", net_id) url = self._url("/networks/{0}/connect", net_id)
res = self._post_json(url, data=data) res = self._post_json(url, data=data)
self._raise_for_status(res) self._raise_for_status(res)

View File

@ -813,19 +813,30 @@ def create_networking_config(endpoints_config=None):
return networking_config return networking_config
def create_endpoint_config(version, aliases=None, links=None): def create_endpoint_config(version, aliases=None, links=None,
ipv4_address=None, ipv6_address=None):
if version_lt(version, '1.22'):
raise errors.InvalidVersion(
'Endpoint config is not supported for API version < 1.22'
)
endpoint_config = {} endpoint_config = {}
if aliases: if aliases:
if version_lt(version, '1.22'):
raise host_config_version_error('endpoint_config.aliases', '1.22')
endpoint_config["Aliases"] = aliases endpoint_config["Aliases"] = aliases
if links: if links:
if version_lt(version, '1.22'):
raise host_config_version_error('endpoint_config.links', '1.22')
endpoint_config["Links"] = normalize_links(links) endpoint_config["Links"] = normalize_links(links)
ipam_config = {}
if ipv4_address:
ipam_config['IPv4Address'] = ipv4_address
if ipv6_address:
ipam_config['IPv6Address'] = ipv6_address
if ipam_config:
endpoint_config['IPAMConfig'] = ipam_config
return endpoint_config return endpoint_config

View File

@ -242,6 +242,7 @@ from. Optionally a single string joining container id's with commas
* labels (dict or list): A dictionary of name-value labels (e.g. `{"label1": "value1", "label2": "value2"}`) or a list of names of labels to set with empty values (e.g. `["label1", "label2"]`) * labels (dict or list): A dictionary of name-value labels (e.g. `{"label1": "value1", "label2": "value2"}`) or a list of names of labels to set with empty values (e.g. `["label1", "label2"]`)
* volume_driver (str): The name of a volume driver/plugin. * volume_driver (str): The name of a volume driver/plugin.
* stop_signal (str): The stop signal to use to stop the container (e.g. `SIGINT`). * stop_signal (str): The stop signal to use to stop the container (e.g. `SIGINT`).
* networking_config (dict): A [NetworkingConfig](networks.md) dictionary
**Returns** (dict): A dictionary with an image 'Id' key and a 'Warnings' key. **Returns** (dict): A dictionary with an image 'Id' key and a 'Warnings' key.

View File

@ -1,27 +1,176 @@
# Using Networks # Using Networks
## Network creation
With the release of Docker 1.9 you can now manage custom networks. With the release of Docker 1.9 you can now manage custom networks.
Here you can see how to create a network named ```network1``` using the ```bridge``` driver Here you can see how to create a network named `network1` using
the `bridge` driver
```python ```python
docker_client.create_network("network1", driver="bridge") docker_client.create_network("network1", driver="bridge")
``` ```
You can also create more advanced networks with custom IPAM configurations. For example, You can also create more advanced networks with custom IPAM configurations.
setting the subnet to ```192.168.52.0/24``` and gateway to ```192.168.52.254``` For example, setting the subnet to `192.168.52.0/24` and gateway address
to `192.168.52.254`
```python ```python
ipam_pool = docker.utils.create_ipam_pool(
ipam_config = docker.utils.create_ipam_config(subnet='192.168.52.0/24', gateway='192.168.52.254') subnet='192.168.52.0/24',
gateway='192.168.52.254'
)
ipam_config = docker.utils.create_ipam_config(
pool_configs=[ipam_pool]
)
docker_client.create_network("network1", driver="bridge", ipam=ipam_config) docker_client.create_network("network1", driver="bridge", ipam=ipam_config)
``` ```
With Docker 1.10 you can now also create internal networks By default, when you connect a container to an overlay network, Docker also
connects a bridge network to it to provide external connectivity. If you want
to create an externally isolated overlay network, with Docker 1.10 you can
create an internal network.
```python ```python
docker_client.create_network("network1", driver="bridge", internal=True) docker_client.create_network("network1", driver="bridge", internal=True)
``` ```
## Container network configuration
In order to specify which network a container will be connected to, and
additional configuration, use the `networking_config` parameter in
`Client.create_container`. Note that at the time of creation, you can
only connect a container to a single network. Later on, you may create more
connections using `Client.connect_container_to_network`.
```python
networking_config = docker_client.create_networking_config({
'network1': docker_client.create_endpoint_config(
ipv4_address='172.28.0.124',
aliases=['foo', 'bar'],
links=['container2']
)
})
ctnr = docker_client.create_container(
img, command, networking_config=networking_config
)
```
## Network API documentation
### Client.create_networking_config
Create a networking config dictionary to be used as the `networking_config`
parameter in `Client.create_container_config`
**Params**:
* endpoints_config (dict): A dictionary of `network_name -> endpoint_config`
relationships. Values should be endpoint config dictionaries created by
`Client.create_endpoint_config`. Defaults to `None` (default config).
**Returns** A networking config dictionary.
```python
docker_client.create_network('network1')
networking_config = docker_client.create_networking_config({
'network1': docker_client.create_endpoint_config()
})
container = docker_client.create_container(
img, command, networking_config=networking_config
)
```
### Client.create_endpoint_config
Create an endpoint config dictionary to be used with
`Client.create_networking_config`.
**Params**:
* aliases (list): A list of aliases for this endpoint. Names in that list can
be used within the network to reach the container. Defaults to `None`.
* links (list): A list of links for this endpoint. Containers declared in this
list will be [linked](https://docs.docker.com/engine/userguide/networking/work-with-networks/#linking-containers-in-user-defined-networks)
to this container. Defaults to `None`.
* ipv4_address (str): The IP address of this container on the network,
using the IPv4 protocol. Defaults to `None`.
* ipv6_address (str): The IP address of this container on the network,
using the IPv6 protocol. Defaults to `None`.
**Returns** An endpoint config dictionary.
```python
endpoint_config = docker_client.create_endpoint_config(
aliases=['web', 'app'],
links=['app_db'],
ipv4_address='132.65.0.123'
)
docker_client.create_network('network1')
networking_config = docker_client.create_networking_config({
'network1': endpoint_config
})
container = docker_client.create_container(
img, command, networking_config=networking_config
)
```
### docker.utils.create_ipam_config
Create an IPAM (IP Address Management) config dictionary to be used with
`Client.create_network`.
**Params**:
* driver (str): The IPAM driver to use. Defaults to `'default'`.
* pool_configs (list): A list of pool configuration dictionaries as created
by `docker.utils.create_ipam_pool`. Defaults to empty list.
**Returns** An IPAM config dictionary
```python
ipam_config = docker.utils.create_ipam_config(driver='default')
network = docker_client.create_network('network1', ipam=ipam_config)
```
### docker.utils.create_ipam_pool
Create an IPAM pool config dictionary to be added to the `pool_configs` param
in `docker.utils.create_ipam_config`.
**Params**:
* subnet (str): Custom subnet for this IPAM pool using the CIDR notation.
Defaults to `None`.
* iprange (str): Custom IP range for endpoints in this IPAM pool using the
CIDR notation. Defaults to `None`.
* gateway (str): Custom IP address for the pool's gateway.
* aux_addresses (dict): A dictionary of `key -> ip_address` relationships
specifying auxiliary addresses that need to be allocated by the
IPAM driver.
**Returns** An IPAM pool config dictionary
```python
ipam_pool = docker.utils.create_ipam_pool(
subnet='124.42.0.0/16',
iprange='124.42.0.0/24',
gateway='124.42.0.254',
aux_addresses={
'reserved1': '124.42.1.1'
}
)
ipam_config = docker.utils.create_ipam_config(pool_configs=[ipam_pool])
network = docker_client.create_network('network1', ipam=ipam_config)
```

View File

@ -185,7 +185,66 @@ class TestNetworks(helpers.BaseTestCase):
container_data = self.client.inspect_container(container) container_data = self.client.inspect_container(container)
self.assertEqual( self.assertEqual(
container_data['NetworkSettings']['Networks'][net_name]['Aliases'], container_data['NetworkSettings']['Networks'][net_name]['Aliases'],
['foo', 'bar']) ['foo', 'bar']
)
@requires_api_version('1.22')
def test_create_with_ipv4_address(self):
net_name, net_id = self.create_network(
ipam=create_ipam_config(
driver='default',
pool_configs=[create_ipam_pool(subnet="132.124.0.0/16")],
),
)
container = self.client.create_container(
image='busybox', command='top',
host_config=self.client.create_host_config(network_mode=net_name),
networking_config=self.client.create_networking_config({
net_name: self.client.create_endpoint_config(
ipv4_address='132.124.0.23'
)
})
)
self.tmp_containers.append(container)
self.client.start(container)
container_data = self.client.inspect_container(container)
self.assertEqual(
container_data[
'NetworkSettings']['Networks'][net_name]['IPAMConfig'][
'IPv4Address'
],
'132.124.0.23'
)
@requires_api_version('1.22')
def test_create_with_ipv6_address(self):
net_name, net_id = self.create_network(
ipam=create_ipam_config(
driver='default',
pool_configs=[create_ipam_pool(subnet="2001:389::1/64")],
),
)
container = self.client.create_container(
image='busybox', command='top',
host_config=self.client.create_host_config(network_mode=net_name),
networking_config=self.client.create_networking_config({
net_name: self.client.create_endpoint_config(
ipv6_address='2001:389::f00d'
)
})
)
self.tmp_containers.append(container)
self.client.start(container)
container_data = self.client.inspect_container(container)
self.assertEqual(
container_data[
'NetworkSettings']['Networks'][net_name]['IPAMConfig'][
'IPv6Address'
],
'2001:389::f00d'
)
@requires_api_version('1.22') @requires_api_version('1.22')
def test_create_with_links(self): def test_create_with_links(self):