hi, my name is Ian Scrivener. I'm an Australian web technology specialist, fullstack/backend javascript web developer & cloud sysadmin. I've extensive (23 years) experience with medium to large scale web projects for .com, .gov & .org.

My main weapons include javascript; node.js, angular.js, d3.js and mean.js, with SQL & noSQL databases; mySQL, PostgresSQL, MSSQL, MongoDB, CouchDB, redis etc

... find out more

notCMS.js version 2

Recently I've been musing about a modern way to approach super simple web publishing of basic websites & SPAs (single page applications)... an approach way lighter than the traditional/monolithic CMS. Specifically;

notCMS.js v1 (no, I haven't written that up yet) approach was to use a grunt/jade/less/markdown workfklow... which is exactly what I use for this blog. However, I felt that this apporach is too to techy for non-devs... so have tried to simplify it here in version 2.

notCMS.js v2 is effectively a mustache.js/markdown.js frankenstein mashup as follows;



mustache.js is an implementation of the mustache template system in JavaScript. Mustache is a logic-less template syntax. It can be used for HTML, config files, source code - anything. It works by expanding tags in a template using values provided in a hash or object.

A simple mustache example would be;

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <div id="output"></div>
    <script src="//cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.2/mustache.min.js"></script>
        var view = {
            title: "Joe",
            calc: function() {
                return 2 + 4;
        var output = Mustache.render("{{title}} spends {{calc}}", view);
        document.getElementById('output').innerHTML = output;




Marked.js is one of many javascript Markdown parsers that also can be used frontend or backend. A simple example fo marked.js would be;

<!DOCTYPE html>
    <textarea id="text-input" oninput="this.editor.update()" rows="6" cols="60">Type **Markdown** here.</textarea>
    <div id="preview"></div>
    <script src="//cdnjs.cloudflare.com/ajax/libs/marked/0.3.0/marked.js"></script>
        function Editor(input, preview) {
            this.update = function() {
                preview.innerHTML = marked(input.value);
            input.editor = this;
        var $ = function(id) {
            return document.getElementById(id);
        new Editor($("text-input"), $("preview"));

notCMS.js example

What it does;

Here's the code;

<!DOCTYPE html>

    <script src="//cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.2/mustache.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/marked/0.3.0/marked.js"></script>
        //config the markdown files to load & insert
        var md_files     = ['intro','body']

        $(function() {
            var data        = {};
            var template     = $('body').html();

            // loop through the markdown files
            $.each(md_files, function(index,value) {

                // load the md file
                $.get(value + ".md",function(md){

                    // add it to the data object
                    data[value] = marked(md);

                    // when all markdown  has finished loading
                    if(index+1 == md_files.length){

                        //parse the template with mustache
                        var new_html         = Mustache.render(template, data);

                        // write the new html back to the body



    <h1>Markdown Mustache Demo</h1>
    <!-- note we use triple braces so that mustache doens't escape the HTML -->



Click here to see a working verison - http://ianscrivener.com/mustache-markdown-demo/

Sourcecode is here: https://github.com/ianscrivener/mustache-markdown-demo


Docker: container versus image

Docker container versus Docker Image

Briefly: think Windows install CD versus a freshly installed running Windows PC...

A Docker Image is a saved copy of a machine.

A Docker Container is a running version of a Docker Image.

For example, we could run many slave machine processes as Docker Containers - based on the same Docker Image


Install etckeeper to backup Ubuntu application setup

etckeeper saves your Ubuntu package configuration using a version control (Git, Subversion, Bazaar, Mercurial etc). Everytime you add/remove/update apt/aptitude packages etckeeper automagically commits the changes to version control.

Ever need to quickly roll-back Ubuntu to s previous application setup state. Yeah.. me too!!


apt-get install etckeeper

(not really optional) Change to Git version Control System

I use Git (doesn't everyone?!)... so switch verison control to Git from Bazaar

nano /etc/etckeeper/etckeeper.conf     

Change from

    # The VCS to use.


    # The VCS to use.

Initalise the etckeeper system

etckeeper init

So what do it do?!

Marvel at the new Git repository in /etc/.git/


Installing Geoserver in Docker

Docker is an exciting new (in January 2014 anyway) technology I can see that I'll be using a lot! I love the idea of a quarrantined machine that reuses the host machine's kernel etc, rather than duplicating them like traditional a virtual machines (VMWare,VirtualBox) do. Smaller foot print and removes all the bloat.

Before we start you need to have Docker installed already.. if you don't head over to the Docker website, they have great instructions on how to install Docker.

I strongly prefer the OpenGeo distribution of Geoserver; it install and configs a bunch of stuff to save us time/effort - for example; postgresql 9.3, postgis 2.1, geowebcache, gdal tools etc.

Warning: geoserver instalation is known to be tricky/problematic. Especially the glad part. Plus, OpenGeo is only supported on 12.04. Trying to install on 12.10 may cause you a mountain of punish.

Anyway, lets get started installing OpenGeo Geoserver;

1) Grab the standard/generic Ubuntu (Precise - 12.04 LTS) Docker image

sudo docker pull ubuntu:quantal

2) Now run the Docker machine interactively

sudo docker run -i -t ubuntu:quantal /bin/bash    

Now notice the different command prompt syntax. Mine is root@4f46de7402cb:/#. The 4f46de7402cb is the UUID of the Docker Container on your host machine. Keep a keen eye out for this as it shows you when you are in the Docker machine.. its easy to miss, believe me!

2) (In the Docker Container.. ie virtual machine) Check the Docker Ubuntu verison just for fun

cat /etc/lsb-release

You should see something like


Why didn't we use lsb-release -a you ask... try it?!

Now we continue to install opengeo geoserver kind of as if we installing on a cloud or physical Ubuntu 12.04 machine. kind of... well, there are few differences, mostly notably we do not use sudo in for our commands and a bunch of stuff you usually use (eg wget/curl) is not installed by default on Docker.

3) (In the Docker machine) Add the universal apt repositories and update echo "deb http://apt.opengeo.org/suite/v4/ubuntu/ precise main" > /etc/apt/sources.list.d/opengeo.list apt-get update

4) Install some of the standard utilities we love & and use that are often installed by default in our distro; apt-get install -y wget gcc patch zip nano ## or your fav text editor apt-get install -y software-properties-common

3) Grab the OpenGeo GPG apt key wget -qO- http://apt.opengeo.org/gpg.key | apt-key add -

4) Add the OpenGeo and the UbuntuGIS apt repositories and update echo "deb http://apt.opengeo.org/suite/v4/ubuntu/ precise main" > /etc/apt/sources.list.d/opengeo.list add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable apt-get update apt-get upgrade

5) Often we get dependancy problems with geoserver... especially the libgdal package. So we're going to try loading libgdal on its own to make sure it works. If things go pear shaped here you're on your own!!

apt-get install -y libgdal    

If you do have problems, checkout the following for another way to install libgdal - http://gis.stackexchange.com/questions/26283/installation-issue-with-opengeo-suite

6) Double check that you can find opengeo in the apt-cache before we proceed with the main event apt-cache search opengeo

You should see

geoserver - High performance, standards-compliant map and geospatial data server.
opengeo - OpenGeo Suite.
opengeo-client - OpenGeo Suite client components.
opengeo-dashboard - Dashboard for OpenGeo Suite.
opengeo-docs - Full documentation for the OpenGeo Suite.
opengeo-jai - A set of Java toolkits to provide enhanced image rendering abilities for the OpenGeo Suite.
opengeo-recipes - Recipe book for OpenGeo Suite.
opengeo-server - OpenGeo Suite server components.
opengeo-tomcat6 - OpenGeo web applications for Tomcat 6.
opengeo-webapp-sdk - OpenGeo Suite Web Application SDK.

Note: opengeo installs postgresql 9.3, postgis 2.1, openjdk, tomcat6 and python xxx for us

7) Finally, install OpenGeo

apt-get install -y opengeo-server 

This install OpenGeo in /usr/share/opengeo and Tomcat6 in /usr/share/tomcat6

8) [Optionally] Remove some packages you may not need

apt-get remove opengeo-dashboard       ## fairly useless IMO 
apt-get remove opengeo-docs            ## who read em anyway
apt-get remove geoexplorer             ## a cool web mapping client I've player with but never used
apt-get remove opengeo-client          ## include pgadmin  

That leaves these installed;
- geoserver: the main web mapping server - postgis21-postgresql93: postgresql and postgis - geowebcache: tile cache etc - opengeo-tomcat: the J2EE engine - geoserver-css: CSS Styling is FAR easier than SLD! see http://docs.geoserver.org/latest/en/user/extensions/css/tutorial.html

Tomcat? I have used Jetty before and prefer it to Tomcat. Jetty is faster but the install is a lot more fiddly - maybe another how-to post later on.

10) Exit Docker


11) REALLY IMPORTANT - Save the Docker Container to a new Docker Image

Now in the host system... get the details of the last Container we ran

Create a new Docker Image with the Docker Container we have just used docker commit 4f46de7402cb ianscrivener/geoserver-base

To run the Docker machien again use

docker run -i -t ianscrivener/geoserver-base /bin/bash

This creates a new instance.. ie Docker Container

12) Some quick Docker cheats;

List all instances (Docker Containers)

sudo docker ps -a

List all running instances (Docker Containers)

sudo docker ps

List all Docker Images

docker images

Remove Docker Containers

docker rm <container_id>

Remove Docker Image

docker rmi <image_name>