diff --git a/docker/errors.py b/docker/errors.py index d03e10f69..8b2762abe 100644 --- a/docker/errors.py +++ b/docker/errors.py @@ -150,6 +150,19 @@ def __init__(self, container, exit_status, command, image, stderr): ) +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 4795523a1..99d614b7d 100644 --- a/docker/models/containers.py +++ b/docker/models/containers.py @@ -5,7 +5,9 @@ from ..api import APIClient from ..constants import DEFAULT_DATA_CHUNK_SIZE from ..errors import ( + APIError, ContainerError, + ContainerStartError, DockerException, ImageNotFound, NotFound, @@ -842,6 +844,8 @@ def run(self, image, command=None, stdout=True, stderr=False, :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` @@ -880,7 +884,17 @@ def run(self, image, command=None, stdout=True, stderr=False, 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 476263ae2..478c1bd34 100644 --- a/tests/integration/models_containers_test.py +++ b/tests/integration/models_containers_test.py @@ -158,13 +158,13 @@ def test_run_with_networking_config_with_undeclared_network(self): ), } - 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()