Schrödinger's cat is a famous hypothetical experiment designed to point out a flaw in the Copenhagen interpretation of superposition as it applies to quantum theory.
Sometimes I'm cheap. As in "$5?! WTF!" cheap. And recently my Digital Ocean bill was nearing $20 a month, when I figured WTF? I run maybe 5 small websites (Wordpress and Ghost), and play around with personal projects (Node and stuff), I shouldn't have to pay this kind of money. What I should do, though, is to run every site in a container, of course, and just use 1 droplet instead of 3. What could possibly go wrong?
Well, apperantly, many things could go wrong. From proper domain and port mapping to SSL certificates and config file permissions. Especially, if you start the process with Ghost, the less popular blogging platform than WordPress. I chose Ghost as a platform for a variety of reasons (basically, I just like it), and I will outline them sometime later (I need time to come up with things besides "I just like it"), so join me on this bumpy journey to the containerized Ghost.
Ghost Docker Container
First thing you need is, not surprisingly, a proper Docker container. Ghost doesn't officially support Docker, however, this is Internet in 2018, and of course there're people who made this happen for us.
Here it is: Ghost Docker container.
You could probably get away with any of the setup options on the page, at least to some extent, but I'd suggest going with the
docker-compose one. Is it the best one? Is it the easiest one? I don't really know. What I do know, that after experiencing all sorts of issues with other ways to spin a working setup, I ended up with this one actually working out in the end. Besides, it gives you a way to extend your setup later, which certainly is a plus. We'll get back to this whole
docker-compose thing later, after we have a server to run it on.
Now, let's create a droplet for our server. Here's how:
Just kidding, simply go to Digital Ocean and create a small droplet (or use an existing one). I'm using Ubuntu 16, you can use whatever you prefer as long as it supports Docker.
Now we're ready to get move forward with the Docker part.
Bringing things together
Let's connect to the droplet we just created via
ssh and install Docker. The last part is pretty easy:
apt-get update apt-get install docker.io
Next step is to create a
ghost.yml file for our
touch ghost.yml nano ghost.yml
Here's what we're going to put it the
ghost.yml (disregard everything else):
version: '2' services: ghost: image: ghost:2.2.4 restart: always ports: - 80:2368 environment: url: https://[YOUR DOMAIN NAME]
There we go. This part it complete, and we are almost there!
It's 2018, and not having SSL for a domain is no longer acceptible. Not only major browsers see this kind of non-SSL websites as a threat (and rightly so), with free and really-really easy certificate installations from Let's encrypt (simple CLI wizard) and Cloudflare (web), there's no justification to not have an SSL certificate for your domain. It is SO simple now, that we don't really need to do anything to make our Ghost accessible via
HTTPS! All there is to it, is obtaining a certificate for your domain and pointing Ghots configs to
https://[your domain]. Done and done.
Now we need to actually spin-up a container with a ghost inside (see what I did here?):
docker-compose -f ghost.yml up
Finish line! Now we have (hopefully) our Ghost up and running inside of container in a droplet in the cloud 1. The only thing left is to convince our Ghost that its url is not
https://[your domain]. In fact, we already have it in our
environment variable of
ghost.yml. However, I found out that it's not necessarily enough, and we do need to update Ghost config. Which is sitting inside of a container. With no editor installed and no Internet access. Well, let's learn a bit more about workarounds:
- We need to get inside of our container
- create a
ghostuser (otherwise Ghost-CLI will cuss at us for using
- exit ghost user and as a
ghostuser permissions to write to a config file
- log back in as
ghostuser and run Ghost-CLI command setting up our default
Here's how we're going to do this.
First, let's enter the container:
This will list your containers and you need to find one with ghost inside. Use the ID of this container to enter it:
CONTAINER ID IMAGE ... 8307bbc42bf4 ghost:2.2.4 ... docker exec -it 8307bbc42bf4 bash
Now let's create a user, make them an owner of a config file, and run a Ghost-CLI commend:
adduser ghost exit chown ghost config.production.json su - ghost ghost config --url https://[your domain] exit
Phew! All set now. Do a simple
docker container restart 8307bbc42bf4 and enjoy your new Ghost blog at https://yourdomain.
This is certainly not a comprehansive setup. There's no backup. What happens if the droplet is shutdown or restarts? (the container will restart as well, but hey, think about it!) Should we use MySQL instead of SQLite? (probably, we should). What if there's more sites running in separate containers? But with the information above, you'd be able to update your
ghost.yml with MySQL environment settings and add an extra MySQL container, add different Ghost instances and map ports and domains to match them and more.
1 - 20 years ago you'd end up in an insane asylum if you said this out loud around people