Grav Flat-File CMS Docker Image
Grav is a fast, simple, flexible web-platform. This is a Docker image that makes it trivial to fire-up and use Grav.
To learn more about Grav, see the Grav Website.
This image is also available on Docker Hub so you can pull it directly from there. There's no need to build it yourself.
NOTE: This is an early-release of this container. See the "Known Issues" section at the very bottom of this page for more information about things we know don't work.
The following documentation tells you how to use the
docker-grav image, a lean full-featured Docker image that has the following features:
- Lean 100MB image with a pre-configured
nginxserver and a complete installation of Grav along with the Grav Administration Plug-in to make it easy to get started..
- Works both as a self-contained image, or will automatically recognize attached storage devices so that persistent Grav data is not stored in the container. Makes it easy to upgrade when new images are released.
- Fully configurable using environment variables, including options for logging, and initial Grav setup. A fully customized container can be started without the need to build a new image.
- Automatically generates a self-signed SSL certificate matched to your domain, or allows you to easily add your own legitimate SSL certificate.
You can get started quickly using the image hosted on Docker Hub. For example, to quickly create a running self-contained Grav server daemon:
$ docker pull garywiz/docker-grav $ docker run -d -p 8080:8080 garywiz/docker-grav
Within a few seconds, you should be able to use Grav by going to
http://localhost:8080/. The default login user is
admin with a password of
ChangeMe. (See "Customizing Grav" below for information about how to modify or add new users.
If you want to store the Grav website and configuration locally outside the image, you can use the built-in launcher script. Extract the launcher script from the image like this:
$ docker run -i --rm garywiz/docker-grav --task get-launcher | sh
This will create a flexible launcher script that you can customize or use as a template. You can run it as a daemon:
$ ./run-docker-grav.sh -d
Or, if you want to have local persistent storage:
$ mkdir docker-grav-storage $ ./run-docker-grav.sh -d
Now, all persistent data will be stored in the
docker-grav-storage directory. The container itself is therefore entirely disposable.
run-docker-grav.sh script is designed to be self-documenting and you can edit it to change start-up options and storage options. You can get up-to-date help on the image's features like this:
$ docker run -i --rm garywiz/docker-grav --task get-help
If you extract the default launcher (see above), it can serve as the basis for your own start-up script. But, it also has some default options built-in to make it easy to tailor startup without having to modify the script. You can use the
-h option to get a list of options:
$ ./run-docker-grav.sh -h Usage: run-docker-grav.sh [-d] [-p port#] [-h] Run Grav from garywiz/docker-grav as a daemon (with -d) or interactively (the default). -d Run as daemon (otherwise interactive) -p port# Specify port number to expose Grav server (default 8080) -s dirpath Specifies the path to an optional storage directory where ALL persistent Grav files and settings will be stored. This allows you to keep your site separate from the container so you can easily upgrade the container software. By default, this script looks to see if ../docker-grav-storage exists, and if it does, it will be used. You can override that default with this switch. -n name Name the container 'name' instead of the default name invented by Docker. HTTPS options (SSL): -H sslhost Specify the SSL host name and enable the SSL server. If specified, Grav will also be available using https on the port specified by -P -P sslport# Specify SSL port number (default 8443)
If you run the Grav container using the above launcher but omit the
-d switch, you'll be place into the container in an interactive shell where you can use the
gpm command to customize Grav by adding users, themes, or plugins:
$ ./run-docker-grav.sh Oct 15 22:08:28 e265699abf5f chaperone: system will be killed when '/bin/bash' exits Now running inside container. Directory is: /apps Your Grav site is running at http://localhost:8080/ The Grav 'gpm' and 'grav' commands are available at the prompt. bash-4.3$ gpm Grav Package Manager version 0.9.45 ...
You can use
gpm as described here in the Grav documentation to install new features or browse around a the installation. The container will run and be usable until you exit, at which point it will be destroyed. This is generally a good way to experiment.
Note: Any features you add will be local to the container unless you use persistent storage as described below under "Configuring Attached Storage".
Once you've configured attached storage, your entire Grav configuration will be located in the attached storage
var/grav subdirectory. There you will find the
site.yaml file. You can change these and re-run your container and they'll persist even if they container is destroyed.
See the Grav Configuration documentation for more information about how to modify these files.
Full Option List
If you want to invent your own start-up, or are using an orchestration tool, here is a quick view of all the configuration options piled into one command along with their defaults:
$ docker run -d garywiz/docker-grav \ -p 8080:8080 \ -e CONFIG_LOGGING=stdout \ -e CONFIG_ADMIN_USER=admin \ -e CONFIG_ADMIN_PASSWORD=ChangeMe \ -e CONFIG_ADMIN_EMAIL="email@example.com" \ -e CONFIG_ADMIN_NAME="Grav Administrator" \ -e CONFIG_ADMIN_TITLE="Grav Administrator" \ -e CONFIG_EXT_SSL_HOSTNAME=""
syslog:host(see "Logging Configuration" below).
CONFIG_ADMIN_USER: Specifies the user credentials for the Administrative plugin interface account. This account will be set up automatically to have full access, but won't be changed if it already exists. You can disable this completely by setting
CONFIG_ADMIN_USERto the string "none".
CONFIG_EXT_SSL_HOSTNAME: This is the name of the SSL host. It should match the actual hostname people will use to access the server. If set to "blank", then Grav will run using standard HTTP. If you set this, you also need to add
-p 8443:8443to the command line to expose the
Of course, you can customize this set-up exactly like any other Docker run command, remapping ports or using other options however you wish. If you want to run interactively, you'll need to include a final argument such as
/bin/bash as well as use the
-t options. See the Docker run CLI reference for further information.
Configuring Attached Storage
Using attached storage, you can choose a location for the Grav user files and configuration so that your entire persistent state is stored outside the container itself. This makes it easy to update the container to a new version while retaining your existing content and configuration.
When configuring attached storage, there are two considerations:
- Attached storage must be mounted at
/apps/varinside the container, whether using the Docker
- You will need to tell the container to match the user credentials using the
--create-userswitch (documented here on the Chaperone site).
Both are pretty easy. For example, assume you are going to store persistent data on your local drive in
/persist/gravsite. Providing the directory exists, you can just do this:
$ docker run -d -v /persist/gravsite:/apps/var garywiz/docker-grav \ --create-user anyuser:/apps/var
When the container starts, it will assure that all internal services run as a new user called
anyuser whose UID/GID credentials match the credentials your host box has assigned to
When you run the container, you'll see that all the Grav persistent data files have been properly created in
By default, all container logs will be sent to
stdout and can be viewed using the
docker logs command.
If this isn't suitable, there are two additional options that can be specified using the
CONFIG_LOGGING environment variable:
CONFIG_LOGGING="file" - This setting will cause all logging information to be sent to
var/log/syslog.log either inside the container or on attached storage.
CONFIG_LOGGING="syslog:hostname" - In this case, you need to specify
hostname as the destination for logging. The specified host must have a syslog-compatible daemon running on UDP port 514.
Using Your Own SSL Keys
By default, a self-signed SSL key will be generated automatically for you at start-up if you enable SSL. If attached storage is used, the key will be generated only once. Otherwise, a new key will be created each time a new container starts.
Most enterprise and production installations will often want to use their own pre-defined key. In order to do so, you'll need to:
- Run this image using attached storage. This is where you will store your keys, and they will persist when you upgrade the container.
- Have your certificate and private key files in standard
PEMformat (the one usually used by Certificate authorities), or convert it from PKCS12 format as described below.
- Not be an SSL noob. I hate to say it, but it really helps if you've done this before.
Here is a step-by-step guide.
Run with Persistent Storage
This is easy if you're using the provided launcher, as described above. The first thing to do is run the container once just to initialize the persistent storage directory:
$ mkdir docker-grav-storage $ ./run-docker-grav.sh -d Using attached storage at .../docker-grav-storage 00e9615bc51d63f9a150186482b3258d1c24b4f21ca0c781ae6e1717d9c97abc $
Now that your container is running, you should see the following in
$ cd docker-grav-storage $ ls certs config grav log run $
Certificates are stored in the
$ cd certs $ ls ssl-cert-localhost.crt ssl-cert-localhost.key $
The self-signed certificates is the file ending with
.crt and the private key is the one ending with
Once you see that these are present, it's probably a good idea to stop (and even delete) your container, as all persistent data is now stored in
Replace the keys with your own
Note that the names of the certificate and keys will always look like this:
<hostname> will be the exact string you used with the
CONFIG_EXT_SSL_HOSTNAME environment variable.
So, if your site is going to be
https://grav.example.com, then make sure you edit your start-up scripts to change the hostname, then make sure your certificate and key files are correctly named as follows:
If your keys are not already in
PEM format, you may need to convert them using SSL as this StackOverflow answer describes for PKCS12 keys.
Re-run the container
Once you've replaced the certificates, you can simply restart the old container, or create a new container using the same attached storage location. Your new certificate will then be in use.
- There is no email service installed within the container, so anything which sends email (such as the forgotten password feature) do not currently work.
- There are many Grav plugins, very few of which have been tested.
- When using attached storage, any newly installed plugins will be stored in attached storage rather inside the image. The admin plugin and related plugins, however, are stored inside the container so that upgrading the container will upgrade the entire set of administrative plugins as well.
Copyright (c) 2016, Gary J. Wisniewski firstname.lastname@example.org
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.