Blogging With Docker

We are living in the Golden Age of the “World Wide Web,” the “Information Highway,” the “Internet,” or what we simply call it nowadays: “Online.” Setting up a blog is as easy as 1-2-3, you don’t need to hire a programmer or become one.

Here’s my take on the subject while still keeping that “techie” feeling. The screencast below walks you through creating this blog post.

So wasn’t that easy? All you need are the following:

  • A computer installed with any flavor of Docker (boot2docker1, toolbox2 etc.)
  • Your very own dot com i.e. domain name (get yours here3 or here4)
  • An AWS account, and an IAM user with sufficient privileges5 (S3, etc.)
  • The Dockerfile6 that describes our Integrated Blogging Environment. (IBE™ Anyone?)

I won’t go into the first 3 bullets above, just the last one and some usage tips. Let’s get right to it!

Creating the Docker Image

In the terminal, run the following commands:

mkdir -p /tmp/jekyll_octopress_s3/
cd /tmp/jekyll_octopress_s3/
curl -O

One teeny tiny little thing that will wreak havoc later if we don’t set this up is the time zone. Now edit the Dockerfile and go to the bottom, you’ll see these lines:

# Last but not the least, set the localtime and timezone
ENV TIMEZONE Asia/Singapore
RUN apk --update add tzdata \
	&& cp /usr/share/zoneinfo/$TIMEZONE /etc/localtime \
	&& echo $TIMEZONE > /etc/timezone

Replace the TIMEZONE variable with your desired time zone. Once that’s done, we run the command to build the image:

docker build -t jekyll_octopress_s3:1.0 .

Just your standard docker build command to create the image from a Dockerfile. We’re doing this in /tmp/ because once the image is created, we really don’t need to keep the Dockerfile. Also, this command takes some time and will depend on a variety of things e.g. network speed, system specs, etc.

So what’s in the image? If you’d have already guessed by the name we’re giving it, well, it contains Jekyll7, Octopress8, and s3_website9 and some dependencies required for these 3 main things.

Running the Docker Image

Once our image is ready, let’s go ahead with the blog setup.

Creating a Test Blog

docker run --rm -it --volume=$(pwd):/srv/jekyll jekyll_octopress_s3:1.0 jekyll new test
New jekyll site installed in /srv/jekyll/test. 

In order to create a new blog (here we called it ‘test’), we need to run the Docker image with the command jekyll new test. This takes care of creating the Jekyll site scaffold in the current working directory since that is where we mounted the volume inside the container at (/srv/jekyll is set to pwd).

After this command finishes, a new directory test is created which makes up the Jekyll site scaffold. We can now start up our new blog next.

Starting Up

cd test/
docker run --rm --name="blog_test" -it --volume=$(pwd):/srv/jekyll -p 3000:4000 jekyll_octopress_s3:1.0 jekyll s -w

Here we are running the Docker image with the command jekyll s -w to start the blog which we can now open in the browser. Just point to http://localhost:3000 and voila! It looks pretty basic, in fact this is the default Jekyll theme and we can see Jekyll’s welcome post as an example. You can customize it to your liking, but that won’t be covered in this post.

Also note that we are running the command inside the newly created test/ directory above.

We didn’t go through the docker run command arguments in detail in the first step, instead we’ll do it here:

  • --rm

    Removes the container after it has stopped. Since we aren’t persisting data inside the container, we can safely remove it.

  • --name="blog_test"

    Give the container a name. We want to connect to it later so giving a name would make it easier to remember.

  • -it

    Keep the STDIN open and allocate a pseudo-TTY to take over the shell we are running the command in, and print Jekyll server logs to it.

  • --volume=$(pwd):/srv/jekyll

    Mount the path in pwd to /srv/jekyll inside the container. Jekyll inspects this location for any Jekyll site scaffold and publishes it over the built-in HTTP server.

  • -p 3000:4000

    Expose the port running in the container to the host. The default port used by the container is 4000, and we’re exposing it to the host’s port at 3000.

  • jekyll_octopress_s3:1.0

    The Docker image created earlier.

  • jekyll s -w

    The command to run when the container starts up which runs the built-in HTTP server and watch for any updates to the Jekyll site scaffold; so we can immediately see our changes in the browser.

Getting Inside the Container

docker exec -it blog_test /bin/sh

Once our container is up and running, we connect to it using this command. From inside, we can then create new posts and publish them to S3. Here’s a quick explanation of the arguments to docker exec:

  • -it

    Keep the STDIN open and allocate a pseudo-TTY to get inside the container’s shell.

  • blog_test

    The name of the running container we want to attach to; which is the name we have given above.

  • /bin/sh

    Invoke the shell inside the container.

By this time, our current shell will be inside the container. Next we start creating our first post.

Writing Our First Post!

/srv/jekyll # octopress new post "First Post!"
New post: _posts/2016-02-09-first-post.markdown

Now we can go ahead and write our very first post using octopress new post which handles the creation of the file for us found under _posts/ directory. Just open up the file with your favorite text editor and start writing some content. Note the first 5 lines (including the ---) contains the post’s meta-data e.g. layout, title, date, categories, etc.

layout: post
title: First Post!
date: 2016-02-09T12:00:00+00:00

First Post! Oh yeah!

After saving it, refresh the browser and our new post will now be available.

Publishing to AWS S3

Finally, we get to the part where we will publish the blog and bring it up online. A lot of the prerequisites here are not provided as mentioned earlier, so before going through the next steps, please secure the domain and AWS S3 credentials.

To publish to S3, we use s3_website to handle that for us. Run the command below to create the base configuration file:

/srv/jekyll # s3_website cfg create

And supply the 3 S3 related entries with your credentials:

s3_id: <access key id>
s3_secret: <access secret key>
s3_bucket: <bucket name>

And then we apply the configuration and publish the blog with the following:

/srv/jekyll # s3_website cfg apply
/srv/jekyll # s3_website push

If all goes well, we should see the blog online! Hooray! Let’s give ourselves a pat on the back, grab a cup of coffee, and celebrate. :)

Tip! Set Up Aliases

Running Docker is a pain when you just want to start up the blog and get to the actual writing, so keeping them as aliases in your shell’s rc file is really a must. These are the aliases I currently have for this blog.

# Alias for starting the container
alias blog_db="docker run --rm --name="blog_db" -it --volume=$BLOG_DB:/srv/jekyll -p 4000:4000 jekyll_octopress_s3:1.0 jekyll s -w"

# Alias for attaching to the container
alias blog_db_shell="docker exec -it blog_db /bin/sh"

Tip! Use a CVS to Manage Your Blog

In traditional blogs, posts are persisted inside databases. Wordpress, Ghost, etc. require a database during installation. In our case, since we use a static site generator like Jekyll, everything is stored inside the actual HTML pages that the posts are written in. This makes it easier for us to persist it; just save it in the hard drive, a USB flash drive, or better yet: a CVS! But why would we want to do that? As programmers, we want to keep track of changes, maybe rollback post (highly unlikely though but maybe configuration settings will do) and other good stuff that comes with using a CVS.

If you indeed go this route, and if you use public hosting like GitHub, DO NOT COMMIT the s3_website.yml file. Doing so would risk your AWS S3 account and no one is responsible except you for that carelessness.

Wrapping Up

I hope this has been an insightful, albeit too long or boring, post on how to blog with Docker. Usefulness of this really depends on the user. If you only maintain one blog, or only blog on one computer, then this would serve nothing, except maybe just for experimenting with Docker.

I appreciate any feedback or even suggestions in doing this using other ways. The Dockerfile is in github, so any pull requests are welcome as well.

Happy blogging!