Hi all,
First of all thanks for the continued work on this SDK -- it's been very useful for making quick work of some local e2e tests. I ran into this problem while a colleague was trying to run some tests that "ran on my machine".
Issue
TL;DR - If you do not have the image you want to run pulled (for example minio/minio), and you have a configuration error (such as an invalid mount specified), the containers.run command will hang (due to one or more silent failures) -- the container will never be pulled, the program will not continue past or error, and the underlying mount problem won't cause an error either -- to the end user it just looks like a hang with no output.
The first progress we were able to make was installing the minio/minio image with the docker CLI directly -- this got rid of the missing image problem (maybe docker-py doesn't fetch missing automatically, I thought this was docker run standard behavior), and exposed an invalid mount configuration issue. The mount configuration issue has to do with how OSX temp directories are created (once the error was visible it was easy to fix):
E docker.errors.APIError: 502 Server Error: Bad Gateway ("b'Mounts denied: \r\nThe path /var/folders/wj/x6b1l_7s1yg977rxrrjpsc8h0000gn/T/project-9dk0ewdx\r\nis not shared from OS X and is not known to Docker.\r\nYou can configure shared paths from Docker -> Preferences... -> File Sharing.\r\nSee https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info.\r\n.'")
this issue is due to namespacing on OSX, and the interaction with python's tempfile functionality:
import tempfile
# Create tmp local directory for minio to use
d = tempfile.mkdtemp(prefix="e2e-minio") # /var/folders/wj/x6b1l_7s1yg977rxrrjpsc8h0000gn/T/project-minio9dk0ewdx
The fact that this folder can't be used by the spawned docker container is more of a gotcha more than a bug (maybe both of these issues are), so I'm not sure exactly what should be done (maybe it's just adding more documentation).
The main issue is the missing container appearing as a hang (which might have been exacerbated by the invalid mount issue), with no output (error or otherwise) returned to the user.
Reproduction
Steps:
docker (native) 18.02 (latest as of 02/16) on OSXtmpfile.mkdtempdocker.from_env()docker_client.containers.run w/ a mounted directory that is the temp directoryI can reproduce this w/ docker-py 4.1.0 on linux without any mounts or temp files:
❯ python
Python 2.7.15+ (default, Oct 7 2019, 17:39:04)
[GCC 7.4.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import docker
>>> docker.from_env().containers.run('ubuntu', 'ls')
wait for a few minutes... nothing happens... then I hit ^C to get this stack trace:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/radix/.virtualenvs/devlandia/local/lib/python2.7/site-packages/docker/models/containers.py", line 805, in run
self.client.images.pull(image, platform=platform)
File "/home/radix/.virtualenvs/devlandia/local/lib/python2.7/site-packages/docker/models/images.py", line 447, in pull
for _ in pull_log:
File "/home/radix/.virtualenvs/devlandia/local/lib/python2.7/site-packages/docker/api/client.py", line 345, in _stream_helper
data = reader.read(1)
File "/home/radix/.virtualenvs/devlandia/local/lib/python2.7/site-packages/urllib3/response.py", line 444, in read data = self._fp.read(amt)
File "/usr/lib/python2.7/httplib.py", line 583, in read
return self._read_chunked(amt)
File "/usr/lib/python2.7/httplib.py", line 625, in _read_chunked
line = self.fp.readline(_MAXLINE + 1)
File "/usr/lib/python2.7/socket.py", line 480, in readline
data = self._sock.recv(self._rbufsize)
KeyboardInterrupt
turns out that this also happens when I just try to pull explicitly:
>>> docker.from_env().images.pull('ubuntu')
ctrl-C:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/radix/.virtualenvs/devlandia/local/lib/python2.7/site-packages/docker/models/images.py", line 447, in pull
for _ in pull_log:
File "/home/radix/.virtualenvs/devlandia/local/lib/python2.7/site-packages/docker/api/client.py", line 345, in _stream_helper
data = reader.read(1)
File "/home/radix/.virtualenvs/devlandia/local/lib/python2.7/site-packages/urllib3/response.py", line 444, in read
data = self._fp.read(amt)
File "/usr/lib/python2.7/httplib.py", line 583, in read
return self._read_chunked(amt)
File "/usr/lib/python2.7/httplib.py", line 625, in _read_chunked
line = self.fp.readline(_MAXLINE + 1)
File "/usr/lib/python2.7/socket.py", line 480, in readline
data = self._sock.recv(self._rbufsize)
KeyboardInterrupt
Ok, it seems that my docker.from_env.images.pull('ubuntu') is trying to download ALL of the ubuntu images. Same with containers.run. This is ONLY happening when there are no matching images in the first place.
with a containers.run('ubuntu', 'ls') running in another terminal...
❯ docker images|grep ubuntu
ubuntu 12.04 5b117edd0b76 2 years ago 104MB
ubuntu 12.04.5 5b117edd0b76 2 years ago 104MB
ubuntu 10.04 e21dbcc7c9de 5 years ago 183MB
❯ docker images|grep ubuntu
ubuntu 12.04 5b117edd0b76 2 years ago 104MB
ubuntu 12.04.5 5b117edd0b76 2 years ago 104MB
ubuntu 12.10 3e314f95dcac 5 years ago 172MB
ubuntu 13.04 a58cd502f927 5 years ago 169MB
ubuntu 10.04 e21dbcc7c9de 5 years ago 183MB
❯ docker images|grep ubuntu
ubuntu 12.04 5b117edd0b76 2 years ago 104MB
ubuntu 12.04.5 5b117edd0b76 2 years ago 104MB
ubuntu 12.10 3e314f95dcac 5 years ago 172MB
ubuntu 13.04 a58cd502f927 5 years ago 169MB
ubuntu 13.10 7f020f7bf345 5 years ago 185MB
ubuntu 10.04 e21dbcc7c9de 5 years ago 183MB
it keeps growing, and growing...
If the default is for docker-py to download all tags from images (if it can't find the image locally), then that would certainly explain it
If the default is for
docker-pyto download all tags from images (if it can't find the image locally), then that would certainly explain it
That's right.
According to docker engine documentation, if no tag is defined, it will pull all the images.
Tag or digest. If empty when pulling an image, this causes all tags for the given image to be pulled.
https://docs.docker.com/engine/api/v1.40/#operation/ImageCreate
Thanks for this, new to Docker and this took way to much time to figure out. Seems a simple update to the docs is in order https://docs.docker.com/engine/api/sdk/examples/
import docker
client = docker.from_env()
print client.containers.run("alpine", ["echo", "hello", "world"])
to
import docker
client = docker.from_env()
print client.containers.run("alpine:latest", ["echo", "hello", "world"])
Edit:
Further to the above, pulling a remote image hangs even with the above. Logging in first works
r = client.login(username="xxxx", password="yyyy")
Thanks to the docs. I pulled entire library of ubuntu image.
@shinebayar-g Me too!
Most helpful comment
Thanks for this, new to Docker and this took way to much time to figure out. Seems a simple update to the docs is in order https://docs.docker.com/engine/api/sdk/examples/
to
Edit:
Further to the above, pulling a remote image hangs even with the above. Logging in first works