Note: This post was written for Ghost 0.7.1, which is no longer a recent version.

I've been eyeballing Docker for months now. Always popping up in my feeds with their enthusiasm and lively community. Their mascot, Moby Dock, temps me with his gentle whale song of isolated applications, scalability, and portability.

But is it not just Moby Dock who haunts me, for there is a Ghost following me as well. One that whispers I should write about my adventures in software and technology. Through serendipity the two came together when I discovered there was an official Ghost image on Docker Hub. Here I take a plunge into the proverbial digital ocean with my first blog post.

Enough with the wordplay - lets get to work.

Now Serving Whale

For the sake of brevity, and because there are already numerous great resources on the topic, I will not be covering the aspects of setting up a server or Docker. Of course, if you simply want to test out Ghost then you can follow their setup instructions. You don't need a dedicated server to test out Ghost or Docker but it is nice.

In the event you plan to set up a server, but have not yet done so, then I highly recommend taking a look at DigitalOcean for their servers and quality documentation. Similarly, Docker has superb documentation and awesome tools. I personally use both.

Also in use is the nginx-proxy image from Docker Hub. This makes establishing a reverse proxy nginx while using containers even easier.

A Ghostly Image at the Dock

At the time of this writing, the current Ghost version is 0.7.1 and things may change in the future. It is being actively developed, after all. Take the following with a grain of salt.

Located in Docker Hub, the Ghost image is relatively straightforward to setup. The Ghost image, by default, runs in development mode. As I want to run in production, the command to run is slightly different than what is found in the documentation. The comments on the Ghost image page were particularly helpful in synthesizing the command.

The full command being used is:

docker run --name ghost-name -d --expose 2368 -e VIRTUAL_HOST=your-domain-name -e NODE_ENV=production -v /path/to/your/ghost/data:/usr/src/ghost/content -v /path/to/your/ghost/data:/var/lib/ghost ghost

Breaking this down, we have:

  • docker run - The basic command to create a container.
  • --name ghost-name - Names the container ghost-name.
  • -d - Short for detached.
  • --expose 2368 - This lets the container play nicely with the nginx-proxy container mentioned earlier. Port 2368 is the default Ghost port.
  • -e VIRTUAL_HOST=your-ghost-domain-name - Another piece for nginx-proxy that let it know to route to this container. Subdomains are fine. Make sure the DNS forwards correctly too!
  • -e NODE_ENV=production - Sets the Ghost image to production mode rather than the default development mode.
  • -v /path/to/your/ghost/data:/usr/src/ghost/content - It is not obvious to me why it is needed in production mode and not development, but the container does not work right without it.
  • -v /path/to/your/ghost/data:/var/lib/ghost - The path /var/lib/ghost came from the documentation on the Ghost image so we will not change it.
  • ghost - The image.

Note: Publicly exposing a port unless you are ready for traffic or at least have an admin account is not a great idea.

Elaborating, the flag -v indicates a volume to mount. Doing so allows data to be persisted outside of the container. The path /ghost/data is the absolute filepath to where the blog content will be persisted on the host. This location can largely be wherever you feel is appropriate. See Docker's User Guide on managing contains in data for more information on data persistence.

Thanks to the -v flags above, if you stop the container via docker stop ghost-name then the blog data should still be under the host path /ghost/data and usable in the future. In fact, if you already had Ghost blog stuff, you could simply have it sitting at the host path and the container will make use of it. Yay data persistence!

The Ghost is Alive

Running the line above will set up a Ghost container and start it. At this point you should be able to point a browser to http://your-ghost-domain-name. This will let you view the blog. Pointing the browser at http://your-ghost-domain-name/ghost lets you set up an admin account and start making edits.

From here on you can continue to configure Ghost or start creating content.