Launching Nginx Proxy Manager
Nginx Proxy Manager is what I use to manage all the reverse proxies to different web apps. It also handles my ssl certificates. Now I will tell you how to get it running.
In my first blog post I mentioned Nginx Proxy Manager. This is what I use to manage all the reverse proxies to different web apps. It also handles my ssl certificates. Now I will tell you how to get it running.
Docker Network
To make life easier (and more secure), we're going to create a seperate docker network for our service. We will attach NPM (Nginx Proxy Manager) and all services we want to expose to this network. Putting them in the same network allows NPM to act as a reverse proxy for those services, without those services having to expose their ports to the host.
We will be creating a simple bridge network. The command is simple:
root@jveweb:/opt/DockerStacks# docker network create npm_network
You can get an overview of your networks with following command:
root@jveweb:/opt/DockerStacks# docker network ls
NETWORK ID NAME DRIVER SCOPE
082aeb477221 bridge bridge local
37c59c54a11b host host local
e483949bc0d2 none null local
f0eecf642da8 npm_network bridge local
The bridge
, host
and none
networks are default. For more information on those read this stackoverflow entry. If you want more detail about any of those networks you can issue the docker network inspect <NETWORK_NAME> command
.
The Files
docker-compose.yml
I will be using docker(-compose) to get NPM up and running. Create a folder with two files: docker-compose.yml
and .env
. The first part of the docker-compose.yml
file looks very similar as the one in my post about setting up ghost.
version: '3'
networks:
default:
external:
name: npm_network
The version
tag defines the syntax version of docker-compose we will be using. The external npm_network
(the one we just created) will be the default network for the containers in this compose file.
The next part describes the services we will be using. Apart from Nginx Proxy Manager itself, we will also need a MariaDB service. Both of those containers are build and maintained by the creator of NPM jc21. He has his own version of the MariaDB container as he needed to force it to use the aria storage engine.
services:
npm-app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80'
- '443:443'
- '81:81'
depends_on:
- npm-db
environment:
DB_MYSQL_HOST: "npm-db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "${MYSQL_USER}"
DB_MYSQL_PASSWORD: "${MYSQL_PW}"
DB_MYSQL_NAME: "${MYSQL_DB}"
volumes:
- ${DATADIR}/npm/data:/data
- ${DATADIR}/npm/letsencrypt:/etc/letsencrypt
npm-db:
image: 'jc21/mariadb-aria:latest'
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: "${MYSQL_ROOTPW}"
MYSQL_DATABASE: "${MYSQL_DB}"
MYSQL_USER: "${MYSQL_USER}"
MYSQL_PASSWORD: "${MYSQL_PW}"
volumes:
- ${DATADIR}/db/data:/var/lib/mysql
Service npm-db
describes the MariaDB instance. The environment variables will be filled at runtime using the .env
file we created. The variables are self-explanatory, but if you want more information check the GitHub repository or the DockerHub page of the upstream image. The volume is where MariaDB will store its database files, the ${DATADIR} variable will be set in the .env
file.
For the npm-app
service; we reuse the same MYSQL_*
variables to create the connection to the database. As DB_MYSQL_HOST
we will set the name of the MariaDB service: npm-db
. That will be the hostname of that container in the npm_network
. The DB_MYSQL_PORT
points to the default port 3306. As this container needs the database service, we use depends_on
. It makes sure the database container is running before starting NPM.
As the outside world will connect using http and https to this application we have to expose those ports through the host. We also expose port 81 to get to the admin interface of NPM.
.env
The contents of the .env
file are as follows:
DATADIR=/media/docker/npm
MYSQL_USER=*****
MYSQL_PW=*****
MYSQL_ROOTPW=*****
MYSQL_DB=*****
Replace the *****
values with your values.
Now you can run docker-compose config
to see how it will look:
root@jveweb:/opt/DockerStacks/npm2# docker-compose config
networks:
default:
external:
name: npm_network
services:
npm-app:
depends_on:
- npm-db
environment:
DB_MYSQL_HOST: npm-db
DB_MYSQL_NAME: '*****'
DB_MYSQL_PASSWORD: '*****'
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: '*****'
image: jc21/nginx-proxy-manager:latest
restart: unless-stopped
volumes:
- /media/docker/npm2/npm/data:/data:rw
- /media/docker/npm2/npm/letsencrypt:/etc/letsencrypt:rw
npm-db:
environment:
MYSQL_DATABASE: '*****'
MYSQL_PASSWORD: '*****'
MYSQL_ROOT_PASSWORD: '*****'
MYSQL_USER: '*****'
image: jc21/mariadb-aria:latest
restart: unless-stopped
volumes:
- /media/docker/npm2/db/data:/var/lib/mysql:rw
version: '3.0'
Launch
Now run docker-compose up -d
in the folder and all will be launched in the background. Now you can browse to <YOUR_SERVER_IP>:81 and start setting up your reverse proxies. More information about configuring NPM itself can be found on the official page.
Now you can also launch the Ghost container we created in the previous post.
Considerations
If you want you can create a reverse proxy inside NPM to his own admin page. This would allow you to stop exposing port 81. But I like to keep it open, as a failsafe. The port is blocked by a firewall, so only people with a VPN connection can connect to it anyway.
The database container does not have to be in the same network. It could be on its own network. This would mean other services can't connect to it by accident. But this would also mean we would need to attach an extra network to the NPM container.