In some very edge use cases you may want to temporarily connect to a remote service on a different network from within a docker container. In this example I needed to provide a solution to connect from a docker container on a Mac laptop to a database hosted in a subnet far far away. Here’s a proof of concept.
setup the ssh tunnel from the Mac host:
ssh -L 56789:10.0.100.200:3306 firstname.lastname@example.org
This starts an ssh tunnel with the TCP port 56789 open on localhost, forwarding through the ssh tunnel to port 3306 on a host with IP address 10.0.100.200 on the remote network
start a container:
docker run --rm -it alpine:latest sh
This runs an interactive shell in a temporary docker container from the alpine:latest image
inside the container add mysql client for testing:
/ # apk add --update --no-cache mysql-client
This fetches a temporary package list and installs mysql-client
create a database connection:
/ # mysql -h docker.for.mac.localhost --port 56789 -udbuser -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MySQL connection id is 675073323 Server version: 5.6.27-log MySQL Community Server (GPL) Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MySQL [(none)]> MySQL [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | awesome_app | | innodb | | mysql | | performance_schema | +--------------------+ 5 rows in set (0.08 sec) MySQL [(none)]>
The magic here comes from the special
docker.for.mac.localhost hostname. The internal Docker for Mac DNS resolver uses this special entry to return the internal IP address used by the Mac host. Tell the mysql client to use the port-forwarded TCP port
--port 56789 and the mysql client inside the container connects through the ssh tunnel to the remote database.
On newer versions of Docker you need to use host.docker.internal as the host name.