Enable use of Docker networking with the --x-networking flag
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
This commit is contained in:
parent
f228173660
commit
d5f5eb1924
14 changed files with 240 additions and 24 deletions
|
|
@ -49,7 +49,10 @@ def project_from_options(base_dir, options):
|
|||
base_dir,
|
||||
get_config_path(options.get('--file')),
|
||||
project_name=options.get('--project-name'),
|
||||
verbose=options.get('--verbose'))
|
||||
verbose=options.get('--verbose'),
|
||||
use_networking=options.get('--x-networking'),
|
||||
network_driver=options.get('--x-network-driver'),
|
||||
)
|
||||
|
||||
|
||||
def get_config_path(file_option):
|
||||
|
|
@ -76,14 +79,18 @@ def get_client(verbose=False):
|
|||
return client
|
||||
|
||||
|
||||
def get_project(base_dir, config_path=None, project_name=None, verbose=False):
|
||||
def get_project(base_dir, config_path=None, project_name=None, verbose=False,
|
||||
use_networking=False, network_driver=None):
|
||||
config_details = config.find(base_dir, config_path)
|
||||
|
||||
try:
|
||||
return Project.from_dicts(
|
||||
get_project_name(config_details.working_dir, project_name),
|
||||
config.load(config_details),
|
||||
get_client(verbose=verbose))
|
||||
get_client(verbose=verbose),
|
||||
use_networking=use_networking,
|
||||
network_driver=network_driver,
|
||||
)
|
||||
except ConfigError as e:
|
||||
raise errors.UserError(six.text_type(e))
|
||||
|
||||
|
|
|
|||
|
|
@ -117,6 +117,10 @@ class TopLevelCommand(DocoptCommand):
|
|||
Options:
|
||||
-f, --file FILE Specify an alternate compose file (default: docker-compose.yml)
|
||||
-p, --project-name NAME Specify an alternate project name (default: directory name)
|
||||
--x-networking (EXPERIMENTAL) Use new Docker networking functionality.
|
||||
Requires Docker 1.9 or later.
|
||||
--x-network-driver DRIVER (EXPERIMENTAL) Specify a network driver (default: "bridge").
|
||||
Requires Docker 1.9 or later.
|
||||
--verbose Show more output
|
||||
-v, --version Print version and exit
|
||||
|
||||
|
|
|
|||
|
|
@ -77,10 +77,12 @@ class Project(object):
|
|||
"""
|
||||
A collection of services.
|
||||
"""
|
||||
def __init__(self, name, services, client):
|
||||
def __init__(self, name, services, client, use_networking=False, network_driver=None):
|
||||
self.name = name
|
||||
self.services = services
|
||||
self.client = client
|
||||
self.use_networking = use_networking
|
||||
self.network_driver = network_driver or 'bridge'
|
||||
|
||||
def labels(self, one_off=False):
|
||||
return [
|
||||
|
|
@ -89,11 +91,15 @@ class Project(object):
|
|||
]
|
||||
|
||||
@classmethod
|
||||
def from_dicts(cls, name, service_dicts, client):
|
||||
def from_dicts(cls, name, service_dicts, client, use_networking=False, network_driver=None):
|
||||
"""
|
||||
Construct a ServiceCollection from a list of dicts representing services.
|
||||
"""
|
||||
project = cls(name, [], client)
|
||||
project = cls(name, [], client, use_networking=use_networking, network_driver=network_driver)
|
||||
|
||||
if use_networking:
|
||||
remove_links(service_dicts)
|
||||
|
||||
for service_dict in sort_service_dicts(service_dicts):
|
||||
links = project.get_links(service_dict)
|
||||
volumes_from = project.get_volumes_from(service_dict)
|
||||
|
|
@ -103,6 +109,7 @@ class Project(object):
|
|||
Service(
|
||||
client=client,
|
||||
project=name,
|
||||
use_networking=use_networking,
|
||||
links=links,
|
||||
net=net,
|
||||
volumes_from=volumes_from,
|
||||
|
|
@ -207,6 +214,8 @@ class Project(object):
|
|||
def get_net(self, service_dict):
|
||||
net = service_dict.pop('net', None)
|
||||
if not net:
|
||||
if self.use_networking:
|
||||
return Net(self.name)
|
||||
return Net(None)
|
||||
|
||||
net_name = get_service_name_from_net(net)
|
||||
|
|
@ -289,6 +298,9 @@ class Project(object):
|
|||
|
||||
plans = self._get_convergence_plans(services, strategy)
|
||||
|
||||
if self.use_networking:
|
||||
self.ensure_network_exists()
|
||||
|
||||
return [
|
||||
container
|
||||
for service in services
|
||||
|
|
@ -350,6 +362,26 @@ class Project(object):
|
|||
|
||||
return [c for c in containers if matches_service_names(c)]
|
||||
|
||||
def get_network(self):
|
||||
networks = self.client.networks(names=[self.name])
|
||||
if networks:
|
||||
return networks[0]
|
||||
return None
|
||||
|
||||
def ensure_network_exists(self):
|
||||
# TODO: recreate network if driver has changed?
|
||||
if self.get_network() is None:
|
||||
log.info(
|
||||
'Creating network "{}" with driver "{}"'
|
||||
.format(self.name, self.network_driver)
|
||||
)
|
||||
self.client.create_network(self.name, driver=self.network_driver)
|
||||
|
||||
def remove_network(self):
|
||||
network = self.get_network()
|
||||
if network:
|
||||
self.client.remove_network(network['id'])
|
||||
|
||||
def _inject_deps(self, acc, service):
|
||||
dep_names = service.get_dependency_names()
|
||||
|
||||
|
|
@ -365,6 +397,26 @@ class Project(object):
|
|||
return acc + dep_services
|
||||
|
||||
|
||||
def remove_links(service_dicts):
|
||||
services_with_links = [s for s in service_dicts if 'links' in s]
|
||||
if not services_with_links:
|
||||
return
|
||||
|
||||
if len(services_with_links) == 1:
|
||||
prefix = '"{}" defines'.format(services_with_links[0]['name'])
|
||||
else:
|
||||
prefix = 'Some services ({}) define'.format(
|
||||
", ".join('"{}"'.format(s['name']) for s in services_with_links))
|
||||
|
||||
log.warn(
|
||||
'\n{} links, which are not compatible with Docker networking and will be ignored.\n'
|
||||
'Future versions of Docker will not support links - you should remove them for '
|
||||
'forwards-compatibility.\n'.format(prefix))
|
||||
|
||||
for s in services_with_links:
|
||||
del s['links']
|
||||
|
||||
|
||||
class NoSuchService(Exception):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ class Service(object):
|
|||
name,
|
||||
client=None,
|
||||
project='default',
|
||||
use_networking=False,
|
||||
links=None,
|
||||
volumes_from=None,
|
||||
net=None,
|
||||
|
|
@ -124,6 +125,7 @@ class Service(object):
|
|||
self.name = name
|
||||
self.client = client
|
||||
self.project = project
|
||||
self.use_networking = use_networking
|
||||
self.links = links or []
|
||||
self.volumes_from = volumes_from or []
|
||||
self.net = net or Net(None)
|
||||
|
|
@ -602,6 +604,9 @@ class Service(object):
|
|||
container_options['hostname'] = parts[0]
|
||||
container_options['domainname'] = parts[2]
|
||||
|
||||
if 'hostname' not in container_options and self.use_networking:
|
||||
container_options['hostname'] = self.name
|
||||
|
||||
if 'ports' in container_options or 'expose' in self.options:
|
||||
ports = []
|
||||
all_ports = container_options.get('ports', []) + self.options.get('expose', [])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue