Skip to content

feat(runtime): resolve sandbox ports over a shared Docker network#775

Merged
0xallam merged 2 commits into
mainfrom
devin/1784136964-docker-network-sandbox
Jul 15, 2026
Merged

feat(runtime): resolve sandbox ports over a shared Docker network#775
0xallam merged 2 commits into
mainfrom
devin/1784136964-docker-network-sandbox

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Summary

Lets the Docker runtime work when the orchestrator itself runs inside a container (Compose, DinD, etc.) rather than on the Docker host.

Today the SDK publishes each sandbox's exposed ports to the host loopback and resolves them at 127.0.0.1:<host-port>. That only works if the orchestrator process shares the host's network namespace. When the orchestrator is a sibling container, 127.0.0.1 is its own loopback, so it can't reach the sandbox's Caido proxy and bootstrap fails.

New opt-in env STRIX_DOCKER_SANDBOX_NETWORK:

  • unset (default): unchanged — sandboxes join the default bridge, ports are host-published and resolved at 127.0.0.1.
  • set to a user-defined network name: the sandbox container joins that network, the (now unnecessary) host port-publish is skipped, and exposed ports resolve to the container's address on that network. A sibling orchestrator attached to the same network then reaches the sandbox container-to-container.

Two small pieces in strix/runtime/docker_client.py:

def _apply_sandbox_network(create_kwargs):        # in _create_container
    network = _sandbox_network()
    if network:
        create_kwargs["network"] = network
        create_kwargs.pop("ports", None)           # no host publish needed

class StrixDockerSandboxSession(DockerSandboxSession):
    async def _resolve_exposed_port(self, port):   # -> container IP on the network
        self._container.reload()
        ip = attrs["NetworkSettings"]["Networks"][self.sandbox_network]["IPAddress"]
        return ExposedPortEndpoint(host=ip, port=port, tls=False)

The SDK chooses the session class inside its own create() with no injection hook, so StrixDockerSandboxClient.create() calls super().create() and then swaps the resolver onto the returned session only when a network is configured — no re-copy of the SDK body:

async def create(self, **kwargs):
    session = await super().create(**kwargs)
    network = _sandbox_network()
    inner = session._inner
    if network and isinstance(inner, DockerSandboxSession):
        inner.__class__ = StrixDockerSandboxSession
        cast("StrixDockerSandboxSession", inner).sandbox_network = network
    return session

Missing/unresolvable network membership raises the SDK's typed ExposedPortUnavailableError.

Test

  • uv run pytest — 248 passed.
  • Pre-commit (ruff-lint, ruff-format, mypy, bandit) clean.

Link to Devin session: https://app.devin.ai/sessions/54414ea3ecb34ade9189534e5c690969
Requested by: @0xallam

…etwork

Add STRIX_DOCKER_SANDBOX_NETWORK: when set, sandbox containers join that
user-defined network and exposed ports resolve to the container's address
on it, instead of a host-published 127.0.0.1 port. This lets the
orchestrator run as a sibling container (e.g. Compose / DinD) rather than
on the Docker host. Unset preserves the existing host-loopback behavior.
@0xallam 0xallam self-assigned this Jul 15, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@greptile-apps

greptile-apps Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR lets containerized orchestrators reach Docker sandboxes over a shared network. The main changes are:

  • Adds an opt-in Docker sandbox network setting.
  • Skips host port publishing when the shared network is enabled.
  • Resolves exposed ports from the container’s network address.
  • Supports both IPv4 and IPv6 network addresses.
  • Returns typed errors when the network address is unavailable.

Confidence Score: 5/5

This looks safe to merge.

  • The IPv6 fallback addresses the reported failure for IPv6-only Docker networks.
  • IPv6 literals are bracketed for the downstream URL construction.
  • No blocking issue was found in the updated code.

Important Files Changed

Filename Overview
strix/runtime/docker_client.py Adds shared-network container creation and exposed-port resolution with IPv4 and IPv6 support.

Reviews (2): Last reviewed commit: "fix(runtime): resolve IPv6-only sandbox ..." | Re-trigger Greptile

Comment thread strix/runtime/docker_client.py Outdated
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

@greptile

@0xallam
0xallam merged commit 914207f into main Jul 15, 2026
2 checks passed
@0xallam
0xallam deleted the devin/1784136964-docker-network-sandbox branch July 15, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant