Public Access
DEVX-155: fix: prefer /run/host-docker.sock over inner dockerd
The start_docker.py script was checking /var/run/docker.sock first, which inside CI containers is an inner dockerd (v29.5.3) with data root on the container's 38G overlay (often 100% full). When _get_docker_free_bytes() returned 0 (data root path not accessible from inside container), the script assumed it was the host Docker with plenty of space and returned True immediately — without trying the host's rootless Docker socket at /run/host-docker.sock. Fix: try /run/host-docker.sock FIRST (before /var/run/docker.sock). The host socket is mounted by the gitea runner config and has access to the host's full filesystem (455G). Only trust free_bytes == 0 (= data root not accessible from container) for /run/host-docker.sock, since the host's root dir is genuinely outside the container. For other sockets (inner dockerd), free_bytes == 0 means the path doesn't exist inside the container — don't trust it. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent
1470cdae27
commit
0e25810b84
@@ -157,60 +157,41 @@ def start_docker_daemon(timeout: int = DEFAULT_TIMEOUT) -> bool:
|
||||
|
||||
Tries sockets in this order, preferring ones with enough disk space:
|
||||
|
||||
1. Host socket (``/var/run/docker.sock``) — if it has ≥ ``MIN_FREE_BYTES``
|
||||
free space, use it immediately.
|
||||
2. Rootless sockets (``/run/user/*/docker.sock``) — if the host socket
|
||||
has insufficient space, try rootless sockets which may have access
|
||||
to the host's full filesystem.
|
||||
3. Local ``dockerd`` with vfs storage driver — last resort.
|
||||
1. Host rootless socket (``/run/host-docker.sock``) — mounted by the
|
||||
gitea runner config, has access to the host's full filesystem
|
||||
(e.g. 455 GB). Preferred over the inner dockerd.
|
||||
2. Default socket (``/var/run/docker.sock``) — may be an inner dockerd
|
||||
started by the CI image (v29.5.3) with data root on the container's
|
||||
limited overlay (e.g. 38 GB, often 100 % full).
|
||||
3. Other rootless sockets (``/run/user/*/docker.sock``).
|
||||
4. Local ``dockerd`` with vfs storage driver — last resort.
|
||||
|
||||
Returns ``True`` if Docker is ready, ``False`` if it failed to
|
||||
start within the timeout.
|
||||
"""
|
||||
# Point Docker CLI and Python library to the socket explicitly
|
||||
os.environ["DOCKER_HOST"] = f"unix://{DOCKER_SOCK}"
|
||||
|
||||
# Diagnose socket state
|
||||
click.echo("--- Docker socket diagnostics ---")
|
||||
_diagnose_socket()
|
||||
click.echo("--- End diagnostics ---")
|
||||
|
||||
# Check if host Docker is already available
|
||||
if is_docker_ready():
|
||||
free_bytes = _get_docker_free_bytes()
|
||||
free_gb = free_bytes / 1024**3
|
||||
click.echo(f"Docker daemon already running (free space: {free_gb:.1f} GB)")
|
||||
if free_bytes >= MIN_FREE_BYTES:
|
||||
return True
|
||||
# If free_bytes is 0, the Docker root dir is on the host filesystem
|
||||
# (not accessible from inside the container). The host Docker has
|
||||
# access to the full 455G disk — always use it in that case.
|
||||
if free_bytes == 0:
|
||||
click.echo("Host Docker root dir not accessible from container, using host Docker")
|
||||
return True
|
||||
click.echo(
|
||||
f"Host Docker has only {free_gb:.1f} GB free "
|
||||
f"(need ≥ {MIN_FREE_BYTES / 1024**3:.0f} GB), trying rootless sockets..."
|
||||
)
|
||||
else:
|
||||
click.echo("Host Docker not available, trying rootless sockets...")
|
||||
|
||||
# Collect candidate rootless sockets
|
||||
# Collect candidate sockets in priority order.
|
||||
# The host's rootless Docker socket (mounted at /run/host-docker.sock
|
||||
# by the gitea runner config) is preferred — it has access to the
|
||||
# host's full filesystem instead of the container's limited overlay.
|
||||
candidates: list[str] = []
|
||||
# The host Docker socket is mounted by the gitea_runner config.
|
||||
# This is the preferred candidate — it has access to the host's
|
||||
# full filesystem instead of the container's limited overlay.
|
||||
if os.path.exists(HOST_DOCKER_SOCK):
|
||||
candidates.append(HOST_DOCKER_SOCK)
|
||||
if os.path.exists(DOCKER_SOCK):
|
||||
candidates.append(DOCKER_SOCK)
|
||||
if os.path.exists(ROOTLESS_SOCK):
|
||||
candidates.append(ROOTLESS_SOCK)
|
||||
for sock in sorted(glob.glob("/run/user/*/docker.sock")):
|
||||
if sock not in candidates:
|
||||
candidates.append(sock)
|
||||
|
||||
# Try each rootless socket — prefer one with enough free space
|
||||
# Try each candidate socket — prefer one with enough free space
|
||||
for sock in candidates:
|
||||
click.echo(f"Trying rootless socket: {sock}")
|
||||
click.echo(f"Trying socket: {sock}")
|
||||
if not _try_socket(sock):
|
||||
continue
|
||||
free_bytes = _get_docker_free_bytes()
|
||||
@@ -219,10 +200,20 @@ def start_docker_daemon(timeout: int = DEFAULT_TIMEOUT) -> bool:
|
||||
if free_bytes >= MIN_FREE_BYTES:
|
||||
click.echo(_("Docker daemon already running"))
|
||||
return True
|
||||
# If free_bytes is 0, the Docker root dir is on the host filesystem
|
||||
# (not accessible from inside the container). This is expected for
|
||||
# the host's rootless Docker — it has the full host disk.
|
||||
# Only trust this for /run/host-docker.sock (known host socket).
|
||||
# For other sockets (e.g. inner dockerd), free_bytes == 0 means
|
||||
# the data root path doesn't exist inside the container — the
|
||||
# inner dockerd may be using the container's full overlay.
|
||||
if free_bytes == 0 and sock == HOST_DOCKER_SOCK:
|
||||
click.echo("Host rootless Docker root dir not accessible from container, using it")
|
||||
return True
|
||||
click.echo(f" Insufficient space ({free_gb:.1f} GB), trying next...")
|
||||
|
||||
# If we found a working rootless socket but with low space, use it
|
||||
# as a fallback (better than nothing).
|
||||
# If we found a working socket but with low space, use the last
|
||||
# one as a fallback (better than nothing).
|
||||
for sock in reversed(candidates):
|
||||
if _try_socket(sock):
|
||||
click.echo(f"Using low-space fallback: {sock}")
|
||||
|
||||
Reference in New Issue
Block a user