Docker Networking Fix
OpenHands couldn’t reach Gitea and volumes wouldn’t mount. Two separate Docker networking failures in one session.
Quick Take
- Docker containers couldn’t resolve each other by name despite being on the same network
- Volume mounts stayed in the wrong container and never reached the sandbox
- A single
.gitconfigtweak fixed both issues without touching the host
OpenHands Sandbox Can’t Resolve Gitea by Name
Symptom
Running curl http://host.docker.internal:3002 from inside the OpenHands sandbox timed out with:
curl: (000) Failed to connect: timeout
Why It Breaks
OpenHands and Gitea were both in the same Docker network (172.18.0.x), but OpenHands tried to hit the host’s port mapping instead of the container name. The host port 3002 was unreachable because Tor blocked it in daemon.json. Meanwhile, the sandbox container had no idea host.docker.internal existed—it only knew the Docker DNS world where containers are resolved by their service names.
In Docker’s default bridge network, containers can communicate using their names as hostnames, but host.docker.internal is a special DNS alias that only works on the host machine itself. The OpenHands sandbox, running as a container, had no access to this host-level alias. This is a common gotcha when containers need to reach services running on the host machine.
How to Fix It
Switch all URLs from the host mapping to the container name. Replace:
http://host.docker.internal:3002
with:
http://gitea:3000
Update every file that referenced the old URL:
/data/secrets/git-credentials/data/openhands-state/.gitconfig
Then verify from inside the OpenHands container:
docker exec openhands curl -s http://gitea:3000/api/v1/version | grep version
Expect a JSON response like:
{"version":"1.21.4"}
Watch Out
If you still see timeouts, check your Docker network:
docker network inspect bridge | grep gitea
The container must appear under Containers with the correct IP. If it’s missing, restart Gitea:
docker restart gitea
You can also inspect the custom network if you’re using one:
docker network inspect openhands_default
Sandbox Container Can’t Read Mounted Volumes
Symptom
Git commands inside the OpenHands sandbox asked for username/password or failed outright because the sandbox couldn’t read .gitconfig or .git-credentials.
Why It Breaks
Volumes mounted in the openhands container don’t automatically propagate to the runtime or sandbox containers. The sandbox is a separate container with its own isolated filesystem. Without explicit volume mounts, those files simply vanish into the container’s ephemeral storage.
This happens because Docker’s volume mounting is scoped to the container where the volume is declared. When OpenHands spawns a sandbox container, it doesn’t inherit volumes from its parent unless explicitly configured. The sandbox container runs with its own root filesystem (/) and any files needed for Git operations must be mounted in explicitly.
How to Fix It
Use the [sandbox] section in config.toml to declare the volumes once:
[sandbox]
volumes = "/data/secrets/git-credentials:/root/.git-credentials:ro,/data/openhands-state/.gitconfig:/root/.gitconfig:ro"
OpenHands will bind-mount these paths into every sandbox container it starts. The :ro flag ensures the files are read-only inside the container, preventing accidental modifications.
Watch Out
If the sandbox still can’t read the files, confirm the source paths exist on the host:
ls -l /data/secrets/git-credentials
Permissions must be readable by the user running the Docker daemon (typically root or the user in the docker group). Fix with:
chmod 644 /data/secrets/git-credentials
You can also check the effective permissions inside the container:
docker exec openhands ls -l /root/.git-credentials
Git URLs Show localhost Instead of Container Name
Symptom
Gitea URLs appear as http://localhost:3002/... in the browser, but the sandbox needs http://gitea:3000/....
Why It Breaks
Git has no idea the sandbox is running inside Docker and that localhost points to the host, not the container network. Without URL rewriting, clones fail when the sandbox tries to hit localhost:3002.
This is a classic case of Git operating at the application layer while Docker operates at the network layer. Git doesn’t understand Docker’s internal DNS or port mappings—it only sees the URLs as written in the repository configuration. When a developer clones a repo using http://localhost:3002/repo.git, Git stores that URL in its config. Later, when OpenHands tries to run Git commands inside the sandbox, it uses the same URL, which points to the host’s localhost (the sandbox container itself), not the Gitea container.
How to Fix It
Add a rewrite rule in .gitconfig:
[url "http://gitea:3000/"]
insteadOf = http://localhost:3002/
Now when OpenHands clones http://localhost:3002/cipherfox/repo.git, Git silently rewrites it to http://gitea:3000/cipherfox/repo.git.
Watch Out
Test the rewrite before relying on it:
git clone --dry-run http://localhost:3002/cipherfox/repo.git
Expect output showing the rewritten URL:
Cloning into 'repo'...
remote: Enumerating objects: ..., done.
You can also verify the rewrite is active:
git config --get-regexp '^url\..*\.insteadOf'
Final Working Config
/data/openhands-state/.gitconfig
[user]
name = cipherfox
email = cipherfoxie@proton.me
[credential]
helper = store --file /root/.git-credentials
[url "http://gitea:3000/"]
insteadOf = http://localhost:3002/
[init]
defaultBranch = main
[pull]
rebase = false
/data/secrets/git-credentials
http://cipherfox:<TOKEN>@gitea:3000
Note: Replace
<TOKEN>with your actual Gitea personal access token. Never commit this file with the token exposed.
Verify everything works from the OpenHands container:
docker exec openhands bash -c 'git ls-remote http://gitea:3000/cipherfox/sovereign-backup.git'
You should see a list of commit hashes, not an authentication prompt.
What I Actually Use
- Gitea: self-hosted Git server running in Docker for private repos and CI (version 1.21.4 as of this writing)
- OpenHands: sandboxed agent that edits code inside isolated Docker containers (running on Docker Engine 24.0.7)
Further Reading
Docker Networking Fix
Resolving container-to-container communication issues