Prevent duplicate binds in generated container config

Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
Joffrey F 2018-04-26 15:20:45 -07:00
parent 9f42fac2bb
commit aecc0de28f
2 changed files with 23 additions and 3 deletions

View File

@ -877,7 +877,6 @@ class Service(object):
container_volumes, self.options.get('tmpfs') or [], previous_container,
container_mounts
)
override_options['binds'] = binds
container_options['environment'].update(affinity)
container_options['volumes'] = dict((v.internal, {}) for v in container_volumes or {})
@ -890,13 +889,13 @@ class Service(object):
if m.is_tmpfs:
override_options['tmpfs'].append(m.target)
else:
override_options['binds'].append(m.legacy_repr())
binds.append(m.legacy_repr())
container_options['volumes'][m.target] = {}
secret_volumes = self.get_secret_volumes()
if secret_volumes:
if version_lt(self.client.api_version, '1.30'):
override_options['binds'].extend(v.legacy_repr() for v in secret_volumes)
binds.extend(v.legacy_repr() for v in secret_volumes)
container_options['volumes'].update(
(v.target, {}) for v in secret_volumes
)
@ -904,6 +903,8 @@ class Service(object):
override_options['mounts'] = override_options.get('mounts') or []
override_options['mounts'].extend([build_mount(v) for v in secret_volumes])
# Remove possible duplicates (see e.g. https://github.com/docker/compose/issues/5885)
override_options['binds'] = list(set(binds))
return container_options, override_options
def _get_container_host_config(self, override_options, one_off=False):

View File

@ -10,6 +10,7 @@ from docker.errors import NotFound
from .. import mock
from .. import unittest
from compose.config.errors import DependencyError
from compose.config.types import MountSpec
from compose.config.types import ServicePort
from compose.config.types import ServiceSecret
from compose.config.types import VolumeFromSpec
@ -955,6 +956,24 @@ class ServiceTest(unittest.TestCase):
assert service.create_container().id == 'new_cont_id'
def test_build_volume_options_duplicate_binds(self):
self.mock_client.api_version = '1.29' # Trigger 3.2 format workaround
service = Service('foo', client=self.mock_client)
ctnr_opts, override_opts = service._build_container_volume_options(
previous_container=None,
container_options={
'volumes': [
MountSpec.parse({'source': 'vol', 'target': '/data', 'type': 'volume'}),
VolumeSpec.parse('vol:/data:rw'),
],
'environment': {},
},
override_options={},
)
assert 'binds' in override_opts
assert len(override_opts['binds']) == 1
assert override_opts['binds'][0] == 'vol:/data:rw'
class TestServiceNetwork(unittest.TestCase):
def setUp(self):