[wanda] Allow selecting the network for image builds - #500
Conversation
A wanda step runs directly on the agent rather than in a container, so a service running on that agent is outside the build's own network namespace and unreachable from a RUN. That is the gap behind ray-project/ray's package-mirror work: the images it builds cannot reach the index proxy the agent runs, and the address-based workaround failed -- pointing a build at the docker bridge gateway broke every ray wheel build (ray postmerge 19281), because pip could not reach it and an unreachable index fails a build outright. With host networking the build shares the agent's namespace, so 127.0.0.1 inside a RUN is the agent. That is a constant rather than an address to discover, which removes the class of failure above. Measured with docker 28.1.1: a build reaching a loopback-only service on the host fails with default networking and succeeds with --network=host. Opt-in through RAYCI_BUILD_NETWORK rather than default, because host networking gives a build reach into whatever else listens on the agent, and nobody should acquire that by accident. Unset, the command line is unchanged. Signed-off-by: Ray CI Test <rayci@ray.io>
There was a problem hiding this comment.
Code Review
This pull request introduces support for configuring a custom Docker network (such as host networking) for build RUN steps via the RAYCI_BUILD_NETWORK environment variable, and adds a corresponding unit test. The review feedback suggests refactoring this implementation to pass the network configuration through dockerCmdConfig and store it as a field in dockerCmd rather than reading the environment variable directly inside the build method, which would improve testability and code design.
| if network := os.Getenv("RAYCI_BUILD_NETWORK"); network != "" { | ||
| args = append(args, "--network", network) | ||
| } |
There was a problem hiding this comment.
Instead of reading the environment variable RAYCI_BUILD_NETWORK directly inside the build method, it is more idiomatic and testable to pass this configuration via dockerCmdConfig and store it as a field in dockerCmd. This avoids relying on global state/environment variables deep within the business logic.
To fully implement this, you would also need to:
- Add
Network stringtodockerCmdConfig. - Add
network stringtodockerCmd. - Initialize
networkinnewDockerCmdfromconfig.Network. - Read
os.Getenv("RAYCI_BUILD_NETWORK")at the application entry point wheredockerCmdConfigis constructed.
| if network := os.Getenv("RAYCI_BUILD_NETWORK"); network != "" { | |
| args = append(args, "--network", network) | |
| } | |
| if c.network != "" { | |
| args = append(args, "--network", c.network) | |
| } |
| t.Setenv("RAYCI_BUILD_NETWORK", "host") | ||
|
|
||
| cmd := newDockerCmd(&dockerCmdConfig{}) // uses real docker client |
There was a problem hiding this comment.
If dockerCmdConfig is updated to accept the Network configuration, you can pass it directly here instead of relying on t.Setenv to set the environment variable.
| t.Setenv("RAYCI_BUILD_NETWORK", "host") | |
| cmd := newDockerCmd(&dockerCmdConfig{}) // uses real docker client | |
| cmd := newDockerCmd(&dockerCmdConfig{ | |
| Network: "host", | |
| }) |
Replaces the `RAYCI_BUILD_NETWORK` option from #500 — same goal, less exposure. A wanda step runs directly on the agent rather than in a container, so a service listening there (a package index, say) is outside the build's own network namespace. `--network=host` achieves that but hands the build the agent's **entire** network namespace, including anything bound to loopback. `--add-host` adds one hosts entry and leaves the namespace intact. Both were measured with docker 28.1.1 against a service on the host, on BuildKit and the legacy builder: ``` default networking: BUILD -> UNREACHABLE --network=host: BUILD -> agent-proxy-ok --add-host rayci.x:host-gateway: BUILD -> agent-proxy-ok (both builders) ``` It is also a **name rather than an address**, which matters: inferring the address is what broke every ray wheel build (ray postmerge 19281 vs 19280). The bridge gateway was read from `docker network inspect bridge`, the build could not reach it, and an unreachable index fails a build outright rather than falling back to PyPI. `host-gateway` is resolved by docker, so there is nothing to infer. `rayci.localhost` is the name `ci/ray_ci/linux_container.py` already passes to `docker run`, so a service is addressed identically from a test container and from an image build. No configuration knob: an unset variable was an easy way to end up half-wired. Tested: `TestDockerCmdBuild_addHost` drives a real build; `go test ./wanda/` passes. Signed-off-by: Ray CI Test <rayci@ray.io> Co-authored-by: Ray CI Test <rayci@ray.io>
A wanda step runs directly on the agent rather than in a container, so a service running on that agent is outside the build's own network namespace and unreachable from a
RUN.That is the gap behind ray-project/ray's package-mirror work. The images ray builds cannot reach the index proxy its agents run, and the address-based workaround failed badly: pointing a build at the docker bridge gateway broke every ray wheel build (ray postmerge 19281 vs 19280), because pip could not reach it and an unreachable index fails a build outright rather than falling back.
With host networking the build shares the agent's namespace, so
127.0.0.1inside aRUNis the agent — a constant, rather than an address that must be discovered and that differs per agent. Measured with docker 28.1.1 against a loopback-only service on the host:Opt-in via
RAYCI_BUILD_NETWORKrather than default, because host networking gives a build reach into whatever else listens on the agent, and nobody should acquire that by accident. Unset, the command line is unchanged.Tested: new
TestDockerCmdBuild_hostNetworkdrives a real build with the variable set; fullgo test ./wanda/passes.