Provide a dockerized site builder
diff --git a/builder/bin/builder.sh b/builder/bin/builder.sh
new file mode 100755
index 0000000..ec60f1e
--- /dev/null
+++ b/builder/bin/builder.sh
@@ -0,0 +1,86 @@
+#!/usr/bin/env bash
+
+DOCKER_NAME=velocity-site-builder
+
+# exit on failures and undeclared variables, echo commands
+set -o errexit
+set -o nounset
+set -o pipefail
+
+# debugging
+#set -o xtrace
+
+# Determine the real location of the script, past symlinks.
+# (source: https://stackoverflow.com/a/246128/710286 )
+SOURCE="${BASH_SOURCE[0]}"
+while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  TARGET="$(readlink "$SOURCE")"
+  if [[ $TARGET == /* ]]; then
+    SOURCE="$TARGET"
+  else
+    DIR="$( dirname "$SOURCE" )"
+    SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+  fi
+done
+
+# get repository root
+cd $( dirname "$SOURCE" )/../..
+if test ! -f .asf.yaml
+then
+    echo Could not find root of velocity-site git repository
+    exit 1
+fi
+ROOT=$( pwd )
+rm -rf target/*
+mkdir -p target
+
+# check docker is installed
+if [ ! -x "$(command -v docker)" ]; then
+    echo "Install docker on your system and try again..."
+    exit 1
+fi
+
+# check that velocity-site-prod (velocity-site on the asf-site branch) is cloned in a sibling directory
+cd "$ROOT/.."
+BASE=$( pwd )
+if test ! -d velocity-site-prod
+then
+    echo the site builder needs a clone of velocity-site under the asf-site branch in the velocity-site-prod directory in the same parent directory than velocity-site.
+    read -n1 -p "Shall I create it for you?" answer
+    echo
+    if [[ "$answer" =~ ^[Yy]$ ]]
+    then
+        git clone --single-branch --branch asf-site https://gitbox.apache.org/repos/asf/velocity-site.git velocity-site-prod
+    fi
+fi
+if test ! -d velocity-site-prod
+then
+   echo velocity-site-prod repository not present, exiting
+   exit 1
+fi
+cd velocity-site-prod
+
+# The philosophy here is to cache the image but not the container.
+
+# stop previous container if present
+if [ "$(docker ps -q -f name=$DOCKER_NAME)" ]
+then
+    docker stop $DOCKER_NAME
+fi
+
+# remove previous container if present
+if [ "$(docker ps -aq -f status=exited -f name=$DOCKER_NAME)" ]
+then
+    docker rm -v $DOCKER_NAME
+fi
+
+# build the image if necessary
+if [[ "$(docker images -q $DOCKER_NAME 2> /dev/null)" == "" ]]; then
+    docker build --file="$ROOT/builder/src/docker/Dockerfile" -t $DOCKER_NAME "$ROOT/builder/src/docker"
+fi
+
+# do the voodoo
+docker run --rm --name $DOCKER_NAME -u "$(id -u):$(id -g)" --volume="$BASE:/home/velocity" $DOCKER_NAME
+
+# alternatively, if you need to debug the container (as root), comment the previous command and run instead:
+# docker run -it --name $DOCKER_NAME --volume="$BASE:/home/velocity" --entrypoint=/bin/bash velocity-site-builder
diff --git a/builder/src/docker/Dockerfile b/builder/src/docker/Dockerfile
new file mode 100644
index 0000000..92a13c3
--- /dev/null
+++ b/builder/src/docker/Dockerfile
@@ -0,0 +1,23 @@
+FROM ubuntu:18.04
+
+MAINTAINER Claude Brisson
+
+RUN apt-get update
+RUN apt-get -y install python2.7 python-pip subversion
+RUN apt-get -y install git libyaml-libyaml-perl libtimedate-perl libwww-perl xsltproc
+RUN apt-get clean
+
+# latest 2.6.x is 2.6.11, but it seems to break codehilite
+RUN pip install Markdown==2.6.7
+
+# install the pygments version we know works well with our markdown version
+RUN pip install Pygments==2.2.0
+
+WORKDIR /home/builder
+
+COPY build.sh .
+RUN svn checkout https://svn.apache.org/repos/infra/websites/cms
+RUN sed -ri 's|#!/usr/local/bin/python|#!/usr/bin/python|' cms/build/markdownd.py
+
+CMD /home/builder/build.sh
+
diff --git a/builder/src/docker/build.sh b/builder/src/docker/build.sh
new file mode 100755
index 0000000..6f5c543
--- /dev/null
+++ b/builder/src/docker/build.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# exit on failures and undeclared variables, echo commands
+set -o errexit
+set -o nounset
+set -o pipefail
+
+export MARKDOWN_SOCKET=/tmp/markdown
+CMS=/home/builder/cms
+VELOCITY=/home/velocity
+
+# launch markdown daemon
+$CMS/build/markdownd.py
+
+# erase temporary files and target directory
+find $VELOCITY/velocity-site/src/content -name "*~" | xargs -r rm
+rm -rf $VELOCITY/velocity-site-target/* $VELOCITY/velocity-site-target/.htaccess
+
+echo Generating site...
+
+$CMS/build/build_site.pl --source-base $VELOCITY/velocity-site/src --target-base $VELOCITY/velocity-site/target
+
+echo Copying to production directory...
+
+rm -rf $VELOCITY/velocity-site-prod/* $VELOCITY/velocity-site-prod/.htaccess
+cp -r $VELOCITY/velocity-site/target/content/* $VELOCITY/velocity-site-prod/
+cp -r $VELOCITY/velocity-site/target/content/.htaccess $VELOCITY/velocity-site-prod/
+
+echo Post processing...
+
+find $VELOCITY/velocity-site-prod/ -name "*.html" | xargs sed -ri -e "s'<span></span>''g"
+