diff --git a/compose/config/config.py b/compose/config/config.py index f34809a9..961d0b57 100644 --- a/compose/config/config.py +++ b/compose/config/config.py @@ -591,7 +591,7 @@ def process_service(service_config): if 'extra_hosts' in service_dict: service_dict['extra_hosts'] = parse_extra_hosts(service_dict['extra_hosts']) - for field in ['dns', 'dns_search']: + for field in ['dns', 'dns_search', 'tmpfs']: if field in service_dict: service_dict[field] = to_list(service_dict[field]) @@ -730,7 +730,7 @@ def merge_service_dicts(base, override, version): ]: md.merge_field(field, operator.add, default=[]) - for field in ['dns', 'dns_search', 'env_file']: + for field in ['dns', 'dns_search', 'env_file', 'tmpfs']: md.merge_field(field, merge_list_or_string) for field in set(ALLOWED_KEYS) - set(md): diff --git a/compose/config/config_schema_v1.json b/compose/config/config_schema_v1.json index 36a93793..9fad7d00 100644 --- a/compose/config/config_schema_v1.json +++ b/compose/config/config_schema_v1.json @@ -104,6 +104,7 @@ "shm_size": {"type": ["number", "string"]}, "stdin_open": {"type": "boolean"}, "stop_signal": {"type": "string"}, + "tmpfs": {"$ref": "#/definitions/string_or_list"}, "tty": {"type": "boolean"}, "ulimits": { "type": "object", diff --git a/compose/config/config_schema_v2.0.json b/compose/config/config_schema_v2.0.json index 33afc9b2..e84d1317 100644 --- a/compose/config/config_schema_v2.0.json +++ b/compose/config/config_schema_v2.0.json @@ -184,6 +184,7 @@ "shm_size": {"type": ["number", "string"]}, "stdin_open": {"type": "boolean"}, "stop_signal": {"type": "string"}, + "tmpfs": {"$ref": "#/definitions/string_or_list"}, "tty": {"type": "boolean"}, "ulimits": { "type": "object", diff --git a/compose/service.py b/compose/service.py index 30d28e4c..f8b13607 100644 --- a/compose/service.py +++ b/compose/service.py @@ -668,6 +668,7 @@ class Service(object): cgroup_parent=options.get('cgroup_parent'), cpu_quota=options.get('cpu_quota'), shm_size=options.get('shm_size'), + tmpfs=options.get('tmpfs'), ) def build(self, no_cache=False, pull=False, force_rm=False): diff --git a/docs/compose-file.md b/docs/compose-file.md index 85875512..09de5615 100644 --- a/docs/compose-file.md +++ b/docs/compose-file.md @@ -226,6 +226,15 @@ Custom DNS search domains. Can be a single value or a list. - dc1.example.com - dc2.example.com +### tmpfs + +Mount a temporary file system inside the container. Can be a single value or a list. + + tmpfs: /run + tmpfs: + - /run + - /tmp + ### entrypoint Override the default entrypoint. diff --git a/docs/extends.md b/docs/extends.md index 9ecccd8a..6f457391 100644 --- a/docs/extends.md +++ b/docs/extends.md @@ -302,8 +302,8 @@ replaces the old value. > This is because `build` and `image` cannot be used together in a version 1 > file. -For the **multi-value options** `ports`, `expose`, `external_links`, `dns` and -`dns_search`, Compose concatenates both sets of values: +For the **multi-value options** `ports`, `expose`, `external_links`, `dns`, +`dns_search`, and `tmpfs`, Compose concatenates both sets of values: # original service expose: diff --git a/requirements.txt b/requirements.txt index 074864d4..2b7c85e6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ cached-property==1.2.0 dockerpty==0.4.1 docopt==0.6.1 enum34==1.0.4 -git+https://github.com/docker/docker-py.git@d8be3e0fce60fbe25be088b64bccbcee83effdb1#egg=docker-py +git+https://github.com/docker/docker-py.git@8c4546f8c8f52bb2923834783a17beb5bb89a724#egg=docker-py jsonschema==2.5.1 requests==2.7.0 six==1.7.3 diff --git a/tests/integration/service_test.py b/tests/integration/service_test.py index 6d0c97db..22cbfcee 100644 --- a/tests/integration/service_test.py +++ b/tests/integration/service_test.py @@ -875,6 +875,11 @@ class ServiceTest(DockerClientTestCase): container = create_and_start_container(service) self.assertEqual(container.get('HostConfig.DnsSearch'), ['dc1.example.com', 'dc2.example.com']) + def test_tmpfs(self): + service = self.create_service('web', tmpfs=['/run']) + container = create_and_start_container(service) + self.assertEqual(container.get('HostConfig.Tmpfs'), {'/run': ''}) + def test_working_dir_param(self): service = self.create_service('container', working_dir='/working/dir/sample') container = service.create_container() diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index d0e82420..e3dac160 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -1194,6 +1194,21 @@ class ConfigTest(unittest.TestCase): } ] + def test_tmpfs_option(self): + actual = config.load(build_config_details({ + 'web': { + 'image': 'alpine', + 'tmpfs': '/run', + } + })) + assert actual.services == [ + { + 'name': 'web', + 'image': 'alpine', + 'tmpfs': ['/run'], + } + ] + def test_merge_service_dicts_from_files_with_extends_in_base(self): base = { 'volumes': ['.:/app'],