Skip to content

Commit 8c4546f

Browse files
committed
Merge pull request #994 from aanand/janLo-tmpfs-support
tmpfs support
2 parents 7befe69 + e576417 commit 8c4546f

File tree

6 files changed

+145
-1
lines changed

6 files changed

+145
-1
lines changed

docker/utils/utils.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,35 @@ def convert_volume_binds(binds):
337337
return result
338338

339339

340+
def convert_tmpfs_mounts(tmpfs):
341+
if isinstance(tmpfs, dict):
342+
return tmpfs
343+
344+
if not isinstance(tmpfs, list):
345+
raise ValueError(
346+
'Expected tmpfs value to be either a list or a dict, found: {}'
347+
.format(type(tmpfs).__name__)
348+
)
349+
350+
result = {}
351+
for mount in tmpfs:
352+
if isinstance(mount, six.string_types):
353+
if ":" in mount:
354+
name, options = mount.split(":", 1)
355+
else:
356+
name = mount
357+
options = ""
358+
359+
else:
360+
raise ValueError(
361+
"Expected item in tmpfs list to be a string, found: {}"
362+
.format(type(mount).__name__)
363+
)
364+
365+
result[name] = options
366+
return result
367+
368+
340369
def parse_repository_tag(repo_name):
341370
parts = repo_name.rsplit('@', 1)
342371
if len(parts) == 2:
@@ -584,7 +613,7 @@ def create_host_config(binds=None, port_bindings=None, lxc_conf=None,
584613
mem_limit=None, memswap_limit=None, mem_swappiness=None,
585614
cgroup_parent=None, group_add=None, cpu_quota=None,
586615
cpu_period=None, oom_kill_disable=False, shm_size=None,
587-
version=None):
616+
version=None, tmpfs=None):
588617

589618
host_config = {}
590619

@@ -751,6 +780,11 @@ def create_host_config(binds=None, port_bindings=None, lxc_conf=None,
751780

752781
host_config['CpuPeriod'] = cpu_period
753782

783+
if tmpfs:
784+
if version_lt(version, '1.22'):
785+
raise host_config_version_error('tmpfs', '1.22')
786+
host_config["Tmpfs"] = convert_tmpfs_mounts(tmpfs)
787+
754788
return host_config
755789

756790

docs/hostconfig.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ for example:
111111
container process will run as.
112112
* devices (list): Host device bindings. See [host devices](host-devices.md)
113113
for more information.
114+
* tmpfs: Temporary filesystems to mouunt. See [Using tmpfs](tmpfs.md) for more
115+
information.
114116

115117
**Returns** (dict) HostConfig dictionary
116118

docs/tmpfs.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Using tmpfs
2+
3+
When creating a container, you can specify paths to be mounted with tmpfs using
4+
the `tmpfs` argument to `create_host_config`, similarly to the `--tmpfs`
5+
argument to `docker run`.
6+
7+
This capability is supported in Docker Engine 1.10 and up.
8+
9+
`tmpfs` can be either a list or a dictionary. If it's a list, each item is a
10+
string specifying the path and (optionally) any configuration for the mount:
11+
12+
```python
13+
client.create_container(
14+
'busybox', 'ls',
15+
host_config=client.create_host_config(tmpfs=[
16+
'/mnt/vol2',
17+
'/mnt/vol1:size=3G,uid=1000'
18+
])
19+
)
20+
```
21+
22+
Alternatively, if it's a dictionary, each key is a path and each value contains
23+
the mount options:
24+
25+
```python
26+
client.create_container(
27+
'busybox', 'ls',
28+
host_config=client.create_host_config(tmpfs={
29+
'/mnt/vol2': '',
30+
'/mnt/vol1': 'size=3G,uid=1000'
31+
})
32+
)
33+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pages:
1313
- Host devices: host-devices.md
1414
- Host configuration: hostconfig.md
1515
- Network configuration: networks.md
16+
- Using tmpfs: tmpfs.md
1617
- Using with boot2docker: boot2docker.md
1718
- Change Log: change_log.md
1819
- Contributing: contributing.md

tests/integration/container_test.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,22 @@ def test_create_with_environment_variable_no_value(self):
382382
sorted(['Foo', 'Other=one', 'Blank='])
383383
)
384384

385+
@requires_api_version('1.22')
386+
def test_create_with_tmpfs(self):
387+
tmpfs = {
388+
'/tmp1': 'size=3M'
389+
}
390+
391+
container = self.client.create_container(
392+
BUSYBOX,
393+
['echo'],
394+
host_config=self.client.create_host_config(
395+
tmpfs=tmpfs))
396+
397+
self.tmp_containers.append(container['Id'])
398+
config = self.client.inspect_container(container)
399+
assert config['HostConfig']['Tmpfs'] == tmpfs
400+
385401

386402
class VolumeBindTest(helpers.BaseTestCase):
387403
def setUp(self):

tests/unit/container_test.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,64 @@ def test_create_container_with_aliases(self):
10161016
}
10171017
}}'''))
10181018

1019+
@requires_api_version('1.22')
1020+
def test_create_container_with_tmpfs_list(self):
1021+
1022+
self.client.create_container(
1023+
'busybox', 'true', host_config=self.client.create_host_config(
1024+
tmpfs=[
1025+
"/tmp",
1026+
"/mnt:size=3G,uid=100"
1027+
]
1028+
)
1029+
)
1030+
1031+
args = fake_request.call_args
1032+
self.assertEqual(args[0][1], url_prefix +
1033+
'containers/create')
1034+
expected_payload = self.base_create_payload()
1035+
expected_payload['HostConfig'] = self.client.create_host_config()
1036+
expected_payload['HostConfig']['Tmpfs'] = {
1037+
"/tmp": "",
1038+
"/mnt": "size=3G,uid=100"
1039+
}
1040+
self.assertEqual(json.loads(args[1]['data']), expected_payload)
1041+
self.assertEqual(args[1]['headers'],
1042+
{'Content-Type': 'application/json'})
1043+
self.assertEqual(
1044+
args[1]['timeout'],
1045+
DEFAULT_TIMEOUT_SECONDS
1046+
)
1047+
1048+
@requires_api_version('1.22')
1049+
def test_create_container_with_tmpfs_dict(self):
1050+
1051+
self.client.create_container(
1052+
'busybox', 'true', host_config=self.client.create_host_config(
1053+
tmpfs={
1054+
"/tmp": "",
1055+
"/mnt": "size=3G,uid=100"
1056+
}
1057+
)
1058+
)
1059+
1060+
args = fake_request.call_args
1061+
self.assertEqual(args[0][1], url_prefix +
1062+
'containers/create')
1063+
expected_payload = self.base_create_payload()
1064+
expected_payload['HostConfig'] = self.client.create_host_config()
1065+
expected_payload['HostConfig']['Tmpfs'] = {
1066+
"/tmp": "",
1067+
"/mnt": "size=3G,uid=100"
1068+
}
1069+
self.assertEqual(json.loads(args[1]['data']), expected_payload)
1070+
self.assertEqual(args[1]['headers'],
1071+
{'Content-Type': 'application/json'})
1072+
self.assertEqual(
1073+
args[1]['timeout'],
1074+
DEFAULT_TIMEOUT_SECONDS
1075+
)
1076+
10191077

10201078
class ContainerTest(DockerClientTest):
10211079
def test_list_containers(self):

0 commit comments

Comments
 (0)