fix: recreate tunnel uses container IP directly for reliable connectivity
Old instances may have auto-generated Docker Compose container names that don't match instance.name.lower(), causing DNS resolution failures for the tunnel. Also, old instances may not be on the backend network. - apps/api/src/services/docker.py: add get_container_ip_on_network() and is_container_on_network() helpers - apps/api/src/services/tunnel.py: start_tunnel() and recreate_tunnel() now accept an optional target_url parameter to override the default name-based URL - apps/api/src/api/tool_instances.py: recreate_tunnel_endpoint now: 1. Looks up the tool container (by stored container_id or name) 2. Ensures it's connected to the backend network 3. Gets the container's IP on that network 4. Passes the IP as the explicit tunnel target This guarantees the tunnel can reach the tool container regardless of naming or network state. Quality gates: ruff clean
This commit is contained in:
@@ -286,6 +286,66 @@ def connect_container_to_network(
|
||||
return result.returncode == 0
|
||||
|
||||
|
||||
def get_container_ip_on_network(
|
||||
container_id: str, network_name: str | None = None
|
||||
) -> str | None:
|
||||
"""Get a container's IP address on a specific Docker network.
|
||||
|
||||
Args:
|
||||
container_id: Docker container ID or name.
|
||||
network_name: Network name. If None, auto-detects from the API container.
|
||||
|
||||
Returns:
|
||||
IP address string, or None if the container is not on that network.
|
||||
"""
|
||||
if network_name is None:
|
||||
network_name = get_backend_network_name()
|
||||
result = subprocess.run(
|
||||
[
|
||||
"docker",
|
||||
"inspect",
|
||||
"-f",
|
||||
f"{{{{.NetworkSettings.Networks.{network_name}.IPAddress}}}}",
|
||||
container_id,
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
ip = result.stdout.strip()
|
||||
if ip and ip != "<no value>":
|
||||
return ip
|
||||
return None
|
||||
|
||||
|
||||
def is_container_on_network(
|
||||
container_id: str, network_name: str | None = None
|
||||
) -> bool:
|
||||
"""Check whether a container is already attached to a Docker network.
|
||||
|
||||
Args:
|
||||
container_id: Docker container ID or name.
|
||||
network_name: Network name. If None, auto-detects from the API container.
|
||||
|
||||
Returns:
|
||||
True if the container is on the network.
|
||||
"""
|
||||
if network_name is None:
|
||||
network_name = get_backend_network_name()
|
||||
result = subprocess.run(
|
||||
[
|
||||
"docker",
|
||||
"inspect",
|
||||
"-f",
|
||||
f"{{{{.NetworkSettings.Networks.{network_name}}}}}",
|
||||
container_id,
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
return result.returncode == 0 and "<no value>" not in result.stdout
|
||||
|
||||
|
||||
def get_container_status(container_id: str) -> dict[str, Any]:
|
||||
"""Get the status of a Docker container.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user