01 Apr

Grav: CMS for developers

by Marcin Budny grav docker

Grav is a CMS that powers this blog. It is flat file based, which makes it perfect for people with a developer mindset. Here I'll explain how to get started with Grav on Docker.

Why Grav?

It is simple, yet powerful in the right hands. It does not use any database, just plain old filesystem with Markdown files for content and YAML for configuration. This basically means you can create content easily and stay in control all the way - now WYSWIG magic. You can also use tools you already work with on daily basis for coding. I prefer Visual Studio Code.

This also means you can version the CMS content with git as you would normally do with any of your web applications. If you want to collaborate with your team on creating the content you can have pull requests, diff files, merge, etc.

You can run a local instance of grav on your machine and edit / preview your content locally. Then you would deploy it with an automated script to public instance. You can event have a staging environment if you want.

Better yet, all of this also applies to Grav's configuration.

All of this makes the CMS very appealing to people used to developer tools and workflows. Those, who are used to WYSWIG approach will find it less lovable.

Running Grav with Docker

First you will have a running Docker deamon. If you didn't install it yet, follow the guide here

Unfortunately there is no official Docker image, but there are some unofficial ones. I recommend starting with this one by Gary Wisniewski. It integrates Grav with nginx proxy and management tools.

docker pull garywiz/docker-grav
docker run -i --rm garywiz/docker-grav --task get-launcher | sh

These commands will pull the image from Docker Hub and create a startup script run-docker-grav.sh that we'll use to start a properly configured container.

We want to have Grav running on port 80. All configuration and user content should be stored in /var/blog-volume directory on the host. The latter means that all files you want to keep safe, will be on stored the host, not in the container itself.

sudo mkdir /var/blog-volume
sudo chown $USER /var/blog-volume
./run-docker-grav.sh -d -s /var/blog-volume -p 80:8080

Now you can go to http://youhost.com/ to view the forntend part, then to http://yourhost.com/admin for the admin panel. The script created a user called admin with password set to ChangeMe.

The /var/blog-volume directory contains stuff you want to version with git, or at least backup from time to time. You can skip the cache directory however.

One more thing to do: with current configuration Grav will not handle some urls properly - it will use port 8080 instead of 80. One such example is the favicon. To remedy this situation, go to grav/user/config/system.yaml file and set:

reverse_proxy_setup: true

Handling host restarts

If you now restart the host, you'll notice the grav container didn't start. You can start it with:

docker ps -a     # to check the name of container
docker start [your_container_name]

But manual process is not a very good idea. To have the container auto start after reboot, modify the run-docker-grav.sh file:

if [ "$INTERACTIVE_SHELL" != "" ]; then
  docker_opt="$docker_opt -t -i -e TERM=$TERM --rm=true"
  docker_opt="-d --restart=always"    # <- added restart option here

Don't worry, modifying the script is ok - the author himself suggests to use it as a template for your own purposes.

Installing and updating plugins

You can install new plugins with the admin panel of Grav. Later, you can also update them in similar way. However there is one problem with the Grave docker image we're using, related to updating Grav itself and the pre-installed plugins. The way the image is built makes it impossible to auto update those from the admin panel. You will have to update whole docker image to the new version. See the next section for details.

Updating to newer Grav version

The update process:

  1. Pull new docker image
  2. Stop and remove existing container
  3. Start new container with the new image

At the time of writing, the latest Docker image contains Grav version 1.0.9 while the actual latest Grav version is 1.0.10. You can wait for the author to update the image, or build a customized version yourself.

First, get the repository:

git clone https://github.com/garywiz/docker-grav.git
cd docker-grav

Modify the Dockerfile:

ENV GRAV_VERSION=1.0.10     #  <- modified version here

Then build the image:


The new image will be stored on your host with name garywiz/docker-grav and tag latest. You can now recreate the container from the new image.

What's next

In a future blog post I will cover setting up SSL connection for the CMS.

About the author:

Marcin Budny

Team lead of R&D at BT Skyrise. Works with Intelligent Transport Systems (ITS), where he faces problems in terms of equipment and software. He is passionate about the architecture of applications, cloudcomputing and IT systems quality. He constantly searches for novelties on software development. Marcin specializes in .NET technology, however he looks for inspiration in other languages and platforms.

Next Post Previous Post

blog comments powered by Disqus