feat: keep Docker images on computes consistent with the controller host

Only relying on the image name lets a moved tag (e.g. a newer :latest)
silently serve stale content from a compute that already has an image
under the same name. When creating a Docker node, the controller now
pins the image id (Id from the Docker daemon on the controller host)
into the create payload. A compute holding a different image under the
same tag reports the image as missing, which routes it through the
image sync added by the previous commit and re-aligns the tag.

No new template fields or database changes: the controller host daemon
remains the source of truth and the pin is resolved per creation. When
the image is not available on the controller host the pin is omitted
and behavior is unchanged (the compute pulls from the repository).
This commit is contained in:
YueGuobin committed 2026-09-14 00:55:18 +08:00
1 parent c477812332
commit be62e8c022
6 files changed
+101 -1

No files matched your search

+24
View File
@@ -465,6 +465,7 @@ class Node:
data["node_id"] = self._id
if self._node_type == "docker":
timeout = None
await self._add_docker_image_digest(data)
else:
timeout = 1200
trial = 0
@@ -788,6 +789,29 @@ class Node:
return True
return False
async def _add_docker_image_digest(self, data):
"""
Pin the Docker image of a node to the image id found on the Docker daemon
of the controller host, so that a compute holding a different image under
the same tag (e.g. a moved :latest) gets it re-synced instead of silently
reusing the stale copy. Not set when the image is not on the controller host.
"""
from gns3server.compute.docker import Docker
from gns3server.compute.docker.docker_error import DockerError
image = data.get("image")
if not image:
return
try:
image_info = await Docker.instance().query("GET", f"images/{image}/json")
except DockerError:
# not available on the controller host: nothing to pin against
return
image_id = image_info.get("Id")
if image_id:
data["image_digest"] = image_id
async def _sync_missing_docker_image(self, image):
"""
Export a Docker image from the Docker daemon on the controller host and