Skip to content

build: forward proxy settings into the container image builds - #113

Open
cleverhu wants to merge 1 commit into
kvcache-ai:mainfrom
cleverhu:build/docker-proxy-passthrough
Open

build: forward proxy settings into the container image builds#113
cleverhu wants to merge 1 commit into
kvcache-ai:mainfrom
cleverhu:build/docker-proxy-passthrough

Conversation

@cleverhu

@cleverhu cleverhu commented Aug 3, 2026

Copy link
Copy Markdown

What

Forward the caller's proxy environment into the container image builds from both make k8s-build and docker compose, and enable reqwest's socks feature.

Why

The --setup-only layer of Dockerfile.agentenv downloads regctl, firecracker, the kernel, the overlaybd package and the ghcr.io tools image. Behind a restricted network that is by far the slowest part of a cold build, and there was no way to point it at a proxy short of editing the Dockerfile.

The socks feature is needed because reqwest reads the standard proxy environment variables but silently ignores socks5:// values when the feature is off. A build that appears to honour HTTPS_PROXY then goes direct and hangs, with no diagnostic.

Related issue

None; build-time developer experience.

Scope and non-goals

Included: proxy passthrough in the Makefile, docker compose and a Dockerfile comment, plus the reqwest feature.

Explicitly excluded, because they were part of the same internal change but are site-specific:

  • Retargeting the k8s image names at a private registry, and adding --push to k8s-build.
  • Defaulting APT_MIRROR_BASE to a regional mirror. It stays empty.

Design and behavior changes

DOCKER_PROXY_ARGS is assembled from HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY, each defaulting to its lowercase counterpart. Both spellings are passed through because Go and Rust HTTP clients differ in which they look up. Unset variables expand to nothing, so with no proxy exported the build commands are byte-for-byte what they are today.

These four are predefined BuildKit build args. Passing them with --build-arg makes them available to every stage's RUN without an ARG declaration, and keeps them out of the image environment, docker history, and the layer cache key — which matters because a proxy URL often carries credentials. The Dockerfile comment records this, since declaring ARG explicitly would scope them to a single stage and leave the deps-stage downloads on a direct connection, which is the opposite of the intent.

docker-compose.yml forwards the same four to the agentenv build.

Compatibility and operations

  • Public API or generated protocol: N/A.
  • Configuration or defaults: no defaults change. Behavior is identical unless a proxy variable is exported.
  • Snapshot manifest, artifact layout, or storage format: N/A.
  • Upgrade and rollback: N/A, build-time only.
  • Host requirements, permissions, ports, or dependencies: socks pulls in reqwest's SOCKS support; Cargo.lock needs no update and cargo metadata --locked still passes.

Validation

  • make fmt
  • make clippy
  • make test-unit
  • Relevant Rust integration tests
  • make -C services test (required when services/ changes)
  • Generated clients/server regenerated with the documented make target
  • Documentation updated
  • Benchmarks or performance comparison completed

Commands and results:

$ cargo clippy --workspace --all-targets -- -D warnings
Finished `dev` profile

$ cargo metadata --locked --format-version 1
LOCKED OK   (Cargo.lock unchanged by the added feature)

$ make -n k8s-build                       # no proxy exported
docker build      -f deploy/docker/Dockerfile.agentenv -t agentenv-runtime:latest .
docker build     -f deploy/docker/Dockerfile.gateway -t agentenv-gateway:latest .
docker build     -f deploy/docker/Dockerfile.scheduler -t agentenv-scheduler:latest .

$ HTTPS_PROXY=socks5://127.0.0.1:1080 make -n k8s-build
docker build   --build-arg HTTPS_PROXY="socks5://127.0.0.1:1080" --build-arg https_proxy="socks5://127.0.0.1:1080"   -f deploy/docker/Dockerfile.agentenv -t agentenv-runtime:latest .
...

$ python3 -c "import yaml; yaml.safe_load(open('deploy/docker-compose.yml'))"
YAML OK

Skipped checks and reasons:

  • make test-unit not run: the only Rust change is a Cargo feature flag, covered by a full --all-targets clippy build.
  • A real proxied make k8s-build was not executed here; the passthrough is verified with make -n in both the proxy and no-proxy cases, and the equivalent change has been used to build these images behind a SOCKS proxy internally.

Risks and reviewer notes

The no-proxy path is the one to check, since it affects everyone: make -n output above confirms the commands are unchanged apart from whitespace when no variable is exported.

Second point for review: proxy URLs frequently embed credentials. Using the predefined BuildKit args rather than declaring ARG keeps them out of the image and out of docker history; if maintainers would rather not accept proxy values through the Makefile at all, the compose and Dockerfile parts still stand on their own.

Most important file: Makefile.

Checklist

  • The PR contains one coherent change and no unrelated formatting or refactoring.
  • New behavior is covered by tests, or I explained why testing is impractical.
  • Logs and examples contain no credentials, tokens, or private registry information.
  • I did not manually edit generated code without updating its source and regenerating it.

The `--setup-only` layer downloads regctl, firecracker, the kernel, the
overlaybd package and the tools image, which is the slowest part of a
cold build behind a restricted network. Forward the caller's proxy
environment into every build stage from both `make k8s-build` and
docker compose, and enable reqwest's socks feature so socks5:// proxy
variables are honoured rather than silently ignored.

The proxy variables are passed as predefined BuildKit build args, so
they reach every stage without an ARG declaration and stay out of the
image environment, docker history and the layer cache key. Unset
variables expand to nothing and leave the build commands unchanged.
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

🔍 OpenCodeReview found 2 issue(s) in this PR.

  • ✅ Successfully posted inline: 2 comment(s)

Comment thread Cargo.toml
reqwest = { version = "0.13", features = ["json", "stream"] }
# `socks` lets dependency downloads honour socks5:// values in the standard
# proxy environment variables; without it reqwest silently ignores them.
reqwest = { version = "0.13", features = ["json", "stream", "socks"] }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[bug · high]
The committed Cargo.lock was not regenerated for this feature change: its reqwest 0.13.3 entry has no SOCKS dependency (such as tokio-socks). Consequently, reproducible/locked builds will reject the stale lockfile, while unlocked builds produce an uncommitted lockfile update. Run cargo update -p reqwest@0.13.3 (or cargo check) and stage the resulting Cargo.lock changes.

Comment thread Makefile
Comment on lines +29 to +33
DOCKER_PROXY_ARGS := \
$(if $(HTTP_PROXY),--build-arg HTTP_PROXY="$(HTTP_PROXY)" --build-arg http_proxy="$(HTTP_PROXY)",) \
$(if $(HTTPS_PROXY),--build-arg HTTPS_PROXY="$(HTTPS_PROXY)" --build-arg https_proxy="$(HTTPS_PROXY)",) \
$(if $(ALL_PROXY),--build-arg ALL_PROXY="$(ALL_PROXY)" --build-arg all_proxy="$(ALL_PROXY)",) \
$(if $(NO_PROXY),--build-arg NO_PROXY="$(NO_PROXY)" --build-arg no_proxy="$(NO_PROXY)",)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[security · medium]
Proxy URLs commonly contain credentials. Expanding their values directly into the recipe causes make to echo those credentials into terminal/CI logs, and also exposes them in the docker build process arguments. Export the upper/lower-case proxy variables and use valueless options such as --build-arg HTTPS_PROXY --build-arg https_proxy; Docker will read their values from the client environment without placing them in the displayed command line. Merely prefixing the recipe with @ would address logs but not process-argument exposure.

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