mirror of https://github.com/docker/docker-py.git
Retrieve container logs before container exits / is removed
Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
parent
8cfd4cb39f
commit
6b8dfe4249
|
|
@ -629,6 +629,9 @@ class ContainerCollection(Collection):
|
||||||
(e.g. ``SIGINT``).
|
(e.g. ``SIGINT``).
|
||||||
storage_opt (dict): Storage driver options per container as a
|
storage_opt (dict): Storage driver options per container as a
|
||||||
key-value mapping.
|
key-value mapping.
|
||||||
|
stream (bool): If true and ``detach`` is false, return a log
|
||||||
|
generator instead of a string. Ignored if ``detach`` is true.
|
||||||
|
Default: ``False``.
|
||||||
sysctls (dict): Kernel parameters to set in the container.
|
sysctls (dict): Kernel parameters to set in the container.
|
||||||
tmpfs (dict): Temporary filesystems to mount, as a dictionary
|
tmpfs (dict): Temporary filesystems to mount, as a dictionary
|
||||||
mapping a path inside the container to options for that path.
|
mapping a path inside the container to options for that path.
|
||||||
|
|
@ -696,6 +699,7 @@ class ContainerCollection(Collection):
|
||||||
"""
|
"""
|
||||||
if isinstance(image, Image):
|
if isinstance(image, Image):
|
||||||
image = image.id
|
image = image.id
|
||||||
|
stream = kwargs.pop('stream', False)
|
||||||
detach = kwargs.pop("detach", False)
|
detach = kwargs.pop("detach", False)
|
||||||
if detach and remove:
|
if detach and remove:
|
||||||
if version_gte(self.client.api._version, '1.25'):
|
if version_gte(self.client.api._version, '1.25'):
|
||||||
|
|
@ -723,23 +727,28 @@ class ContainerCollection(Collection):
|
||||||
if detach:
|
if detach:
|
||||||
return container
|
return container
|
||||||
|
|
||||||
exit_status = container.wait()
|
|
||||||
if exit_status != 0:
|
|
||||||
stdout = False
|
|
||||||
stderr = True
|
|
||||||
|
|
||||||
logging_driver = container.attrs['HostConfig']['LogConfig']['Type']
|
logging_driver = container.attrs['HostConfig']['LogConfig']['Type']
|
||||||
|
|
||||||
|
out = None
|
||||||
if logging_driver == 'json-file' or logging_driver == 'journald':
|
if logging_driver == 'json-file' or logging_driver == 'journald':
|
||||||
out = container.logs(stdout=stdout, stderr=stderr)
|
out = container.logs(
|
||||||
else:
|
stdout=stdout, stderr=stderr, stream=True, follow=True
|
||||||
out = None
|
)
|
||||||
|
|
||||||
|
exit_status = container.wait()
|
||||||
|
if exit_status != 0:
|
||||||
|
out = container.logs(stdout=False, stderr=True)
|
||||||
|
|
||||||
if remove:
|
if remove:
|
||||||
container.remove()
|
container.remove()
|
||||||
if exit_status != 0:
|
if exit_status != 0:
|
||||||
raise ContainerError(container, exit_status, command, image, out)
|
raise ContainerError(
|
||||||
return out
|
container, exit_status, command, image, out
|
||||||
|
)
|
||||||
|
|
||||||
|
return out if stream or out is None else b''.join(
|
||||||
|
[line for line in out]
|
||||||
|
)
|
||||||
|
|
||||||
def create(self, image, command=None, **kwargs):
|
def create(self, image, command=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import docker
|
import docker
|
||||||
import tempfile
|
import tempfile
|
||||||
from .base import BaseIntegrationTest, TEST_API_VERSION
|
from .base import BaseIntegrationTest, TEST_API_VERSION
|
||||||
from ..helpers import random_name
|
from ..helpers import random_name, requires_api_version
|
||||||
|
|
||||||
|
|
||||||
class ContainerCollectionTest(BaseIntegrationTest):
|
class ContainerCollectionTest(BaseIntegrationTest):
|
||||||
|
|
@ -95,7 +95,7 @@ class ContainerCollectionTest(BaseIntegrationTest):
|
||||||
"alpine", "echo hello",
|
"alpine", "echo hello",
|
||||||
log_config=dict(type='none')
|
log_config=dict(type='none')
|
||||||
)
|
)
|
||||||
self.assertEqual(out, None)
|
assert out is None
|
||||||
|
|
||||||
def test_run_with_json_file_driver(self):
|
def test_run_with_json_file_driver(self):
|
||||||
client = docker.from_env(version=TEST_API_VERSION)
|
client = docker.from_env(version=TEST_API_VERSION)
|
||||||
|
|
@ -104,7 +104,24 @@ class ContainerCollectionTest(BaseIntegrationTest):
|
||||||
"alpine", "echo hello",
|
"alpine", "echo hello",
|
||||||
log_config=dict(type='json-file')
|
log_config=dict(type='json-file')
|
||||||
)
|
)
|
||||||
self.assertEqual(out, b'hello\n')
|
assert out == b'hello\n'
|
||||||
|
|
||||||
|
@requires_api_version('1.25')
|
||||||
|
def test_run_with_auto_remove(self):
|
||||||
|
client = docker.from_env(version=TEST_API_VERSION)
|
||||||
|
out = client.containers.run(
|
||||||
|
'alpine', 'echo hello', auto_remove=True
|
||||||
|
)
|
||||||
|
assert out == b'hello\n'
|
||||||
|
|
||||||
|
def test_run_with_streamed_logs(self):
|
||||||
|
client = docker.from_env(version=TEST_API_VERSION)
|
||||||
|
out = client.containers.run(
|
||||||
|
'alpine', 'sh -c "echo hello && echo world"', stream=True
|
||||||
|
)
|
||||||
|
logs = [line for line in out]
|
||||||
|
assert logs[0] == b'hello\n'
|
||||||
|
assert logs[1] == b'world\n'
|
||||||
|
|
||||||
def test_get(self):
|
def test_get(self):
|
||||||
client = docker.from_env(version=TEST_API_VERSION)
|
client = docker.from_env(version=TEST_API_VERSION)
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ def make_fake_api_client():
|
||||||
fake_api.get_fake_inspect_container()[1],
|
fake_api.get_fake_inspect_container()[1],
|
||||||
'inspect_image.return_value': fake_api.get_fake_inspect_image()[1],
|
'inspect_image.return_value': fake_api.get_fake_inspect_image()[1],
|
||||||
'inspect_network.return_value': fake_api.get_fake_network()[1],
|
'inspect_network.return_value': fake_api.get_fake_network()[1],
|
||||||
'logs.return_value': 'hello world\n',
|
'logs.return_value': [b'hello world\n'],
|
||||||
'networks.return_value': fake_api.get_fake_network_list()[1],
|
'networks.return_value': fake_api.get_fake_network_list()[1],
|
||||||
'start.return_value': None,
|
'start.return_value': None,
|
||||||
'wait.return_value': 0,
|
'wait.return_value': 0,
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class ContainerCollectionTest(unittest.TestCase):
|
||||||
client = make_fake_client()
|
client = make_fake_client()
|
||||||
out = client.containers.run("alpine", "echo hello world")
|
out = client.containers.run("alpine", "echo hello world")
|
||||||
|
|
||||||
assert out == 'hello world\n'
|
assert out == b'hello world\n'
|
||||||
|
|
||||||
client.api.create_container.assert_called_with(
|
client.api.create_container.assert_called_with(
|
||||||
image="alpine",
|
image="alpine",
|
||||||
|
|
@ -24,9 +24,8 @@ class ContainerCollectionTest(unittest.TestCase):
|
||||||
client.api.start.assert_called_with(FAKE_CONTAINER_ID)
|
client.api.start.assert_called_with(FAKE_CONTAINER_ID)
|
||||||
client.api.wait.assert_called_with(FAKE_CONTAINER_ID)
|
client.api.wait.assert_called_with(FAKE_CONTAINER_ID)
|
||||||
client.api.logs.assert_called_with(
|
client.api.logs.assert_called_with(
|
||||||
FAKE_CONTAINER_ID,
|
FAKE_CONTAINER_ID, stderr=False, stdout=True, stream=True,
|
||||||
stderr=False,
|
follow=True
|
||||||
stdout=True
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_create_container_args(self):
|
def test_create_container_args(self):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue