-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Open
Description
I reported this to moby/moby (moby/moby#50614), but since it also affects Docker SDK for Python, I'd like to report it here as well.
Reproducer from moby/moby#50614 (comment):
-
Run on shell:
docker run --name registry --publish 5000:5000 --detach registry:2.8.3 docker pull hello-world:latest docker tag hello-world:latest localhost:5000/hello-world:latest
-
Run in Python, with Docker SDK for Python available:
import docker list(docker.APIClient().push("localhost:5000/hello-world:latest", stream=True, decode=True))
This results in:
Traceback (most recent call last):
File "/usr/lib/python3.13/http/client.py", line 579, in _get_chunk_left
chunk_left = self._read_next_chunk_size()
File "/usr/lib/python3.13/http/client.py", line 546, in _read_next_chunk_size
return int(line, 16)
ValueError: invalid literal for int() with base 16: b''
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.13/http/client.py", line 597, in _read_chunked
while (chunk_left := self._get_chunk_left()) is not None:
~~~~~~~~~~~~~~~~~~~~^^
File "/usr/lib/python3.13/http/client.py", line 581, in _get_chunk_left
raise IncompleteRead(b'')
http.client.IncompleteRead: IncompleteRead(0 bytes read)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/lib/python3.13/site-packages/urllib3/response.py", line 779, in _error_catcher
yield
File "/usr/lib/python3.13/site-packages/urllib3/response.py", line 904, in _raw_read
data = self._fp_read(amt, read1=read1) if not fp_closed else b""
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.13/site-packages/urllib3/response.py", line 887, in _fp_read
return self._fp.read(amt) if amt is not None else self._fp.read()
~~~~~~~~~~~~~^^^^^
File "/usr/lib/python3.13/http/client.py", line 473, in read
return self._read_chunked(amt)
~~~~~~~~~~~~~~~~~~^^^^^
File "/usr/lib/python3.13/http/client.py", line 609, in _read_chunked
raise IncompleteRead(b''.join(value)) from exc
http.client.IncompleteRead: IncompleteRead(0 bytes read)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
list(docker.APIClient().push("localhost:5000/hello-world:latest", stream=True, decode=True))
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/docker-py/docker/api/client.py", line 360, in _stream_helper
yield from json_stream(self._stream_helper(response, False))
File "/path/to/docker-py/docker/utils/json_stream.py", line 60, in split_buffer
for data in stream_as_text(stream):
~~~~~~~~~~~~~~^^^^^^^^
File "/path/to/docker-py/docker/utils/json_stream.py", line 16, in stream_as_text
for data in stream:
^^^^^^
File "/path/to/docker-py/docker/api/client.py", line 365, in _stream_helper
data = reader.read(1)
File "/usr/lib/python3.13/site-packages/urllib3/response.py", line 980, in read
data = self._raw_read(amt)
File "/usr/lib/python3.13/site-packages/urllib3/response.py", line 903, in _raw_read
with self._error_catcher():
~~~~~~~~~~~~~~~~~~~^^
File "/usr/lib/python3.13/contextlib.py", line 162, in __exit__
self.gen.throw(value)
~~~~~~~~~~~~~~^^^^^^^
File "/usr/lib/python3.13/site-packages/urllib3/response.py", line 806, in _error_catcher
raise ProtocolError(f"Connection broken: {e!r}", e) from e
urllib3.exceptions.ProtocolError: ('Connection broken: IncompleteRead(0 bytes read)', IncompleteRead(0 bytes read))
A simple workaround is to pass auth_config={}
:
list(docker.APIClient().push("localhost:5000/hello-world:latest", stream=True, decode=True, auth_config={}))
This bug can be fixed on Docker SDK for Python's side with the following patch:
diff --git a/docker/api/image.py b/docker/api/image.py
index 85109473..6e28894e 100644
--- a/docker/api/image.py
+++ b/docker/api/image.py
@@ -484,6 +484,8 @@ class ImageApiMixin:
header = auth.get_config_header(self, registry)
if header:
headers['X-Registry-Auth'] = header
+ else:
+ headers['X-Registry-Auth'] = auth.encode_header({})
else:
log.debug('Sending supplied auth config')
headers['X-Registry-Auth'] = auth.encode_header(auth_config)
heitorPB
Metadata
Metadata
Assignees
Labels
No labels