I was working on a NextJS project recently. For those who don't know, NextJS is the most popular React framework with in-built SSR support.

Now, people use SSR for many reasons but the most common ones are as follows.

  1. To render pages on the server-side and hence reduce latency on the client-side.
  2. To protect their APIs.

I needed NextJS and SSR for the 2nd benefit that is, protecting my API. I had two Dokku apps for my project - frontend and backend and I had to make it such that frontend can access backend internally. Also, the backend should not be available publically.

I found that the easiest way to do so is by using Docker networks. The idea here is to create a network and assign that network to both frontend and backend apps. With this, both apps will be able to access each other's networks.

To do so, we ssh to the server running our Dokku apps. Then we create a Docker network.

docker network create mynetwork

You can verify that the network has been created as follows.

docker network list

Once that is done, we simply assign it to our frontend and backend apps.

dokku docker-options:add frontend deploy "--net mynetwork"
dokku docker-options:add backend deploy "--net mynetwork"

After this, just restart your apps.

dokku ps:restart frontend
dokku ps:restart backend

frontend and backend will now be able to access each other's network internally. To verify, just enter the frontend container and try to access the backend network as follows.

dokku enter frontend
# once entered
curl http://backend.web.1

The URL backend.web.1 comes from the container name. We know that Dokku renames the containers as <app name>.<process name>.<number>. Since you will probably be serving the API from the web process, we use the URL backend.web.1.

From that curl request, we should get the data that the backend serves at route /. Note that in the above case it is assumed that backend is running the server at port 80.

If you have a different port that serves your backend, you should be able to access it normally.

# in frontend container
curl http://backend.web.1:5000

The next step is disabling public access to the backend. Dokku's documentation says to do this by running the following command.

dokku domains:disable backend

This gives a random high port to your backend app. You can either use it or just use a custom random port. For example, here I forward port 5000 in the container to host's 5426.

dokku proxy:ports-set backend http:5426:5000

This allows you to access the backend app from http://<serverIP>:5426 as well as access it internally in the frontend from http://backend.web.1:5000.

Dokku has no way to completely disable exposing a web service to the public so this is your best bet. If you do want to do so, you should be able to do it by modifying the NGINX configuration. But I believe that is not needed for most applications.

That's it. By doing everything in this article, you can access your Dokku apps internally without leaking it publically.