Using Ngrok through Docker for local service development on Mac

Corporate policy restrictions got you down? Me too! I've struggled to find a reliable solution for local Slack, Github, or cloud development when Ngrok, the most commonly used tool for exposing services locally, is restricted by either a local execution policy or via OpenDNS (or similar). I've found the following Docker-based method to be a reliable workaround to those typical corporate or public network restrictions while still having the full functionality of Ngrok.

Prerequisites

Install Docker Desktop via Homebrew

brew install docker

Container

You could roll your own; however, there are already several popular options on Docker Hub to get you up and running immediately. I recommend wernight/ngrok, it's well-documented and easy to configure.

Update Started a fork to support some additional Ngrok arguments until they are merged in sirkirby/ngrok

docker pull wernight/ngrok:latest

Starting your tunnel

On the host, I'm exposing a local rest API on port: 5000, which Ngrok will expose on the internet. I also want to access the Ngrok request inspector running inside the container on port: 4040.

docker run --rm -p 4040:4040 -p 5000:5000 -e NGROK_PORT="host.docker.internal:5000" \
-e NGROK_AUTH="{your_account_key}" -e NGROK_SUBDOMAIN=mycname wernight/ngrok

NOTES AND CONSIDERATIONS

  • On Mac, the host address changes, so you need to utilize the reserved DNS name host.docker.internal in your port binding. See https://docs.docker.com/docker-for-mac/networking/#httphttps-proxy-support for more info.
  • The NGROK_AUTH and NGROK_SUBDOMAIN env args are optional and are primarily used with a paid account. Free accounts will generate a random CNAME each time you initialize a tunnel.
  • You may run into a port conflict with your service when using explicit port binding. Start your service before the docker container, which should mitigate the issue.
  • Rather than binding the ports individually, you can use the host network directly via the --net=host flag. When used in combination with -p, the port mappings are ignored. The only limitation I found with this solution was the inability to connect to the ngrok HTTP inspector from the browser.

Conclusion

Pretty simple! Slack commands (or your use case) are now flowing to your local service; no policy exceptions are required.