Private and Proxied Docker Networking Setup – How to Configure

dockerfirewallnetworking

Desired schema

Above is a layout of the desired network. I am struggling with getting it just right. The internal link from the router is not relevant for this problem.

Requirements:

  1. The only container directly exposed to the public, should be the proxy.
  2. All containers can communicate with eachother, preferrably via host name (see user-defined docker network).
  3. Some services such as Portainer require internet access (outgoing) to retrieve some data from their servers but should otherwise not be directly accessible.
  4. The host may be allowed to access container services directly, but only from the host itself, not externally.

What I have achieved so far:

  1. The proxy correctly proxies the desired containers to the outside.
  2. All containers can communicate with eachother and their IP can be resolved via service name.

Problems:

  1. All containers are still accessible directly, without using the proxy (by using their exposed ports)
  2. If they are not in a bridge network they don't have internet, but if they are, they are accessible directly.

I believe 3 networks are necessary:

  1. An internal network for the containers themselves
  2. A network that has internet (but somehow does not expose any ports)
  3. A network that will be used by the proxy that gets exposed to the public

I am configuring everything via Portainer, and the docker host is using Firewalld. Thanks in advance for any suggestions!

Best Answer

Alright so after revisiting this issue, I was reading a cheatsheet for Docker, and realized you can bind to an interface. By default, if no interface is specified, it binds to 0.0.0.0, but by specifying, for example 127.0.0.1:80:80 means only the docker host will be able to access the container on port 80.

This way, I specified my private network (192.168.1.0/24) as the interface to bind to for all exposed ports of my docker containers (so I can access directly from within my network) and only the Caddy proxy I bound to 0.0.0.0. Now this is behaving like I want and no special setup was needed.

Additionally I linked all containers together to the same user-defined network called internal in which I set restrict external access to true. This way, the containers can talk to eachother, can be resolved by container name and cannot be accessed by anything but my private network. All services from all containers are exposed to the public only by the reverse proxy.