The Mac Docker Network Problem

Docker is a critical part of my development environment. I run multiple projects, some of which have multiple components that run on the same ports. I need to be able to address the services of my applications between containers as well as from my web browser. To do this using Docker, you have two options:

Address everything against the docker host and manage a multiplicity of (random) ports, which can change every time you docker-compose up.

Alternatively, you can address the containers directly via IP.

I much prefer the latter. Because Docker must run in a virtual machine (VM) on a Mac, to address by IP, you must route through a virtual interface, which connects to the VM. However, there is a known issue with Docker for Mac, I can't ping my containers. This happens because there is no virtual interface — instead, Docker for Mac binds published ports directly to your Mac's localhost.

The Solution Is a Tunnel

In my attempts to bring Mac-based development to parity with a native Linux environment, this is what I have tried. My first thought was to use the VPN over SSH approach. Running ssh -w required installing TapTun, which was clobbering existing tun interfaces whenever a new one was created. The second effort was to investigate Building TUN based virtual networks with socat. However, socat doesn't support TUN on a Mac. Finally, I decided to make something myself.

The Soctun Tunnel Approach

That is why I built soctun. It creates a native (no new drivers) utun device and connects it to a socket. In our case, we will be connecting it to a socket created by socat in a Docker container, which will act as a bridge. This creates a new virtual network, which effectively replaces the one that Docker for Mac is missing (although this one goes straight to the Docker network, not the Docker host). Once routes have been configured on both sides, ping (or other network operations) will succeed to any container in that Docker network.

Next Steps

Download soctun's latest release and give it a try. If you are using Node.js, you should look at yaktor, another SciSpike project. It builds projects with a script to automatically ensure a tunnel is available every time you start the application.