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.
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).