Skip to content

Conversation

@olivembo
Copy link

@olivembo olivembo commented Nov 5, 2025

Summary

This PR adds robust support for running the devcontainer in environments with or without a corporate proxy, including WSL2 scenarios. The setup is now fully automated and self-healing, ensuring Docker and BuildKit always use the correct proxy settings.

Key changes

  • Automated proxy detection and configuration

    • Adds .devcontainer/setup-proxy.sh which configures Docker daemon, BuildKit, and Docker client for proxy or non-proxy environments.
    • Automatically detects and applies current proxy environment variables.
    • Cleans up and recreates BuildKit builder with correct proxy settings if the proxy changes.
  • Post-create automation

    • Runs the setup script automatically via postCreateCommand in devcontainer.json.
  • Build-time and runtime proxy support

    • Passes proxy variables as build args and runtime envs.
    • Ensures Dockerfile and all devcontainer features can access the internet through the proxy.
  • WSL2 and host networking compatibility

    • Adds host.docker.internal and other runArgs for seamless networking in WSL2.
  • Documentation and testing

    • Adds .devcontainer/test-proxy.sh for easy verification.
    • Adds README-PROXY.md with usage and troubleshooting instructions.

How it works

On container creation, the setup script:
Detects proxy settings.
Configures Docker daemon and BuildKit accordingly.
Verifies Docker and registry access.
Works out-of-the-box for both proxy and non-proxy environments.
Handles proxy changes and container rebuilds gracefully.

Why

Ensures reliable devcontainer builds in corporate, WSL, and direct-internet environments.
Reduces manual setup and troubleshooting for developers.
Makes onboarding and CI/CD more robust.

"--volume=/home/${USER}/.cache/uv:/home/user/.cache/uv"
],
"workspaceFolder": "/workspace",
"postCreateCommand": "bash .devcontainer/setup-proxy.sh",
Copy link
Member

Choose a reason for hiding this comment

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

@opajonk can you please document/explain how the split between devcontainer and features is designed?

fi
}

# Restart Docker with proxy settings
Copy link
Member

Choose a reason for hiding this comment

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

Will this kill any (unrelated) running dockers on the system?

Copy link
Contributor

@lurtz lurtz left a comment

Choose a reason for hiding this comment

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

Adds README-PROXY.md with usage and troubleshooting instructions.

I guess this forgotten to be added.

We should talk about this pull request via Slack.

"--volume=/home/${USER}/.cache/uv:/home/user/.cache/uv"
],
"workspaceFolder": "/workspace",
"postCreateCommand": "bash .devcontainer/setup-proxy.sh",
Copy link
Contributor

Choose a reason for hiding this comment

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

I am a bit confused where this script is intended to be run. Per the location it should be run inside the S-CORE devcontainer. But the content assumes that docker is present, which is not installed in the S-CORE devcontainer but on the host instead.

If you intend to run it on the host, you have to use initializeCommand: https://containers.dev/implementors/json_reference/#lifecycle-scripts. However in this case you have to deal with lots of different environments.

Host environments I am aware of so far:

  • Ubuntu 20.04, 22.04, 24.04
    • do not expect to have root permissions on these
  • MacOS
  • WSL2

Copy link
Contributor

Choose a reason for hiding this comment

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

is this script reconfiguring my host Docker daemon from inside the S-CORE devcontainer?

"--volume=/var/run/docker.sock:/var/run/docker.sock",
"--volume=..:/workspace:cached",
"--volume=/tmp/.X11-unix:/tmp/.X11-unix",
"--volume=/home/${USER}/.cache/uv:/home/user/.cache/uv"
Copy link
Contributor

Choose a reason for hiding this comment

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

what is in .cache/uv? It does not exist on my host

"--env=WORKSPACE_FOLDER=/workspace",
"--volume=/var/run/docker.sock:/var/run/docker.sock",
"--volume=..:/workspace:cached",
"--volume=/tmp/.X11-unix:/tmp/.X11-unix",
Copy link
Contributor

Choose a reason for hiding this comment

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

would this close the door to wayland users?

"--env=no_proxy",
"--env=DISPLAY",
"--env=WORKSPACE_FOLDER=/workspace",
"--volume=/var/run/docker.sock:/var/run/docker.sock",
Copy link
Contributor

Choose a reason for hiding this comment

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

I have to check how well this works with podman. At the time being I would like to be able to run the container on both docker and podman. The reason is that for being able to run bazels linux-sandbox the container needs to be run with --privileged which gives the container with docker basically root access to my notebook. With podman this can be minimized to my user.

I have so far seen containers as an easy to setup development environment and as a security / safety measure for the host system of my computer. Having to use --privileged is already a big boon to that and seeing the host docker being reconfigured from within the container seems to further tear down this wall.

"--env=https_proxy",
"--env=NO_PROXY",
"--env=no_proxy",
"--env=DISPLAY",
Copy link
Contributor

Choose a reason for hiding this comment

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

will this read the content of the current variable and assign it to DISPLAY inside the container?

echo "🔄 Restarting Docker daemon with proxy settings..."

# Kill existing dockerd if running
if pgrep dockerd > /dev/null; then
Copy link
Contributor

Choose a reason for hiding this comment

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

docker is not installed inside the container. How can you access it?

Comment on lines 30 to 39
sudo tee /etc/docker/daemon.json > /dev/null << EOF
{
"registry-mirrors": [],
"insecure-registries": [],
"debug": false,
"experimental": false,
"dns": ["8.8.8.8", "1.1.1.1"],
"dns-search": [],
"dns-opts": []
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I have setup a daemon.json so that docker works in the corporate environment of my company. Would this be overriden, if I were using one of the proxy variables?

Comment on lines 121 to 122
# Prepare buildx command with proxy options
BUILDX_CMD="docker buildx create --name multiarch --driver docker-container --driver-opt network=host"
Copy link
Contributor

Choose a reason for hiding this comment

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

now I get very confused. I assume this requires the existence of a Dockerfile. Is this script used to build the S-CORE devcontainer with the other devcontainer of this repository?

@opajonk
Copy link
Contributor

opajonk commented Nov 10, 2025

Adds README-PROXY.md with usage and troubleshooting instructions.

I guess this forgotten to be added.

We should talk about this pull request via Slack.

I agree we should have a chat. There seems to be a legitimate use-case (as I also heard during the architecture workshop last week). However, re-configuring the docker host (!) significantly - and probably unexpectedly to most other users - is a problem. Maybe we can find a less "intrusive" and still helpful solution?

Copy link
Contributor

@lurtz lurtz left a comment

Choose a reason for hiding this comment

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

Works on my machine.

Now proxy related environment variables are defined in the container with empty content. I hope no software trips over that.

Have you considered using

    "runArgs": [
        "--env-file", "proxy_settings.env",
    ],

In the devcontainer.json? In proxy_settings.env you define the environment variables to be made available inside the container. Maybe even .env as filename is sufficient and no extra arguments needed (was not working for me with an already built container)

@olivembo
Copy link
Author

Works on my machine.

Now proxy related environment variables are defined in the container with empty content. I hope no software trips over that.

Have you considered using

    "runArgs": [
        "--env-file", "proxy_settings.env",
    ],

In the devcontainer.json? In proxy_settings.env you define the environment variables to be made available inside the container. Maybe even .env as filename is sufficient and no extra arguments needed (was not working for me with an already built container)

In general, I like the .env file approach, but in that case it would mean that users behind proxies would have to create the .env file manually before they can start. The current approach does not need any user interaction, neither from user behind a proxy nor from users with direct internet connection.

Regarding the empty environment variables in case of direct internet access:
I agree it is maybe confusing, but didn't had side effects so far when I tested on my machine with direct internet access.

However, I could add a line like

"postStartCommand": "for var in HTTP_PROXY HTTPS_PROXY http_proxy https_proxy NO_PROXY no_proxy; do [ -z \"${!var}\" ] && unset $var || true; done",

to the devcontainer.json. Does that make sense from your side?

@lurtz
Copy link
Contributor

lurtz commented Nov 11, 2025

I would appreciate if these are deleted if empty. Then we are sure not to get unintended side effects. I also only checked if some tools work. Would be a waste of time to discover that there is a tool which malfunctions when these variables are set but empty.

@olivembo
Copy link
Author

I would appreciate if these are deleted if empty. Then we are sure not to get unintended side effects. I also only checked if some tools work. Would be a waste of time to discover that there is a tool which malfunctions when these variables are set but empty.

Is addressed with c81e8ed

@lurtz
Copy link
Contributor

lurtz commented Nov 12, 2025

I get an error, when starting the container:

Running the postStartCommand from devcontainer.json...

[3301 ms] Start: Run in container: /bin/sh -c for var in HTTP_PROXY HTTPS_PROXY http_proxy https_proxy NO_PROXY no_proxy; do [ -z "${!var}" ] && unset $var || true; done
/bin/sh: 1: Bad substitution
[3349 ms] postStartCommand from devcontainer.json failed with exit code 2. Skipping any further user-provided commands.

I suspect the problem is that /bin/sh is used instead of bash.

"./s-core-local"
],
"remoteUser": "vscode",
"postStartCommand": "bash -c 'for var in HTTP_PROXY HTTPS_PROXY http_proxy https_proxy NO_PROXY no_proxy; do [ -z \"${!var}\" ] && unset $var || true; done'",
Copy link
Contributor

Choose a reason for hiding this comment

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

this still does not work. Execution is now successful, but variables are still present in a new shell:

vscode ➜ /workspaces/inc_mw_com (example_trait_impl) $ cat .devcontainer/devcontainer.json 
{
    "name": "eclipse-s-core",
    // "image": "ghcr.io/eclipse-score/devcontainer:rustup-completion-amd64"
    "image": "ghcr.io/eclipse-score/devcontainer:proxy-settings-amd64"
    // "image": "ghcr.io/eclipse-score/devcontainer:fix-setting-bazel-version-amd64"
}
vscode ➜ /workspaces/inc_mw_com (example_trait_impl) $ env | grep -i proxy
no_proxy=
https_proxy=
NO_PROXY=
HTTPS_PROXY=
HTTP_PROXY=
http_proxy=

Copy link
Author

@olivembo olivembo Nov 12, 2025

Choose a reason for hiding this comment

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

You are right. The postStartCommand runs in its own shell und unsets the environment variables only there.

The only solution I would have at the moment, would be to append unset commands to .bashrc in the postStartCommand. The .bashrc is then sourced by every new bash shell and every time unsets the environment variables. But it's not a nice solution imho. Would appreciate better proposals.

Copy link
Contributor

@lurtz lurtz Nov 13, 2025

Choose a reason for hiding this comment

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

I guess we can use /etc/profile.d/ for this. Here is an example where I removed using it: https://github.com/eclipse-score/devcontainer/pull/51/files#diff-e418ce180663a5c3fc806f1c352a9d737097e60cecaa9cd1724c8236a955a335R64

Comment on lines +116 to +117
# gdb (GNU Debugger)
apt-get install -y gdb="${gdb_version}*"
Copy link
Contributor

Choose a reason for hiding this comment

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

@opajonk Do we really have to specify the tool version, if it just installed via apt-get? E.g. Python tooling is not installed with a specific version either: https://github.com/etas-contrib/score_devcontainer/blob/8aae83706ce51796b85894cdd2c6c0bc29901e84/src/s-core-devcontainer/.devcontainer/s-core-local/install.sh#L41

We already have a Ubuntu release set, which defines the versions of these tools. And thus defining the versions for each tool feels redundant.


# OpenJDK JRE and CA certificates, via APT
# Required for Bazel to work with corporate proxy/CA certificates
apt-get install -y --no-install-recommends ca-certificates-java openjdk-${openjdk_version}-jre-headless
Copy link
Contributor

Choose a reason for hiding this comment

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

Specifying the Java version here is IMHO ok, because there are different versions as apt packages available for the same Ubuntu release.

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.

4 participants