diff --git a/docker/models/containers.py b/docker/models/containers.py index 9c9e92c90f..4a7e9c1faf 100644 --- a/docker/models/containers.py +++ b/docker/models/containers.py @@ -38,10 +38,15 @@ def image(self): """ The image of the container. """ - image_id = self.attrs.get('ImageID', self.attrs['Image']) + image_id = self.attrs.get('ImageID') or self.attrs.get('Image') if image_id is None: return None - return self.client.images.get(image_id.split(':')[1]) + # ``ImageID`` is a digest; strip the algorithm prefix from it. Daemons + # that omit ``ImageID`` report a name such as ``busybox:latest`` in + # ``Image`` instead, which must not be split on its tag separator. + if image_id.startswith('sha256:'): + image_id = image_id[len('sha256:'):] + return self.client.images.get(image_id) @property def labels(self): diff --git a/tests/unit/models_containers_test.py b/tests/unit/models_containers_test.py index 0e2ae341a9..a2d14dcaae 100644 --- a/tests/unit/models_containers_test.py +++ b/tests/unit/models_containers_test.py @@ -725,6 +725,24 @@ def test_image(self): client = make_fake_client() container = client.containers.get(FAKE_CONTAINER_ID) assert container.image.id == FAKE_IMAGE_ID + # The container reports no 'ImageID', so the name in 'Image' is looked + # up as-is rather than being split on its tag separator. + client.api.inspect_image.assert_called_with('busybox:latest') + + def test_image_from_image_id(self): + client = make_fake_client() + container = client.containers.get(FAKE_CONTAINER_ID) + container.attrs['ImageID'] = FAKE_IMAGE_ID + assert container.image.id == FAKE_IMAGE_ID + client.api.inspect_image.assert_called_with( + FAKE_IMAGE_ID[len('sha256:'):] + ) + + def test_image_without_image_id_or_image(self): + client = make_fake_client() + container = client.containers.get(FAKE_CONTAINER_ID) + del container.attrs['Image'] + assert container.image is None def test_kill(self): client = make_fake_client()