From 9ffe69a572e862eb90017cceddd65d76c4eed555 Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Thu, 16 Jul 2015 12:46:15 +0100 Subject: [PATCH 1/3] Refactor can_be_scaled for clarity Signed-off-by: Aanand Prasad --- compose/service.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compose/service.py b/compose/service.py index a488b2c68c..f73fa96b46 100644 --- a/compose/service.py +++ b/compose/service.py @@ -157,7 +157,7 @@ class Service(object): - starts containers until there are at least `desired_num` running - removes all stopped containers """ - if not self.can_be_scaled(): + if self.specifies_host_port(): log.warn('Service %s specifies a port on the host. If multiple containers ' 'for this service are created on a single host, the port will clash.' % self.name) @@ -703,11 +703,11 @@ class Service(object): '{0}={1}'.format(LABEL_ONE_OFF, "True" if one_off else "False") ] - def can_be_scaled(self): + def specifies_host_port(self): for port in self.options.get('ports', []): if ':' in str(port): - return False - return True + return True + return False def pull(self, insecure_registry=False): if 'image' not in self.options: From 445fe89fcec3292919b3432223f90c77cafbbbee Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Fri, 17 Jul 2015 14:59:43 +0100 Subject: [PATCH 2/3] Tweak wording of scale warning Signed-off-by: Aanand Prasad --- compose/service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose/service.py b/compose/service.py index f73fa96b46..d606e6b21f 100644 --- a/compose/service.py +++ b/compose/service.py @@ -158,7 +158,7 @@ class Service(object): - removes all stopped containers """ if self.specifies_host_port(): - log.warn('Service %s specifies a port on the host. If multiple containers ' + log.warn('The "%s" service specifies a port on the host. If multiple containers ' 'for this service are created on a single host, the port will clash.' % self.name) From a3191ab90f57a42aa84c94e9920287b9e9b81f3f Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Thu, 16 Jul 2015 12:51:15 +0100 Subject: [PATCH 3/3] Add container_name option Signed-off-by: Aanand Prasad --- compose/config.py | 1 + compose/service.py | 12 +++++++++++- docs/yml.md | 10 ++++++++++ tests/integration/service_test.py | 7 +++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/compose/config.py b/compose/config.py index 2baf327b01..064dadaec4 100644 --- a/compose/config.py +++ b/compose/config.py @@ -50,6 +50,7 @@ DOCKER_CONFIG_KEYS = [ ALLOWED_KEYS = DOCKER_CONFIG_KEYS + [ 'build', + 'container_name', 'dockerfile', 'expose', 'external_links', diff --git a/compose/service.py b/compose/service.py index d606e6b21f..d90318f5ec 100644 --- a/compose/service.py +++ b/compose/service.py @@ -157,6 +157,12 @@ class Service(object): - starts containers until there are at least `desired_num` running - removes all stopped containers """ + if self.custom_container_name() and desired_num > 1: + log.warn('The "%s" service is using the custom container name "%s". ' + 'Docker requires each container to have a unique name. ' + 'Remove the custom name to scale the service.' + % (self.name, self.custom_container_name())) + if self.specifies_host_port(): log.warn('The "%s" service specifies a port on the host. If multiple containers ' 'for this service are created on a single host, the port will clash.' @@ -531,7 +537,8 @@ class Service(object): for k in DOCKER_CONFIG_KEYS if k in self.options) container_options.update(override_options) - container_options['name'] = self.get_container_name(number, one_off) + container_options['name'] = self.custom_container_name() \ + or self.get_container_name(number, one_off) if add_config_hash: config_hash = self.config_hash() @@ -703,6 +710,9 @@ class Service(object): '{0}={1}'.format(LABEL_ONE_OFF, "True" if one_off else "False") ] + def custom_container_name(self): + return self.options.get('container_name') + def specifies_host_port(self): for port in self.options.get('ports', []): if ':' in str(port): diff --git a/docs/yml.md b/docs/yml.md index 772e5dd554..f92b568256 100644 --- a/docs/yml.md +++ b/docs/yml.md @@ -239,6 +239,16 @@ It's recommended that you use reverse-DNS notation to prevent your labels from c - "com.example.department=Finance" - "com.example.label-with-empty-value" +### container_name + +Specify a custom container name, rather than a generated default name. + + container_name: my-web-container + +Because Docker container names must be unique, you cannot scale a service +beyond 1 container if you have specified a custom name. Attempting to do so +results in an error. + ### log driver Specify a logging driver for the service's containers, as with the ``--log-driver`` option for docker run ([documented here](http://docs.docker.com/reference/run/#logging-drivers-log-driver)). diff --git a/tests/integration/service_test.py b/tests/integration/service_test.py index 9880b8e84d..dbb97d8f3b 100644 --- a/tests/integration/service_test.py +++ b/tests/integration/service_test.py @@ -699,6 +699,13 @@ class ServiceTest(DockerClientTestCase): for name in labels_list: self.assertIn((name, ''), labels) + def test_custom_container_name(self): + service = self.create_service('web', container_name='my-web-container') + self.assertEqual(service.custom_container_name(), 'my-web-container') + + container = create_and_start_container(service) + self.assertEqual(container.name, 'my-web-container') + def test_log_drive_invalid(self): service = self.create_service('web', log_driver='xxx') self.assertRaises(ValueError, lambda: create_and_start_container(service))