I decided that it was time to create the personal project that I already had in mind for quite some time: a blog to record the interesting things I find as a software developer. More than that, I also wanted to learn something out of it, and to have some fun while doing it.
I thought Docker would be ideal to organize the services I need. Simply put, Docker is a tool that allows creating and managing applications inside containers. I ended up having three of them, one for each of the services I needed:
Table of Contents
Before starting
First I chose and bought my domain, and my VPS to host the applications. I'm using Vultr as both my VPS and DNS provider.
I obtained an SSL/TLS certificate for my blog to be accessed through HTTPS. For that purpose, I used Certbot to request a certificate from Let's Encrypt for free!
sudo apt install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install certbot
sudo certbot certonly --standalone -d blog.afmonteiro.pt
The certificate is downloaded to the folder /etc/letsencrypt/live/example.com/
.
Install Docker
My VPS is running a Linux machine based on Debian, so I used apt
to manage my packages, following the official Docker documentation.
- Install all the necessary packages:
sudo apt install apt-transport-https ca-certificates curl software-properties-common
- Add Docker's GPG key to authenticate the packages:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
- Verify the key's fingerprint:
sudo apt-key fingerprint 0EBFCD88
- Add the
stable
Docker repository:sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- Update the package index and install Docker Community Edition:
sudo apt-get update sudo apt install docker-ce
- Add your Linux user to the
docker
group:sudo usermod -aG docker $USER
- Download and install the latest version of Docker Compose, and set permissions to run it. I'm running the version 1.24.1, check the releases page for the latest version.
sudo curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
Now that Docker and Docker Compose are installed, the process can continue to its next step - installing the three main components, which will be listed in a single Docker Compose file. For those who don't know Compose, it is described as the following in the official documentation:
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.
Creating the Docker Compose file
-
Create and change to the directory that will hold all the Docker services:
mkdir docker && cd docker
-
Create an empty file named
docker-compose.yml
:touch docker-compose.yml
-
Open
docker-compose.yml
with your favorite text editor, and paste the following snippet. ReplaceMY_DOMAIN
with your domain, and insert a new database password whereMY_DB_PASSWORD
appears.# docker/docker-compose.yml version: '3' services: ghost: image: ghost:latest restart: always depends_on: - db environment: url: MY_DOMAIN database__client: mysql database__connection__host: db database__connection__user: root database__connection__password: MY_DB_PASSWORD database__connection__database: ghost volumes: - /opt/ghost_content:/var/lib/ghost/content db: image: mysql:5.7 restart: always environment: MYSQL_ROOT_PASSWORD: MY_DB_PASSWORD volumes: - /opt/ghost_mysql:/var/lib/mysql nginx: build: context: ./nginx dockerfile: Dockerfile restart: always depends_on: - ghost ports: - "80:80" - "443:443" volumes: - /etc/letsencrypt/:/etc/letsencrypt/ - /usr/share/nginx/html:/usr/share/nginx/html
-
Docker Compose creates a few Docker bind mounts:
/var/lib/ghost/content
and/var/lib/mysql
inside the containers are mapped to/opt/ghost_content
and/opt/ghost_mysql
, respectively. These locations will store Ghost and MySQL data.- A bind mount for
/etc/letsencrypt/
is created for NGINX to access the Lets Encrypt certificates. - NGINX also uses a bind mount for
/usr/share/nginx/html
so that it can access the Let’s Encrypt challenge files that are created when your certificate is renewed.
Directories should be created if they do not exist already:
sudo mkdir /opt/ghost_content sudo mkdir /opt/ghost_mysql sudo mkdir -p /usr/share/nginx/html
Create the NGINX Docker Image
- Create a new directory
nginx
(inside the previously created directory):mkdir nginx
- Create a file named
Dockerfile
and paste in the following contents:# nginx/Dockerfile FROM nginx:latest COPY default.conf /etc/nginx/conf.d
- Create a file named
default.conf
and paste in the following contents. ReplaceMY_DOMAIN
with your own domain.# nginx/default.conf server { listen 80; listen [::]:80; server_name MY_DOMAIN; # Useful for Let's Encrypt location /.well-known/acme-challenge/ { root /usr/share/nginx/html; allow all; } location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name MY_DOMAIN; ssl_protocols TLSv1.2; ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_certificate /etc/letsencrypt/live/MY_DOMAIN/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/MY_DOMAIN/privkey.pem; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_pass http://ghost:2368; } }
Run and test the new blog
When the environment is ready, run docker-compose up -d
. This creates a daemon which runs the components in the background. To stop the instances, run the command docker-compose down
. These commands should be run inside the folder that contains the Docker Compose file!
The command docker-compose up
can be issued without the flag -d
so the logs are shown in the console, running Docker Compose in attached state, this being useful for seeing errors if one occurs. To shut down the services in this case, press the combination CTRL-C
in your keyboard.
Final thoughts
Docker Compose is an ideal tool for a simple environment in which multiple applications need to be running in parallel and communicating with each other.
Creating an environment using Docker Compose may seem easy, but some unexpected errors may occur to some people. I had some trouble configuring the different components which required me to do some research on the side. Please use this guide at your own discretion, and feel free to leave me a comment if you have any doubt or suggestion.
Source: How to Install Ghost CMS with Docker Compose on Ubuntu 18.04