Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions docker/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,7 @@ def start(self, container, binds=None, port_bindings=None, lxc_conf=None,
publish_all_ports=False, links=None, privileged=False,
dns=None, dns_search=None, volumes_from=None, network_mode=None,
restart_policy=None, cap_add=None, cap_drop=None, devices=None,
extra_hosts=None):
extra_hosts=None, read_only=None):

if utils.compare_version('1.10', self._version) < 0:
if dns is not None:
Expand All @@ -948,13 +948,19 @@ def start(self, container, binds=None, port_bindings=None, lxc_conf=None,
'volumes_from is only supported for API version >= 1.10'
)

if utils.compare_version('1.17', self._version) < 0 and \
read_only is not None:
raise errors.InvalidVersion(
'read_only is only supported for API version >= 1.17'
)

start_config = utils.create_host_config(
binds=binds, port_bindings=port_bindings, lxc_conf=lxc_conf,
publish_all_ports=publish_all_ports, links=links, dns=dns,
privileged=privileged, dns_search=dns_search, cap_add=cap_add,
cap_drop=cap_drop, volumes_from=volumes_from, devices=devices,
network_mode=network_mode, restart_policy=restart_policy,
extra_hosts=extra_hosts
extra_hosts=extra_hosts, read_only=read_only
)

if isinstance(container, dict):
Expand Down
5 changes: 4 additions & 1 deletion docker/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ def create_host_config(
publish_all_ports=False, links=None, privileged=False,
dns=None, dns_search=None, volumes_from=None, network_mode=None,
restart_policy=None, cap_add=None, cap_drop=None, devices=None,
extra_hosts=None
extra_hosts=None, read_only=None
):
host_config = {}

Expand All @@ -311,6 +311,9 @@ def create_host_config(
if publish_all_ports:
host_config['PublishAllPorts'] = publish_all_ports

if read_only is not None:
host_config['ReadOnlyRootFs'] = read_only

if dns_search:
host_config['DnsSearch'] = dns_search

Expand Down
1 change: 1 addition & 0 deletions docs/hostconfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ for example:
* cap_add (list of str): Add kernel capabilities
* cap_drop (list of str): Drop kernel capabilities
* extra_hosts (dict): custom host-to-IP mappings (host:ip)
* read_only (bool): mount the container's root filesystem as read only

**Returns** (dict) HostConfig dictionary

Expand Down
27 changes: 27 additions & 0 deletions tests/integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,33 @@ def runTest(self):
self.assertFalse(inspect_data['VolumesRW'][mount_dest])


class TestCreateContainerReadOnlyFs(BaseTestCase):
def runTest(self):
ctnr = self.client.create_container(
'busybox', ['mkdir', '/shrine'],
host_config=create_host_config(read_only=True)
)
self.assertIn('Id', ctnr)
self.tmp_containers.append(ctnr['Id'])
self.client.start(ctnr)
res = self.client.wait(ctnr)
self.assertNotEqual(res, 0)


class TestStartContainerReadOnlyFs(BaseTestCase):
def runTest(self):
# Presumably a bug in 1.5.0
# https://github.com/docker/docker/issues/10695
ctnr = self.client.create_container(
'busybox', ['mkdir', '/shrine'],
)
self.assertIn('Id', ctnr)
self.tmp_containers.append(ctnr['Id'])
self.client.start(ctnr, read_only=True)
# res = self.client.wait(ctnr)
# self.assertNotEqual(res, 0)


class TestCreateContainerWithName(BaseTestCase):
def runTest(self):
res = self.client.create_container('busybox', 'true', name='foobar')
Expand Down