Ken Muse

Using Git SSH From Docker With a Local Proxy


In last week’s post, we saw that there are some great ways to use the configuration files to enable you to rewrite the connection URLs and dynamically select credentials. Today, let’s look at something slightly more complex.

Sometimes we need a Docker container to be able to use local resources. For example, perhaps we’re developing from within a Dev Container. At the same time, we need to be able to get access to a proxy on the host that is providing secure SSH access to a resource. For our example, the host machine is running a secure proxy from port 2022 to the remote environments’s port 22 (SSH) to avoid exposing port 22 directly.

The initial SSH configuration in ~/.ssh/config with a direct connection might look like this:


HOST ghes
    AddKeysToAgent yes
    HostName git.myco.corp
    IdentityFile ~/.ssh/ghes_rsa
    IdentitiesOnly yes
    User git

Because of the way Docker works, we can’t rely on localhost or the host’s name to access that resource. So, how do we get access? Docker provides a special DNS name host.docker.internal that resolves to the internal IP address that Docker uses for the host. This only works with Docker for Mac and Docker for Windows, so Linux users need an additional step.

Linux users will need to run Docker will an additional argument: --add-host=host.docker.internal:host-gateway. If you’re doing this from within a Dev Container, you’ll need to specify this in the runArgs. If you’re using Docker Compose, there’s a nice write-up in StackOverflow covering the extra_hosts parameter and the networking configuration.

The add-host command adds an entry to the /etc/hosts file in the container, making the domain name available to the container. Moby added support for the magic string, host-gateway in 2020; it represents the IP for the host. This adds an explicit entry in /etc/hosts for the name host.docker.internal and maps it to the IP address provided by host-gateway. This approach means you can also define any DNS name you choose for the host. Adding this command makes it compatible on all platforms.

Now that you know how to give the container access to the host, we just need to make a tweak in the ~/.ssh/config file that is used in the container. The new config would point to our host name and the proxy’s port. Continuing with the example:


HOST ghes
    AddKeysToAgent yes
    HostName host.docker.internal
    IdentityFile ~/.ssh/ghes_rsa
    IdentitiesOnly yes
    User git
    Port 2022

The HostName has been changed and we’ve added an entry for the port. Now, connections to the Host ghes will be connected to the container’s host, port 2022 instead of connecting to the original host on port 22. This same approach can be used for connecting to other services (with the caveat that this is not recommended on production systems).

Happy DevOp’ing!