Improving Containers with Docker Compose

In my last post, I walked through how to run Ghost in a container on a really cheap VM with Digital Ocean. It's a great start, but while I have reproducibility in the container, I can't be sure that I supplied the correct parameters when I run the container. That is, docker run -e url=<host> -p <dest:src> -v <dest:src> --restart=always ghost:3.33.0-alpine. What if I need to restart? Can I be sure I did it exactly the same each time? Sure, I could create a simple bash script to start the container, but there's a better solution.

Docker 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. In essence, you use a single YAML file that describes multiple services and start and stop these services with a single command. Furthermore, we have the config file available in case we need to make any tweaks later on.

So let's get into it.

Install Docker Compose

Installing Docker Compose is super simple. Just run:

$ apt install docker-compose

This will go ahead and grab Docker Compose along with any dependencies. It won't be the latest version, but I don't care much about that.

Configure Docker Compose

Configuring the container is simple (in as much as any YAML config file is simple). Hey, I don't mind them, but I know a lot of people who seem to think YAML destroyed the internet.

Create the file /var/www/anthonyison.com/docker-compose.yaml with the following contents:

version: "3.1"

services:
  ghost:
    container_name: ghost
    image: ghost:3-alpine
    restart: always
    ports:
      - 2368:2368
    environment:
      - NODE_ENV=production
      - url=https://anthonyison.com
    volumes:
      - ./content:/var/lib/ghost/content

The content folder should be immediately off this folder. The content folder will be mapped to the /var/lib/ghost/content folder when the container is started. The config file also sets up the url, ports, image, container name, etc.

If we wanted to step things up, we could also start a MySQL container and set the config for Ghost to use MySQL instead of SQLite as the database. I don't care to do that for now.

We can now start the Ghost container like so:

$ cd /var/www/anthonyison.com
$ docker-compose up -d

To shut down all of the containers started by Docker Compose, we could then run:

$ docker-compose down

Conclusion

We now have a configuration file for the parameters required to run our Ghost container for the blog. This reduces the complexity (or at least makes it more reproducible) since the container can be started with a simple docker-compose up command.

As we've discovered in this post, Docker Compose helps to simplify the startup and basic orchestration of containers. Kubernetes would take this to a whole new level, but I can't fit a Kubernetes cluster into my limited budget just yet. For now, Docker Compose will fit the bill while keeping my running costs right down.