From d320e51e16c3c7ed2170412cd84c0528c1490908 Mon Sep 17 00:00:00 2001 From: Henry Addo Date: Sat, 29 Apr 2017 00:12:35 +0900 Subject: [PATCH] Add docker support (#24) It provides a script with command line options for creating a docker container, building a docker image and running the container. The docker configurations are created based off of some provided templates in the docker folder. These serve as the base for creating a Dockerfile and docker-compose.yaml files. These created files are ignored by git because they get overwritten when the script is run. The script enforces it's run from the root folder of the repository. This ensures the script reads the necessary template files from the right location. It uses the `gulp` folder as means of knowing that it's being run from the root of the repo. Hopefully there's a better way of doing this. Update the README file with info on running the script. Adds an entry to `.gitignore` to exclude the created files by the script. Use a script to create a new hugo website and create the asset folder structure if it doesn't exist. This script is executed as the last command during a docker build process. This ensures the required folders are there before executing `hugulp watch` in the created hugo website. --- .gitignore | 4 + README.md | 16 +++ docker/Dockerfile.template | 24 ++++ docker/docker-compose.yaml.template | 15 +++ scripts/create-docker-machine-and-run-it | 156 +++++++++++++++++++++++ scripts/create-hugo-site | 80 ++++++++++++ 6 files changed, 295 insertions(+) create mode 100644 docker/Dockerfile.template create mode 100644 docker/docker-compose.yaml.template create mode 100755 scripts/create-docker-machine-and-run-it create mode 100755 scripts/create-hugo-site diff --git a/.gitignore b/.gitignore index e8f1ec8..35a9f11 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,7 @@ node_modules # bower bower_components src/vendor + +# docker +Dockerfile +docker-compose.yaml diff --git a/README.md b/README.md index bb33bf7..52c8df7 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,22 @@ Then just $ npm install -g hugulp ``` +Or you can build and run using [docker](https://www.docker.com): + +```bash +# Default docker setup: +$ ./scripts/create-docker-machine-and-run-it + +# -- OR -- + +# Run with custom machine name, specific hugo version, specific node version and run docker in detached mode: +$ ./scripts/create-docker-machine-and-run-it -a app-devel -g 0.20.6 -n 6.10.0 -d +``` + +**Note:** You only run the `./scripts/create-docker-machine-and-run-it` if you want to create +a new docker machine. Once the docker machine is created, you have to use docker commands +to manage it. Please be familiar with docker in this regard. + ## Getting Started *hugulp* requires you to create the following folders inside your hugo site: diff --git a/docker/Dockerfile.template b/docker/Dockerfile.template new file mode 100644 index 0000000..bce2035 --- /dev/null +++ b/docker/Dockerfile.template @@ -0,0 +1,24 @@ +FROM node:7.9.0-alpine +# Set environment variable +ARG RUN_AS=node +ARG HUGO_VERSION=0.20.6 +ARG HUGO_BINARY="hugo_${HUGO_VERSION}_Linux-64bit" +RUN apk update && apk add py-pygments && rm -rf /var/cache/apk/* +# Download and install hugo +RUN mkdir /usr/local/hugo +ADD https://github.com/spf13/hugo/releases/download/v${HUGO_VERSION}/${HUGO_BINARY}.tar.gz \ + /usr/local/hugo/ +RUN tar xzf /usr/local/hugo/${HUGO_BINARY}.tar.gz -C /usr/local/hugo/ \ + && ln -s /usr/local/hugo/hugo /usr/local/bin/hugo \ + && rm /usr/local/hugo/${HUGO_BINARY}.tar.gz +RUN npm install -g hugulp +ENV HOME=/home/$RUN_AS +COPY package.json $HOME/web/ +RUN chmod 755 $HOME/* && chown -R $RUN_AS:$RUN_AS $HOME/* +USER $RUN_AS +# Change working directory +WORKDIR $HOME/web/ +USER root +COPY . $HOME/web/ +RUN chown -R $RUN_AS:$RUN_AS $HOME/* +USER $RUN_AS \ No newline at end of file diff --git a/docker/docker-compose.yaml.template b/docker/docker-compose.yaml.template new file mode 100644 index 0000000..ea48c92 --- /dev/null +++ b/docker/docker-compose.yaml.template @@ -0,0 +1,15 @@ +--- +version: '3' +services: + app: + labels: + app: "app" + build: + context: . + command: /bin/sh -c './scripts/create-hugo-site -a ./app;cd app;hugulp watch' + volumes: + - .:/home/node/app + - /home/node/app/node_modules + ports: + - "3000:3000" + - "3001:3001" diff --git a/scripts/create-docker-machine-and-run-it b/scripts/create-docker-machine-and-run-it new file mode 100755 index 0000000..47c85e3 --- /dev/null +++ b/scripts/create-docker-machine-and-run-it @@ -0,0 +1,156 @@ +#!/bin/bash +# +# Setup a docker machine for development +set -eu + +readonly PROGNAME=$(basename "$0") +readonly ARGS=("$@") +# Docker settings +HUGO_VERSION=0.20.6 +NODE_VERSION="7.9.0-alpine" +APP_NAME="app" +DETACHED= +check_where_cmd_is_run() { + # Check if script is being run from the root directory + if [ ! -d 'gulp' ]; then + cat <<- EOF + Please run this script from the root directory. + + Example: + ./scripts/create-docker-machine-and-run-it + + -- OR -- + + bash ./scripts/create-docker-machine-and-run-it + EOF + exit 1 + fi +} + +usage() { + cat <<- EOF + Usage: ./scripts/$PROGNAME optional options + + Setups a docker machine and runs it for development. + + OPTIONS: + -g --hugo-version the hugo version to be installed. Minus v or version prefix. It defaults to 0.9 + -n --node-version the node version to be installed. Minus v or version prefix. It defaults to 6.10.0 + -a --app-name the name of the app. It defaults to app + -d --detached detached mode: Run containers in the background, print new container names. + -h --help show this help + + Examples: + Run with default settings: + + ./scripts/$PROGNAME + + Run with custom machine name, specific hugo version, specific node version and run docker in detached mode: + + bash ./scripts/$PROGNAME -a app-name -g 0.9 -n 6.10.0 + EOF +} + +cmdline() { + local arg= + local args= + for arg; do + local delim="" + case "$arg" in + # Copied from: http://www.kfirlavi.com/blog/2012/11/14/defensive-bash-programming/ + # Translate --machine-name to -m (short options) + --hugo-version) args="${args}-g ";; + --node-version) args="${args}-n ";; + --app-name) args="${args}-a ";; + --detached) args="${args}-d ";; + --help) args="${args}-h ";; + #pass through anything else + *) [[ "${arg:0:1}" == "-" ]] || delim="\"" + args="${args}${delim}${arg}${delim} ";; + esac + done + while getopts "g:n:a:dh" OPTION; do + case "$OPTION" in + h) + usage + exit 0 + ;; + g) + HUGO_VERSION=$OPTARG + ;; + n) + NODE_VERSION=$OPTARG + ;; + a) + APP_NAME=$OPTARG + ;; + d) + DETACHED='-d' + ;; + esac + done + return 0 +} + +create_docker_file() { + # Check to make sure Dockerfile exist + if [ ! -f './docker/Dockerfile.template' ]; then + echo "This script requires ./docker/Dockerfile.template file to setup docker." + exit 1 + fi + echo "Creating Dockerfile file..." + cp ./docker/Dockerfile.template ./Dockerfile + # Replace some lines in existing Dockerfile. + # Set sed -i option to '' to prevent it from creating backup files + # Replace node version set value + sed -i '' -e "s|^FROM node:\([0-9\.]*\).*|FROM node:$NODE_VERSION|" \ + Dockerfile + # Replace hugo version with set value + sed -i '' -e "s|^ARG HUGO_VERSION=\([0-9\.]*\).*|ARG HUGO_VERSION=$HUGO_VERSION|" \ + Dockerfile + # Replace app home directory with set value + sed -i '' -e "s|\$HOME/[a-zA-Z0-9]*/$|\$HOME/$APP_NAME/|g" \ + Dockerfile + echo "Dockerfile successfully created." +} + +setup_docker() { + # Check if docker is installed on the machine + if ! docker version > /dev/null; then + echo "Please docker-engine and docker-compose are required to be installed on the host machine" + echo "https://docs.docker.com/engine/installation/" + echo "https://docs.docker.com/compose/" + exit 1 + fi + create_docker_file +} + +setup_docker_compose() { + # Check to make sure docker-compose template file exist + if [ ! -f './docker/docker-compose.yaml.template' ]; then + echo "This script requires ./docker/docker-compose.yaml.template file to setup docker-compose." + exit 1 + fi + echo "Creating docker-compose.yaml file..." + cp ./docker/docker-compose.yaml.template ./docker-compose.yaml + echo "docker-compose.yaml successfully created." + sed -i '' -e "s/app:/${APP_NAME}:/" \ + docker-compose.yaml + sed -i '' -e "s/app/$APP_NAME/g" \ + docker-compose.yaml + if [[ "$DETACHED" != "" ]]; then + docker-compose up --build "$DETACHED" "$APP_NAME" + else + docker-compose up --build "$APP_NAME" + fi +} + +####################### +# Main function # +####################### +if [[ $# -gt 0 ]]; then + cmdline "${ARGS[@]}" +fi +check_where_cmd_is_run +setup_docker +setup_docker_compose diff --git a/scripts/create-hugo-site b/scripts/create-hugo-site new file mode 100755 index 0000000..8570374 --- /dev/null +++ b/scripts/create-hugo-site @@ -0,0 +1,80 @@ +#!/bin/sh +# +# Creates pre-requiste hugo site +set -eu + +readonly PROGNAME=$(basename "$0") +readonly ARGS="$@" +APP_NAME="app" + +usage() { + cat <<- EOF + Usage: ./scripts/$PROGNAME optional options + + Creates folders needed to run hulgulp if they do not exist + + OPTIONS: + -a --app-name the name of the app. It defaults to app + -h --help show this help + + Example: + Run with a hugo website name set to website + + ./scripts/$PROGNAME -a website + EOF +} + +cmdline() { + local arg= + local args= + for arg; do + local delim="" + case "$arg" in + # Copied from: http://www.kfirlavi.com/blog/2012/11/14/defensive-bash-programming/ + # Translate --machine-name to -m (short options) + --app-name) args="${args}-a ";; + --help) args="${args}-h ";; + #pass through anything else + *) [[ "${arg:0:1}" == "-" ]] || delim="\"" + args="${args}${delim}${arg}${delim} ";; + esac + done + + OPTIND=1 + while getopts "ha:" OPTION; do + case "$OPTION" in + h) + usage + exit 0 + ;; + a) + APP_NAME=$OPTARG + ;; + esac + done + shift "$((OPTIND-1))" # Shift off the options and optional --. + return 0 +} + +create_hugo_site() { + if [ ! -d "$APP_NAME" ]; then + hugo new site "$APP_NAME" + fi +} + +create_assets_folders() { + if [ ! -d "${APP_NAME}/assets" ]; then + mkdir -p "${APP_NAME}"/assets/img + mkdir -p "${APP_NAME}"/assets/styles + mkdir -p "${APP_NAME}"/assets/scripts + fi +} + +####################### +# Main function # +####################### +if [[ $# -gt 0 ]]; then + cmdline "$@" +fi +create_hugo_site +create_assets_folders