access host's ssh tunnel from docker container
Using your hosts network as network for your containers via --net=host
or in docker-compose via network_mode: host
is one option but this has the unwanted side effect that (a) you now expose the container ports in your host system and (b) that you cannot connect to those containers anymore that are not mapped to your host network.
In your case, a quick and cleaner solution would be to make your ssh tunnel "available" to your docker containers (e.g. by binding ssh to the docker0
bridge) instead of exposing your docker containers in your host environment (as suggested in the accepted answer).
Setting up the tunnel:
For this to work, retrieve the ip your docker0
bridge is using via:
ifconfig
you will see something like this:
docker0 Link encap:Ethernet HWaddr 03:41:4a:26:b7:31
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
Now you need to tell ssh to bind to this ip to listen for traffic directed towards port 9000 via
ssh -L 172.17.0.1:9000:host-ip:9999
Without setting the bind_address, :9000
would only be available to your host's loopback interface and not per se to your docker containers.
Side note: You could also bind your tunnel to 0.0.0.0
, which will make ssh listen to all interfaces.
Setting up your application:
In your containerized application use the same docker0
ip to connect to the server: 172.17.0.1:9000
. Now traffic being routed through your docker0
bridge will also reach your ssh tunnel :)
For example, if you have a "DOT.NET Core" application that needs to connect to a remote db located at :9000
, your "ConnectionString" would contain "server=172.17.0.1,9000;
.
Forwarding multiple connections:
When dealing with multiple outgoing connections (e.g. a docker container needs to connect to multiple remote DB's via tunnel), several valid techniques exist but an easy and straightforward way is to simply create multiple tunnels listening to traffic arriving at different docker0
bridge ports.
Within your ssh tunnel command (ssh -L [bind_address:]port:host:hostport] [user@]hostname
), the port
part of the bind_address
does not have to match the hostport
of the host
and, therefore, can be freely chosen by you. So within your docker containers just channel the traffic to different ports of your docker0
bridge and then create several ssh tunnel commands (one for each port you are listening to) that intercept data at these ports and then forward it to the different host
s and hostport
s of your choice.
I think you can do it by adding --net=host
to your docker run. But see also this question: Forward host port to docker container
on MacOS (tested in v19.03.2
),
1) create a tunnel on host
ssh -i key.pem username@jump_server -L 3336:mysql_host:3306 -N
2) from container, you can use host.docker.internal
or docker.for.mac.localhost
or docker.for.mac.host.internal
to reference host.
example,
mysql -h host.docker.internal -P 3336 -u admin -p
note from docker-for-mac official doc
I WANT TO CONNECT FROM A CONTAINER TO A SERVICE ON THE HOST
The host has a changing IP address (or none if you have no network access). From 18.03 onwards our recommendation is to connect to the special DNS name
host.docker.internal
, which resolves to the internal IP address used by the host. This is for development purpose and will not work in a production environment outside of Docker Desktop for Mac.The gateway is also reachable as
gateway.docker.internal
.