Expose Docker Container services on the Internet using the ngrok docker image

Lucas Jellema
Jan 6, 2019 · 5 min read

The challenge: you are running a service, API or web application in a Docker container, locally on your laptop or in a cloud based VM or container platform. You would like to provide access to external consumers — yourself on your smart phone, a piece of code running in a cloud environment, a colleague on your local network or on the other side of the world. The question is: how to get requests from these external parties to the application that does not and cannot [easily] expose and external endpoint.

In this article, we will look at how ngrok — a tool and a cloud service — makes this happen. It generates a public URL and ensures that all requests sent to that URL are forwarded to a local agent (running in its own, stand alone Docker container) that can then pass them on to the local service. See https://technology.amis.nl/2016/12/07/publicly-exposing-a-local-service-to-nearby-and-far-away-consumer-on-the-internet-using-ngrok/ for an introduction to ngrok.

Assuming you are working on a Docker host — a system that can run Docker containers, here are some steps to try out:

First steps with ngrok and Docker

Define a logical network `myngroknet` to link two or more containers together:

docker network create myngroknet

Run a Docker Container called www based on the nginx image and associate it with the mynrgoknet network:

docker run -d -p 80 –net myngroknet –name www nginx

Image for post
Image for post

Run a container called ngrok based on the ngrok container image. Associate the container with the myngroknet network; this enables the container to access container www using its container name as hostname (for example http://www). Expose port 4040 — where the ngrok inspection interface is accessed. Specify that ngrok should open a tunnel (expose a public url) for HTTP requests to port 80 on container www:

docker run -d -p 4040:4040 –net myngroknet –name ngrok wernight/ngrok ngrok http www:80

You can now access the ngrok monitor: access port 4040 on the Docker host in your web browser (see later in this article for an example).

Either from the ngrok monitor of from the command line in the Docker host using `curl $(docker port ngrok 4040)/api/tunnels` get the public url that has been assigned to the ngrok session.

Image for post
Image for post

Access that URL from any browser on any machine anywhere in the world. The request from the browser should be handled by the Docker Container, in this case the www container running nginx.

Image for post
Image for post
Accessing nginx running on my laptop from a different computer -anywhere in the world
Accessing the Docker based nginx service no any mobile phone

Expose a local Node Application on the Internet

On the Docker host — for example the Ubuntu Linux VM created with Vagrant as described here — clone the code-cafe GitHub repository (or use any other Node application).

git clone https://github.com/AMIS-Services/code-cafe

Then navigate to the directory that contains the Node application that we will expose on the internet:

cd code-cafe/jsonata-query-and-transform-json-documents

And run a Docker container with a Node runtime called json-server; the current directory ($PWD) is mapped into the container at /usr/src/app. The container is associated with the myngroknet network that makes it accessible later on to the container running ngrok.

docker run -it –rm -p 8080:8080 -v “$PWD”:/usr/src/app –net myngroknet –name json-server node:10 bash

Once the container is started, you will find yourself in a shell in the container. Perform the following steps to copy the sources, install dependencies and run the Node application:

cp -r /usr/src/app /app

cd /app

npm install

node json-server

Image for post
Image for post
Cloning the GitHub repo, npm installing the dependencies and running the application

The Node application is up and listening at port 8080. You can verify this from the Docker Host `http://localhost:8080/?region=Europe` (or possibly the Windows host: `http://<vagrant VM IP>:8080/?region=Europe`.

Image for post
Image for post
Accessing the Node application locally — to see it is working

Run the ngrok Docker Container to create a tunnel from the a newly assigned public URL to port 8080 on the json-server container (at which the Node application is handling requests )

docker run -d -p 4040:4040 –net myngroknet –name ngrok wernight/ngrok ngrok http json-server:8080

Image for post
Image for post
Running the ngrok container — linking into the Docker network with the Node runtime container

Inspect ngrok at port 4040 and learn about the public url — or use `curl $(docker port ngrok 4040)/api/tunnels` to get that url.

Image for post
Image for post
Using the ngrok console — exposed by the ngrok container at port 4040

Access the Node application from any client anywhere in the world (for example your mobile device) at the url: `http://<assigned ngrok id>.ngrok.io/?region=Europe`

Image for post
Image for post
Response from the Node application — from any machine anywhere in the world

So what do we have running now?

Two containers on a Docker host — which can be a local one or a cloud based host. One container with a Node JS runtime and a custom Node application (cloned from GitHub) and the other with the ngrok client. The containers are linked through a Docker network. The ngrok client is connected to the ngrok public site — requests sent to a specific URL on that site are relayed to the ngrok client that in turn sends these requests to the companion container that it acts as a side car for.

Image for post
Image for post
Sketch of setup — the Node container with its ngrok sidecar that receives public requests on its behalf

Alternative Offerings

Ngrok is not the only option for exposing local services through a public url. Two alternatives are briefly introduced below.

Localtunnel

localtunnel exposes your localhost to the world for easy testing and sharing! No need to mess with DNS or deploy just to have others test out your changes.

Check out: https://github.com/localtunnel/localtunnel

Localtunnel is available in a Docker Container, very similar to the ngrok solution discussed overhead:

https://hub.docker.com/r/efrecon/localtunnel/ .

Note: localtunnel can use localtunnel.me as its server — or you can run your own server to handle all requests (see: https://github.com/localtunnel/server)

Vagrant Share

Vagrant Share allows you to share your Vagrant environment with anyone in the world, enabling collaboration directly in your Vagrant environment in almost any network environment with just a single command: `vagrant share`.

See https://www.vagrantup.com/docs/share/ for details and http://www.gizmola.com/blog/archives/121-Vagrant-Share-and-Ngrok.html for more background.

Originally published at technology.amis.nl on January 6, 2019.

Oracle Groundbreakers

Aggregation of articles from Oracle engineers…

Lucas Jellema

Written by

Lucas Jellema is solution architect and CTO at AMIS, The Netherlands. He is Oracle ACE Director, Groundbreaker Ambassador, JavaOne Rockstar and programmer

Oracle Groundbreakers

Aggregation of articles from Oracle engineers, Groundbreaker Ambassadors, ACEs, and the developer community on all things Oracle Cloud. The views expressed are those of the authors and not necessarily of Oracle.

Lucas Jellema

Written by

Lucas Jellema is solution architect and CTO at AMIS, The Netherlands. He is Oracle ACE Director, Groundbreaker Ambassador, JavaOne Rockstar and programmer

Oracle Groundbreakers

Aggregation of articles from Oracle engineers, Groundbreaker Ambassadors, ACEs, and the developer community on all things Oracle Cloud. The views expressed are those of the authors and not necessarily of Oracle.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store