{"id":13490118,"url":"https://github.com/chipmk/docker-mac-net-connect","last_synced_at":"2026-02-19T01:09:55.975Z","repository":{"id":37959685,"uuid":"426684003","full_name":"chipmk/docker-mac-net-connect","owner":"chipmk","description":"Connect directly to Docker-for-Mac containers via IP address 🐳 💻","archived":false,"fork":false,"pushed_at":"2024-09-06T22:39:27.000Z","size":164,"stargazers_count":501,"open_issues_count":29,"forks_count":51,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-28T05:32:16.002Z","etag":null,"topics":["containers","docker","ip","macos","networking","vpn","wireguard"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chipmk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-10T15:53:39.000Z","updated_at":"2025-03-27T10:12:50.000Z","dependencies_parsed_at":"2024-10-31T03:42:03.593Z","dependency_job_id":null,"html_url":"https://github.com/chipmk/docker-mac-net-connect","commit_stats":{"total_commits":25,"total_committers":2,"mean_commits":12.5,"dds":"0.040000000000000036","last_synced_commit":"2e79a15bb39e63259b6ec4d6c5bea4de406dff17"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chipmk%2Fdocker-mac-net-connect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chipmk%2Fdocker-mac-net-connect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chipmk%2Fdocker-mac-net-connect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chipmk%2Fdocker-mac-net-connect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chipmk","download_url":"https://codeload.github.com/chipmk/docker-mac-net-connect/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247947820,"owners_count":21023058,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["containers","docker","ip","macos","networking","vpn","wireguard"],"created_at":"2024-07-31T19:00:41.073Z","updated_at":"2026-02-19T01:09:55.966Z","avatar_url":"https://github.com/chipmk.png","language":"Go","readme":"# Docker Mac Net Connect\n\n\u003e Connect directly to Docker-for-Mac containers via IP address.\n\n## Features\n\n- **L3 connectivity:** Connect to Docker containers from macOS host (without port binding).\n- **Lightweight:** Based on WireGuard (built-in to Linux kernel).\n- **Hands-off:** Install once and forget. No need to re-configure every time you restart your Mac or Docker daemon.\n- **Automatic:** Docker networks are automatically added/removed from macOS routing table.\n- **No bloat:** Everything is handled by a single binary. No external dependencies/tools are needed.\n\n## Requirements\n\nOne of the following Docker runtimes:\n\n- **Docker Desktop** v3.6.0 or higher (see [#10](https://github.com/chipmk/docker-mac-net-connect/issues/10#issuecomment-1146662058))\n- **Colima** (likely other Lima-based runtimes as well, but not tested)\n\n## Installation\n\n```bash\n# Install via Homebrew\n$ brew install chipmk/tap/docker-mac-net-connect\n\n# Run the service and register it to launch at boot\n$ sudo brew services start chipmk/tap/docker-mac-net-connect\n```\n\n### `GOPROXY` support\n\nThis Homebrew formulae is built using `go`. When Homebrew installs a formulae, it strips away local environment variables and configuration, including configuration set using `go env`.\n\nSome users require changing `GOPROXY` due to firewalls. This formulae adds special support for `GOPROXY` using `HOMEBREW_GOPROXY`:\n\n```bash\nHOMEBREW_GOPROXY=https://my-proxy-url brew install chipmk/tap/docker-mac-net-connect\n```\n\n## Usage\n\nAfter installing, you will be able to do this:\n\n```bash\n# Run an nginx container\n$ docker run --rm --name nginx -d nginx\n\n# Get the internal IP for the container\n$ docker inspect nginx --format '{{.NetworkSettings.IPAddress}}'\n172.17.0.2\n\n# Make an HTTP request directly to its IP\n$ curl -I 172.17.0.2\nHTTP/1.1 200 OK\nServer: nginx/1.21.3\nDate: Thu, 11 Nov 2021 21:00:37 GMT\nContent-Type: text/html\nContent-Length: 615\nLast-Modified: Tue, 07 Sep 2021 15:21:03 GMT\nConnection: keep-alive\nETag: \"6137835f-267\"\nAccept-Ranges: bytes\n```\n\n## Background\n\nAccessing containers directly by IP (instead of port binding) can be useful and convenient.\n\n### Problem\n\nUnlike Docker on Linux, Docker-for-Mac does not expose container networks directly on the macOS host. Docker-for-Mac works by running a Linux VM under the hood (using [`hyperkit`](https://github.com/moby/hyperkit)) and creates containers within that VM.\n\nDocker-for-Mac supports connecting to containers over Layer 4 (port binding), but not Layer 3 (by IP address).\n\n### Solution\n\nCreate a minimal network tunnel between macOS and the Docker Desktop Linux VM. The tunnel is implemented using WireGuard.\n\n### Why WireGuard?\n\nWireGuard is an extremely lightweight and fast VPN. It’s also built in to the Linux kernel, which means no background processes/containers are required. It is the perfect tool for this application.\n\n## How does it work?\n\n![Connection Diagram](assets/connection-diagram.png)\n\n### macOS side\n\nA lightweight customized WireGuard server (_`docker-mac-net-connect`_) runs on your macOS host and creates a virtual network interface (`utun`) that acts as the link between your Mac and the Docker Desktop Linux VM.\n\n### Linux VM side\n\nSince WireGuard is built into the Linux kernel, all we need to do is configure the VM with a virtual network interface that links to the macOS host. No background processes or containers are required.\n\nHow do we configure the VM? A one-time container is deployed with just enough privileges to configure the Linux host’s network interfaces (`—-cap-add=NET_ADMIN` + `-—net=host`).\n\nThe container creates the interface, configures WireGuard, then exits and is destroyed. The WireGuard interface continues working after the container is gone because it was created on the Linux host’s network namespace, not the container’s.\n\n### Tying it together\n\nThe server on macOS monitors your Docker container networks and automatically adds their subnets to your macOS routing table (routing through the `utun` interface). Now you can connect to any container directly by it’s IP address from your macOS host. Eg.\n\n```bash\n# Run an nginx container\n$ docker run --rm --name nginx -d nginx\n\n# Get the internal IP for the container\n$ docker inspect nginx --format '{{.NetworkSettings.IPAddress}}'\n172.17.0.2\n\n# Make an HTTP request directly to its IP\n$ curl -I 172.17.0.2\nHTTP/1.1 200 OK\nServer: nginx/1.21.3\nDate: Thu, 11 Nov 2021 21:00:37 GMT\nContent-Type: text/html\nContent-Length: 615\nLast-Modified: Tue, 07 Sep 2021 15:21:03 GMT\nConnection: keep-alive\nETag: \"6137835f-267\"\nAccept-Ranges: bytes\n```\n\n## Internal Docker Networks\n\nDocker's [internal networks](https://docs.docker.com/reference/cli/docker/network/create/#internal) allow containers to communicate with each other while blocking access to external networks. They are supported out of the box - you can reach containers on internal networks from your macOS host just like any other container.\n\n```bash\n# Create an internal network\n$ docker network create --internal --subnet 172.30.0.0/24 my-internal\n\n# Run a container on it\n$ docker run --rm -d --name nginx --network my-internal --ip 172.30.0.2 nginx\n\n# Connect directly from macOS\n$ curl -I 172.30.0.2\nHTTP/1.1 200 OK\n```\n\nUnder the hood, your macOS host's WireGuard IP is translated (NAT) to the Docker bridge gateway IP so that the container sees the traffic as coming from within its own network. This is necessary because internal networks intentionally have no default gateway - without NAT, the container would have no route to send replies back to the host.\n\nThis is safe because only your local macOS host can reach internal containers through the tunnel. Other devices on your LAN cannot reach them unless you have explicitly enabled IP forwarding on your Mac (which is off by default). Even then, LAN traffic is not NAT'd, so the container has no route to reply - effectively making internal containers unreachable from the LAN.\n\n## Accessing Containers from the LAN\n\nBy default, `docker-mac-net-connect` enables your macOS host to reach containers directly by IP. With some additional configuration, other devices on your local network can reach containers too.\n\n### Prerequisites\n\n1. **Enable IP forwarding on your Mac.** This allows your Mac to forward packets from the LAN into the WireGuard tunnel:\n\n   ```bash\n   sudo sysctl -w net.inet.ip.forwarding=1\n   ```\n\n   To persist across reboots, add `net.inet.ip.forwarding=1` to `/etc/sysctl.conf`.\n\n2. **Add a static route on your router.** Route your Docker network subnet(s) through your Mac's LAN IP. For example, if your Mac's LAN IP is `192.168.1.6` and your Docker network uses `192.168.2.0/24`:\n\n   ```\n   Network: 192.168.2.0\n   Netmask: 255.255.255.0\n   Gateway: 192.168.1.6\n   ```\n\n   Not all routers support static routes - you may need one that supports OpenWRT or similar.\n\n### How it works\n\nTraffic from LAN devices is forwarded through the WireGuard tunnel without NAT, so containers see the real source IP of each device. This is useful for services like Pi-hole that need to identify individual clients.\n\n## Other Solutions\n\nOther great solutions have been created to solve this, but none of them are as turn-key and lightweight as we wanted.\n\n- **[docker-tuntap-osx](https://github.com/AlmirKadric-Published/docker-tuntap-osx)**\n  - Requires installing third party `tuntap` kernel extension\n  - Requires manually re-running a script every time the Docker VM restarts to bring the network interface back up\n  - Docker network subnets have to be routed manually\n\n- **[docker-mac-network](https://github.com/wojas/docker-mac-network)**\n  - Requires installing an OpenVPN client (ie. `Tunnelblick`)\n  - Requires an OpenVPN server container to be running at all times in order to function\n  - Docker network subnets have to be routed manually\n\n## FAQ\n\n### Is this secure?\n\nThis tool piggybacks off of WireGuard which has gone through numerous audits and security tests (it is built-in to the Linux kernel after all). The `docker-mac-net-connect` server generates new private/public key pairs for each WireGuard peer every time it runs. The WireGuard listen port is also ephemeral - no values are hard-coded.\n\nNetwork traffic runs directly between the macOS host and local Linux VM - no external connections are made.\n\n### Can I use this in production?\n\nThis tool was designed to assist with development on macOS. Since Docker-for-Mac isn't designed for production workloads, neither is this.\n\n### What happens if Docker Desktop restarts?\n\nThe server detects when the Docker daemon stops and automatically reconfigures the tunnel when it starts back up.\n\n### Do you add/remove routes when Docker networks change?\n\nYes, the server watches the Docker daemon for both network creations and deletions and will add/remove routes accordingly.\n\nFor example, let's create a Docker network with subnet `172.200.0.0/16`:\n\n```bash\n# First validate that no route exists for the subnet\nsudo netstat -rnf inet | grep 172.200\n\n# Create the docker network\n$ docker network create --subnet 172.200.0.0/16 my-network\n\n# Check the routing table - a new route exists\n$ sudo netstat -rnf inet | grep 172.200\n172.200            utun0              USc          utun0\n\n# Remove the docker network\n$ docker network rm my-network\n\n# The route has been removed\nsudo netstat -rnf inet | grep 172.200\n```\n\n### Will routes remain orphaned in the routing table if the server crashes?\n\nNo, routes are tied to the `utun` device created by the server. If the server dies, the `utun` interface will disappear along with its routes.\n\n### Why does the service need to run as root?\n\nRoot permissions are required by the service to:\n\n- Create a `utun` network interface\n- Configure the `utun` interface (`ifconfig`)\n- Add and remove routes in the routing table (`route`)\n\nThis app tries to minimize opportunity for privilege escalation by following the principle of least privilege (PoLP). With that said, macOS has no concept of fine-grained admin privileges (ie. capabilities), so running as `sudo` is required.\n\n## Troubleshooting\n\n- If things stop working after upgrading Docker, you may need to do a clean uninstall / reinstall of Docker Desktop. See here for uninstall instructions: [Uninstall Docker](https://docs.docker.com/desktop/uninstall/)\n- For general troubleshooting, try running the command directly rather than as a service: (From e.g. `/opt/homebrew/Cellar/docker-mac-net-connect/v{*.*}/bin/`):\n\n```\nsudo brew services stop chipmk/tap/docker-mac-net-connect\nsudo docker-mac-net-connect\n```\n\nThis will show any debug messages that may indicate what is causing your issue.\n\n## License\n\nMIT\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchipmk%2Fdocker-mac-net-connect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchipmk%2Fdocker-mac-net-connect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchipmk%2Fdocker-mac-net-connect/lists"}