Home > Back-end >  testing docker image using python
testing docker image using python

Time:06-01

I have a python code for testing my docker images.

import docker
client = docker.from_env()
container = client.containers.run("my_image", ["python  --version"], auto_remove = True)
print("done!")

I get the following error:

Traceback (most recent call last):
  File "/home/user1/miniconda3/envs/py_test/lib/python3.10/site-packages/docker/api/client.py", line 268, in _raise_for_status
    response.raise_for_status()
  File "/home/user1/miniconda3/envs/py_test/lib/python3.10/site-packages/requests/models.py", line 960, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: http docker://localhost/v1.41/containers/19b94bfbebc0dbaaf2864b8cc72d1c597fe108a3ddd9bf45b58b8d3c825cb3e6/start

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/user1/tmp_python/test.py", line 5, in <module>
    container = client.containers.run("my_image", ["python  --version"], auto_remove = True)
  File "/home/user1/miniconda3/envs/py_test/lib/python3.10/site-packages/docker/models/containers.py", line 826, in run
    container.start()
  File "/home/user1/miniconda3/envs/py_test/lib/python3.10/site-packages/docker/models/containers.py", line 404, in start
    return self.client.api.start(self.id, **kwargs)
  File "/home/user1/miniconda3/envs/py_test/lib/python3.10/site-packages/docker/utils/decorators.py", line 19, in wrapped
    return f(self, resource_id, *args, **kwargs)
  File "/home/user1/miniconda3/envs/py_test/lib/python3.10/site-packages/docker/api/container.py", line 1109, in start
    self._raise_for_status(res)
  File "/home/user1/miniconda3/envs/py_test/lib/python3.10/site-packages/docker/api/client.py", line 270, in _raise_for_status
    raise create_api_error_from_http_exception(e)
  File "/home/user1/miniconda3/envs/py_test/lib/python3.10/site-packages/docker/errors.py", line 31, in create_api_error_from_http_exception
    raise cls(e, response=response, explanation=explanation)
docker.errors.APIError: 400 Client Error for http docker://localhost/v1.41/containers/19b94bfbebc0dbaaf2864b8cc72d1c597fe108a3ddd9bf45b58b8d3c825cb3e6/start: Bad Request ("failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "python  --version": executable file not found in $PATH: unknown")

however, when I run manually my image, I can get the python version:

docker run -it my_image
(base) root@6f9d163cc547:/# python --version
Python 3.9.12
(base) root@6f9d163cc547:/# exit
exit

CodePudding user response:

This error:

unable to start container process: exec: "python  --version": executable file not found in $PATH: unknown")

Means you should be passing a list of arguments:

client.containers.run('myimage', ['python', '--version'])

Or a single string:

client.containers.run('myimage', 'python --version')

With your current code, Docker is trying to find an executable file named literally python --version. This is exactly what you see with RUN and CMD statements in a Dockerfile: a single string is executed using /bin/sh -c, while a list argument is executed directly (e.g., passed as arguments to execve()).

This works just fine:

import docker
client = docker.from_env()
container = client.containers.run('docker.io/python:3', ['python', '--version'])
print("done!")

I find that in my setup, using auto_remove=True results in a different error, but that's unrelated to what you show in your question. @KrerkkiatChusap has some suggestions for that issue in their answer.

CodePudding user response:

You code seems to be

container = client.containers.run("my_image", ["python  --version"], auto_remove = True)
container.start()

The docker run command will create and start the container, so there is no need for container.start().

The next problem is then when auto_remove=True, the container will be destroyed after it finished the execution, and the library have a hard time obtaining the output from destroyed container. Also, without detach=True, the output (byte) will be returned instead of a container object (so calling .start() on it will not make sense).

Instead, you can obtain the handle with detach=True and manually remove the container after you get the output with container.logs().

import docker
client = docker.from_env()
# The command here is implicitly fixed by larsks' answer.
container = client.containers.run("my_image", ["python", "--version"], detach=True)
output_bytes = container.logs()
# Since the container is already exited, you can skip the `.stop()`.
container.remove()
  • Related