The little website that could

There could not have been a better way to start 2017 than by fixing this website. What started as a small task of self-hosting actually spiraled into many smaller projects. The additional time demands, along with a full-time job, culminated to breaking ivanarellano.com for nearly a year. And yet I've been able to script a way, a convenient one, to spin-up this website and a photography site. Enter Docker Compose.

Background

First, I have to explain how Docker can be a downside. I quickly started writing scripts after going through an enormous amount of setup steps for each container. All setup scripts can then be fired in a correct sequence from another script to re-create this website, like a reset.

For added convenience, I saved each script onto private gists, so that I could download and execute them in a terminal, with something like wget -qO - https://gist.github.com/ivanarellano/[gist_hash]/raw/start_website.sh | sudo bash.

Initializing containers this way isn't so bad at first, but there are too many pieces to maintain. There are also unforeseen issues. Containers can fail to restart after a server restart. The scripts needed constant documentation for every new solution. The tech debt was real and I started regretting containers.

How it went uphill, with Docker Compose

Docker Compose is able to run multiple containers with only one file to describe dependencies. After installing it, you should be able to use docker-compose from your terminal. All of your container dependencies are then listed in a file named docker-compose.yaml. Here is a sample based on this website:

# Describes a Ghost blog with a host name, build variant, Mailgun info, and Let's Encrypt info
my_blog:  
  image: ghost
  volumes:
    - /my_path/blog:/var/lib/ghost
  environment:
    - VIRTUAL_HOST=example.com
    - NODE_ENV=production
    - EMAIL_SERVICE=Mailgun
    - EMAIL_USER=postmaster@mg.example.com
    - EMAIL_PASSWORD=1234567890
    - LETSENCRYPT_HOST=example.com
    - LETSENCRYPT_EMAIL=user@example.com
  restart: always

# Describes a Koken photo gallery with a host name and Let's Encrypt info
my_photo_gallery:  
  image: koken/koken-lemp
  volumes: 
    - /data/koken/www:/usr/share/nginx/www
    - /data/koken/mysql:/var/lib/mysql
  environment: 
    - VIRTUAL_HOST=sub.example.com
    - LETSENCRYPT_HOST=sub.example.com
    - LETSENCRYPT_EMAIL=user@example.com

# Describes an Nginx web server that proxies to other container's nginx server
nginx-proxy:  
  image: jwilder/nginx-proxy
  ports:
    - "##:##"
    - "##:##"
  volumes:
    - /my_path/certs:/etc/nginx/certs:ro
    - /etc/nginx/vhost.d
    - /usr/share/nginx/html
    - /var/run/docker.sock:/tmp/docker.sock:ro
    - /my_path/vhost.d:/etc/nginx/vhost.d
  restart: always

# Describes a container that automatically creates Let's Encrypt certifications for each other container
# If you use this, consider donating: https://letsencrypt.org/donate/
letsencrypt:  
  image: jrcs/letsencrypt-nginx-proxy-companion
  volumes:
    - /my_path/certs:/etc/nginx/certs:rw
    - /var/run/docker.sock:/var/run/docker.sock:ro
  volumes_from:
    - nginx-proxy
  restart: always

It's straightforward to run this script with docker-compose up. You can optionally add -d to run detached containers in the background. Containers can be stopped with docker-compose stop and upgraded with docker-compose pull.

The website's future

This website is going to be my grounds for ideas, thoughts, and stories. Though, less of the stories at the start. It's going to be about discovering new hobbies, game programming, some math, and it's going to be messy while I try to explain it all. Here's to 2017!