Docker's Python SDK "container.start()" exit immediately

Question:

I want to create a docker container via the docker’s Python SDK.
The bash equivalence (which works on the cli) of what I am trying to achieve is as follows. (the image entry point is /bin/bash)

docker container create --name <container_name>-i --mount source=<src>,target=/project_data <image_name>

docker container start -i <container_name>

While this works on the Cli, after creating the container via the Python SDK and starting it, the container is exited shortly after, hence when I try to execute commands on the container I get an error which states that the container is not running.

container = client.containers.run("<image_name>", name="<container_name>", detach=True, volumes=volumes)

I wasn’t able to start the container in detached mode.
my goal eventually, after starting the container is to execute multiple cmd in the same container instance. i.e.

result = container.exec_run('ls')
result = container.exec_run('./run_scripts > out.txt')
result = container.exec_run('./run_scripts_2 > out.txt')

# some data processing
... <omitted> ...

# execute more scripts
result = container.exec_run('./run_scripts _3> out.txt')

When I try to run container.start(), the container is started but it is exited shortly after, hence when I try to execute container.exec_run function I get the following error:

---------------------------------------------------------------------------
HTTPError                                 Traceback (most recent call last)
File ~/miniconda3/envs/foldynamics/lib/python3.8/site-packages/docker/api/client.py:268, in APIClient._raise_for_status(self, response)
    267 try:
--> 268     response.raise_for_status()
    269 except requests.exceptions.HTTPError as e:

File ~/miniconda3/envs/foldynamics/lib/python3.8/site-packages/requests/models.py:1021, in Response.raise_for_status(self)
   1020 if http_error_msg:
-> 1021     raise HTTPError(http_error_msg, response=self)

HTTPError: 409 Client Error: Conflict for url: http+docker://localhost/v1.41/containers/43cb7fd5549053bf426ed3d39c1d4f5a982d329f7483e890604d0d5b2a38f7b1/exec

The above exception was the direct cause of the following exception:

APIError                                  Traceback (most recent call last)
Cell In[87], line 1
----> 1 result = container.exec_run("echo pwd", tty=True, detach=True)

File ~/miniconda3/envs/foldynamics/lib/python3.8/site-packages/docker/models/containers.py:193, in Container.exec_run(self, cmd, stdout, stderr, stdin, tty, privileged, user, detach, stream, socket, environment, workdir, demux)
    152 def exec_run(self, cmd, stdout=True, stderr=True, stdin=False, tty=False,
    153              privileged=False, user='', detach=False, stream=False,
    154              socket=False, environment=None, workdir=None, demux=False):
    155     """
    156     Run a command inside this container. Similar to
    157     ``docker exec``.
   (...)
    191             If the server returns an error.
    192     """
--> 193     resp = self.client.api.exec_create(
    194         self.id, cmd, stdout=stdout, stderr=stderr, stdin=stdin, tty=tty,
    195         privileged=privileged, user=user, environment=environment,
    196         workdir=workdir,
    197     )
    198     exec_output = self.client.api.exec_start(
    199         resp['Id'], detach=detach, tty=tty, stream=stream, socket=socket,
    200         demux=demux
    201     )
    202     if socket or stream:

File ~/miniconda3/envs/foldynamics/lib/python3.8/site-packages/docker/utils/decorators.py:19, in check_resource.<locals>.decorator.<locals>.wrapped(self, resource_id, *args, **kwargs)
     15 if not resource_id:
     16     raise errors.NullResource(
     17         'Resource ID was not provided'
     18     )
---> 19 return f(self, resource_id, *args, **kwargs)

File ~/miniconda3/envs/foldynamics/lib/python3.8/site-packages/docker/api/exec_api.py:78, in ExecApiMixin.exec_create(self, container, cmd, stdout, stderr, stdin, tty, privileged, user, environment, workdir, detach_keys)
     76 url = self._url('/containers/{0}/exec', container)
     77 res = self._post_json(url, data=data)
---> 78 return self._result(res, True)

File ~/miniconda3/envs/foldynamics/lib/python3.8/site-packages/docker/api/client.py:274, in APIClient._result(self, response, json, binary)
    272 def _result(self, response, json=False, binary=False):
    273     assert not (json and binary)
--> 274     self._raise_for_status(response)
    276     if json:
    277         return response.json()

File ~/miniconda3/envs/foldynamics/lib/python3.8/site-packages/docker/api/client.py:270, in APIClient._raise_for_status(self, response)
    268     response.raise_for_status()
    269 except requests.exceptions.HTTPError as e:
--> 270     raise create_api_error_from_http_exception(e) from e

File ~/miniconda3/envs/foldynamics/lib/python3.8/site-packages/docker/errors.py:39, in create_api_error_from_http_exception(e)
     37     else:
     38         cls = NotFound
---> 39 raise cls(e, response=response, explanation=explanation) from e

APIError: 409 Client Error for http+docker://localhost/v1.41/containers/43cb7fd5549053bf426ed3d39c1d4f5a982d329f7483e890604d0d5b2a38f7b1/exec: Conflict ("Container 43cb7fd5549053bf426ed3d39c1d4f5a982d329f7483e890604d0d5b2a38f7b1 is not running")

Asked By: Ido

||

Answers:

The docker-py repository seems to have had a issue with the same issue, this addresses this.

Basically, the sdk doesn’t implement interactive feature. The workaround is to pass stdin_open = True, tty = True to the container = client.containers.run command.

E.g. container = client.containers.run("<image_name>", name="<container_name>", stdin_open = True, tty = True detach=True, volumes=volumes)

Answered By: Captain Levi
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.