diff --git a/docker/errors.py b/docker/errors.py index d03e10f6..8b2762ab 100644 --- a/docker/errors.py +++ b/docker/errors.py @@ -150,6 +150,19 @@ class ContainerError(DockerException): ) +class ContainerStartError(DockerException): + """ + Represents a container that has failed to start. + """ + def __init__(self, container, reason): + self.container = container + self.msg = reason + + super().__init__( + f"Container '{container.short_id}' failed to start: {reason}" + ) + + class StreamParseError(RuntimeError): def __init__(self, reason): self.msg = reason diff --git a/docker/models/containers.py b/docker/models/containers.py index 9c9e92c9..971e3f9c 100644 --- a/docker/models/containers.py +++ b/docker/models/containers.py @@ -5,7 +5,9 @@ from collections import namedtuple from ..api import APIClient from ..constants import DEFAULT_DATA_CHUNK_SIZE from ..errors import ( + APIError, ContainerError, + ContainerStartError, DockerException, ImageNotFound, NotFound, @@ -843,6 +845,8 @@ class ContainerCollection(Collection): :py:class:`docker.errors.ContainerError` If the container exits with a non-zero exit code and ``detach`` is ``False``. + :py:class:`docker.errors.ContainerStartError` + If the container fails to start. :py:class:`docker.errors.ImageNotFound` If the specified image does not exist. :py:class:`docker.errors.APIError` @@ -881,7 +885,17 @@ class ContainerCollection(Collection): container = self.create(image=image, command=command, detach=detach, **kwargs) - container.start() + try: + container.start() + except APIError as e: + if remove: + container.remove() + + if e.explanation: + error = e.explanation + else: + error = e + raise ContainerStartError(container, error) from e if detach: return container diff --git a/tests/integration/models_containers_test.py b/tests/integration/models_containers_test.py index 87274559..6f9b8b13 100644 --- a/tests/integration/models_containers_test.py +++ b/tests/integration/models_containers_test.py @@ -157,13 +157,13 @@ class ContainerCollectionTest(BaseIntegrationTest): ), } - with pytest.raises(docker.errors.APIError): - container = client.containers.run( + with pytest.raises(docker.errors.ContainerStartError) as err: + client.containers.run( 'alpine', 'echo hello world', network=net_name, networking_config=networking_config, detach=True ) - self.tmp_containers.append(container.id) + self.tmp_containers.append(err.container.id) def test_run_with_networking_config_only_undeclared_network(self): net_name = random_name()