Using ngrok in Docker

2021-08-11 2 min read

You can run multiple services as a single app with docker-compose. If you are using ngrok in your development environment, you may also need to make it a Docker service. Should you? Probably not. But if you want to, you will see how to do it in this article.

Creating an ngrok service

First of all, create a folder named ngrok. You should then create a symbolic link in that folder that references to the actual ngrok executable. For instance,

ln -s ~/.local/bin/ngrok ./ngrok/ngrok

In the ngrok folder, you now have a symbolic link to the ngrok executable. Next, you should create a configuration file for ngrok. In the same ngrok folder, create a file like the one below:

ngrok.yml
web_addr: 0.0.0.0:4040
authtoken: <YOUR_AUTH_TOKEN_HERE>
log: stdout

Then define your ngrok service in the docker-compose.yml file:

docker-compose.yml
services:
  # ...
  ngrok:
    profiles:
      - ngrok
    image: nginx
    volumes:
      - ./ngrok:/code/
    command: /code/ngrok http nginx:80 -config=/code/ngrok.yml
    ports:
      - 4040:4040

Did you notice the profiles section in the above file? You can find more about it in this article.

Accessing the ngrok service

You can access it on localhost:4040. You may also need to access the ngrok service from other services. Moreover, you may want to get the current ngrok address dynamically. Below is a sample Python code I wrote for this:

def get_ngrok_url(startswith: str = 'https://') -> str:
    ngrok_tunnels = 'http://ngrok:4040/api/tunnels'
    r = os.system(f'curl {ngrok_tunnels} > tunnels.json 2> /dev/null')

    if r != 0:
        os.system('rm -f tunnels.json')
        raise OSError('Either ngrok is not running or curl is not installed.')

    with open('tunnels.json', 'r') as f:
        tunnels = json.loads(f.read())
        os.system('rm -f tunnels.json')

        for tunnel in tunnels['tunnels']:
            if tunnel['public_url'].startswith(startswith):
                return tunnel['public_url']

print(get_ngrok_url)
# https://bc2aadf5e32f.ngrok.io

This will return the public URL of the running ngrok instance according to the HTTP protocol you specified.

Date: 2021-08-11
Categories: development