Skip to content

Commit 4e441b2

Browse files
committed
Merge pull request #834 from lots0logs/814-host-config-mem-swap
Add support for MemorySwappiness to client.create_host_config()
2 parents ac14839 + 64fc383 commit 4e441b2

File tree

3 files changed

+68
-19
lines changed

3 files changed

+68
-19
lines changed

docker/utils/utils.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -469,16 +469,17 @@ def parse_bytes(s):
469469
return s
470470

471471

472-
def create_host_config(
473-
binds=None, port_bindings=None, lxc_conf=None,
474-
publish_all_ports=False, links=None, privileged=False,
475-
dns=None, dns_search=None, volumes_from=None, network_mode=None,
476-
restart_policy=None, cap_add=None, cap_drop=None, devices=None,
477-
extra_hosts=None, read_only=None, pid_mode=None, ipc_mode=None,
478-
security_opt=None, ulimits=None, log_config=None, mem_limit=None,
479-
memswap_limit=None, cgroup_parent=None, group_add=None, cpu_quota=None,
480-
cpu_period=None, version=None
481-
):
472+
def create_host_config(binds=None, port_bindings=None, lxc_conf=None,
473+
publish_all_ports=False, links=None, privileged=False,
474+
dns=None, dns_search=None, volumes_from=None,
475+
network_mode=None, restart_policy=None, cap_add=None,
476+
cap_drop=None, devices=None, extra_hosts=None,
477+
read_only=None, pid_mode=None, ipc_mode=None,
478+
security_opt=None, ulimits=None, log_config=None,
479+
mem_limit=None, memswap_limit=None, mem_swappiness=None,
480+
cgroup_parent=None, group_add=None, cpu_quota=None,
481+
cpu_period=None, version=None):
482+
482483
host_config = {}
483484

484485
if not version:
@@ -491,13 +492,26 @@ def create_host_config(
491492
if mem_limit is not None:
492493
if isinstance(mem_limit, six.string_types):
493494
mem_limit = parse_bytes(mem_limit)
495+
494496
host_config['Memory'] = mem_limit
495497

496498
if memswap_limit is not None:
497499
if isinstance(memswap_limit, six.string_types):
498500
memswap_limit = parse_bytes(memswap_limit)
499501
host_config['MemorySwap'] = memswap_limit
500502

503+
if mem_swappiness is not None:
504+
if version_lt(version, '1.20'):
505+
raise errors.InvalidVersion(
506+
'mem_swappiness param not supported for API version < 1.20'
507+
)
508+
if not isinstance(mem_swappiness, int):
509+
raise TypeError(
510+
'Invalid type for mem_swappiness param: expected int but'
511+
' found {0}'.format(type(mem_swappiness))
512+
)
513+
host_config['MemorySwappiness'] = mem_swappiness
514+
501515
if pid_mode not in (None, 'host'):
502516
raise errors.DockerException(
503517
'Invalid value for pid param: {0}'.format(pid_mode)

docs/hostconfig.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,20 @@ Docker bridge, 'none': no networking for this container, 'container:[name|id]':
3434
reuses another container network stack), 'host': use the host network stack
3535
inside the container.
3636

37-
`restart_policy` is available since v1.2.0 and sets the RestartPolicy for how a
38-
container should or should not be restarted on exit. By default the policy is
39-
set to no meaning do not restart the container when it exits. The user may
40-
specify the restart policy as a dictionary for example:
37+
`restart_policy` is available since v1.2.0 and sets the container's *RestartPolicy*
38+
which defines the conditions under which a container should be restarted upon exit.
39+
If no *RestartPolicy* is defined, the container will not be restarted when it exits.
40+
The *RestartPolicy* is specified as a dict. For example, if the container
41+
should always be restarted:
4142
```python
4243
{
4344
"MaximumRetryCount": 0,
4445
"Name": "always"
4546
}
4647
```
4748

48-
For always restarting the container on exit or can specify to restart the
49-
container to restart on failure and can limit number of restarts. For example:
49+
It is possible to restart the container only on failure as well as limit the number
50+
of restarts. For example:
5051
```python
5152
{
5253
"MaximumRetryCount": 5,
@@ -95,10 +96,12 @@ for example:
9596
of ulimits to be set in the container.
9697
* log_config (`docker.utils.LogConfig` or dict): Logging configuration to
9798
container
98-
* mem_limit (str or num): Maximum amount of memory container is allowed to
99-
consume. (e.g. `'1g'`)
100-
* memswap_limit (str or num): Maximum amount of memory + swap a container is
99+
* mem_limit (str or int): Maximum amount of memory container is allowed to
100+
consume. (e.g. `'1G'`)
101+
* memswap_limit (str or int): Maximum amount of memory + swap a container is
101102
allowed to consume.
103+
* mem_swappiness (int): Tune a container's memory swappiness behavior.
104+
Accepts number between 0 and 100.
102105
* group_add (list): List of additional group names and/or IDs that the
103106
container process will run as.
104107
* devices (list): A list of devices to add to the container specified as dicts

tests/integration/container_test.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,38 @@ def test_valid_no_config_specified(self):
335335
self.assertEqual(container_log_config['Type'], "json-file")
336336
self.assertEqual(container_log_config['Config'], {})
337337

338+
def test_create_with_memory_constraints_with_str(self):
339+
ctnr = self.client.create_container(
340+
BUSYBOX, 'true',
341+
host_config=self.client.create_host_config(
342+
memswap_limit='1G',
343+
mem_limit='700M'
344+
)
345+
)
346+
self.assertIn('Id', ctnr)
347+
self.tmp_containers.append(ctnr['Id'])
348+
self.client.start(ctnr)
349+
inspect = self.client.inspect_container(ctnr)
350+
351+
self.assertIn('HostConfig', inspect)
352+
host_config = inspect['HostConfig']
353+
for limit in ['Memory', 'MemorySwap']:
354+
self.assertIn(limit, host_config)
355+
356+
def test_create_with_memory_constraints_with_int(self):
357+
ctnr = self.client.create_container(
358+
BUSYBOX, 'true',
359+
host_config=self.client.create_host_config(mem_swappiness=40)
360+
)
361+
self.assertIn('Id', ctnr)
362+
self.tmp_containers.append(ctnr['Id'])
363+
self.client.start(ctnr)
364+
inspect = self.client.inspect_container(ctnr)
365+
366+
self.assertIn('HostConfig', inspect)
367+
host_config = inspect['HostConfig']
368+
self.assertIn('MemorySwappiness', host_config)
369+
338370

339371
class VolumeBindTest(api_test.BaseTestCase):
340372
def setUp(self):

0 commit comments

Comments
 (0)