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!