Docker Networks and Nginx Proxy Manager
A part of my home lab configuration is the existence of Nginx Proxy Manager. What NPM does is it takes an incoming request, usually a domain and forwards it to the correct service. In the example about you can see that the request for the website domain.cxx
is searched DNS magic, for now, forwards that request to your domains IP address. If you're self-hosting a blog for example on your network, the IP address would typically be your public IP. You can find out what your IP is by going here.
From there your domain would point to your IP and then your router would see what it should do with a request for that IP and port, often 80 for http
and 443 for https
. The server that has your services and NPM would have its ports open for 80 and 443. NPM would take the request now in the form of domain.cxx:443 and forward that to the correct service and port on your network. Then you would get the content. Now this is a highly simplified take on what happens to request and NPM, but it helps me understand it better.
Because NPM is a reverse proxy manager it means you don't have to expose multiple ports for many services and some services even use the same ports. NPM will just 1st forward the request to the service at the correct port. That's a pretty nice thing to have, reverse proxy that is, because we don't need to expose more ports than we have too, so it hides are network behind a proxy.
Another thing that I do for security is to keep my databases on their own docker network and are only reachable by their docker container app that is on the same docker network. For example a configuration of Ghost that I would use for production would have two parts, the docker app ghost-app
and the docker database ghost-db
. ghost-app
would be two networks as it needs to be able to access ghost-db
, a frontend
docker network that is external would be used with backend
network that only ghost-db
would be a part of, no other networks. This in my opinion is much better for security and while it's the end all to threats it makes me feel a little better. How a docker compose would look like with my principles:
As you can see the frontend
network is external and sits in the same network as Nginx Proxy Manager, so that they are able to communicate with each other. backend
is left without the modification of external: true
because we want Docker to create an isolated Docker network that would be ghost-backend
where the ghost-app
and ghost-db
sit inside so that they can communicate with each other. This is that's important because Ghost will not work in production mode unless It's paired with a MySQL database. With that now all said there is the Docker compose that I would use:
version: '3'
networks:
frontend:
external: true
backend:
services:
npm-app:
image: jc21/nginx-proxy-manager:latest
container_name: nginx-app
depends_on:
- npm-db
restart: always
ports:
- "80:80"
- "81:81"
- "443:443"
environment:
- DB_MYSQL_HOST=npm-db
- DB_MYSQL_PORT=3306
- DB_MYSQL_USER=npm
#make sure you change this to a secure password!
- DB_MYSQL_PASSWORD=yoursecurepassword
- DB_MYSQL_NAME=npm
volumes:
- /your/path/nginx/data:/data
- /your/path/nginx/ssl:/etc/letsencrypt
networks:
- frontend
- backend
npm-db:
image: jc21/mariadb-aria:latest
restart: always
container_name: nginx-db
environment:
#make sure to change this to a secure root password!
- MYSQL_ROOT_PASSWORD=rootyoursecurepassword
- MYSQL_DATABASE=npm
- MYSQL_USER=npm
#make sure this is the same as above in npm-app
- MYSQL_PASSWORD=yoursecurepassword
volumes:
- /your/path/nginx/db:/var/lib/mysql
networks:
- backend
With that up and running with the command docker compose up -d
in your favourite terminal you should now have NPM running. Visit your local host on port 81 or 443 to configure NPM.