Self Hosting Websites using Docker
I decided to self host Ghost CMS for this blog, and needed to expose its interface to the public. I found Nginx Proxy Manager (NPM) quite appealing, and decided to give it a try.
Background
There are many ways to host your own website(s). The combination I chose and documented here is just one of them. In particular,
- I have obtained a VPS in the cloud, running Ubuntu.
- In the past, I would just install the plain old Nginx, log in into the machine remotely, and manage services using the command line.
- Recently I found many people using NPM, and wanted to give it a try.
- As switching to NPM almost means I need to use Docker as the basis for the services I am hosting later, more investigations are needed, especially for the case where the services to be hosted do not run as Docker containers.
Preparation
Naturally, before deciding on NPM I have searched the web for related information. This process highly subjective for different people, and for different purposes. For me, at least right now, I will just make sure the tool is widely used and frequently maintained, has no obvious drawbacks and bad reputation, and will not lock me down so deep that I cannot leave it without a lot of reworking.
To install NPM, I start with skimming the web for common practices, while paying attention to the official website at the same time. I don't want to just jump in following the official website and filling the blanks myself, only to find later that there are common or better practices people use. However, while "unofficial" blog posts and guidelines can provide quicker introduction, more well-rounded instructions, and useful feedbacks in shorter passages, they may contain outdated information.
Installation
First create a "parent" folder that will hold container configurations and working spaces for NPM and other services later.
mkdir ws
cd ws
Create the folder for NPM:
mkdir npm1
cd npm1
Head to official website for setup instructions, then create docker-compose.yaml
with the following content:
networks:
mynet:
name: mynet
services:
mynpm:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80' # Public HTTP Port
- '443:443' # Public HTTPS Port
- '81:81' # Admin Web Port
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
network:
- mynet
The major modifications compared to the website are:
- remove the version property
- define a network
mynet
, on which this NPM and other containers will run later - change the container "block" name to
mynpm
for clear reference later (can also setcontainer_name
)
Now launch NPM using docker compose:
docker compose up -d
after which, you can also see the running logs by
docker compose logs -f
You can access NPM via http://localhost:81
and initialize the admin account. However, since the procedure is over HTTP, entering passwords would not feel right. Since we will be serving main services, likely including the NPM itself, it is better to obtain domain names, bind them to corresponding IPs, and try to run things over HTTPS. For more detailed setup, see this lab.
Serving Another Site
Assuming you have set up NPM and can access it using the domain name of your choice over HTTPS. It is easy now to add another site, on another domain.
Let's just use a bare Nginx container as an example. Suppose you have created the domain docs.example.com
and bound to the same IP where the NPM is running. Create another folder (next to NPM's)
mkdir docs
cd docs
Create inside the docker-compose.yaml
file:
networks:
mynet:
name: mynet
external: true
services:
docs:
restart: unless-stopped
image: nginx:1-alpine
expose:
- 80
# volumes:
# - ./html/:/usr/share/nginx/html
networks:
- mynet
Launch the service
docker compose up -d && docker compose logs -f
If everything is running OK, back to the NPM page, and add the following proxy host (please rename accordingly):
- domain name:
docs.example.com
- scheme, hostname, and port:
http
,docs
,80
- obtain the SSL certificate
You can see if the bare Nginx site is accessible by visiting https://docs.example.com
.
If you want to try some HTMLs of your own, you can uncomment the volumes
lines in the docker compose file, create an html
subfolder, and place index.html
and other files in it.