From f996fa2ae71fd04e6b9997daf6e4cacc4d1a02ae Mon Sep 17 00:00:00 2001 From: James Hillyerd Date: Mon, 22 Feb 2016 22:39:14 -0800 Subject: [PATCH] Docker best practices - Install and remove OS and Go build deps in a single layer - Use COPY instead of ADD - WORKDIR now resolves ENV variables, use one - Use VOLUMES for configuration and datastore - Added launcher script start-inbucket.sh - Made docker-run.sh more powerful --- Dockerfile | 17 ++++--- etc/docker/{ => defaults}/greeting.html | 0 etc/docker/{ => defaults}/inbucket.conf | 4 +- etc/docker/defaults/start-inbucket.sh | 24 ++++++++++ etc/docker/docker-run.sh | 59 ++++++++++++++++++++++++- etc/docker/install.sh | 29 +++++++++--- 6 files changed, 116 insertions(+), 17 deletions(-) rename etc/docker/{ => defaults}/greeting.html (100%) rename etc/docker/{ => defaults}/inbucket.conf (97%) create mode 100755 etc/docker/defaults/start-inbucket.sh diff --git a/Dockerfile b/Dockerfile index dd3d338..8542f99 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,19 +4,22 @@ FROM golang:1.6-alpine MAINTAINER James Hillyerd, @jameshillyerd -# Dependencies -RUN apk update && apk add git - # Configuration (WORKDIR doesn't support env vars) ENV INBUCKET_SRC $GOPATH/src/github.com/jhillyerd/inbucket ENV INBUCKET_HOME /opt/inbucket -WORKDIR /opt/inbucket -ENTRYPOINT ["bin/inbucket"] -CMD ["/etc/opt/inbucket.conf"] +WORKDIR $INBUCKET_HOME +ENTRYPOINT ["/con/context/start-inbucket.sh"] +CMD ["/con/configuration/inbucket.conf"] # Ports: SMTP, HTTP, POP3 EXPOSE 10025 10080 10110 +# Persistent Volumes, following convention at: +# https://github.com/docker/docker/issues/9277 +# NOTE /con/context is also used, not exposed by default +VOLUME /con/configuration +VOLUME /con/data + # Build Inbucket -ADD . $INBUCKET_SRC/ +COPY . $INBUCKET_SRC/ RUN "$INBUCKET_SRC/etc/docker/install.sh" diff --git a/etc/docker/greeting.html b/etc/docker/defaults/greeting.html similarity index 100% rename from etc/docker/greeting.html rename to etc/docker/defaults/greeting.html diff --git a/etc/docker/inbucket.conf b/etc/docker/defaults/inbucket.conf similarity index 97% rename from etc/docker/inbucket.conf rename to etc/docker/defaults/inbucket.conf index eea72f8..6b6cf6a 100644 --- a/etc/docker/inbucket.conf +++ b/etc/docker/defaults/inbucket.conf @@ -86,13 +86,13 @@ public.dir=%(install.dir)s/themes/%(theme)s/public # Path to the greeting HTML displayed on front page, can # be moved out of installation dir for customization -greeting.file=/etc/opt/inbucket-greeting.html +greeting.file=/con/configuration/greeting.html ############################################################################# [datastore] # Path to the datastore, mail will be written into subdirectories -path=/var/opt/inbucket +path=/con/data # How many minutes after receipt should a message be stored until it's # automatically purged. To retain messages until manually deleted, set this diff --git a/etc/docker/defaults/start-inbucket.sh b/etc/docker/defaults/start-inbucket.sh new file mode 100755 index 0000000..3f30e6b --- /dev/null +++ b/etc/docker/defaults/start-inbucket.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# start-inbucket.sh +# description: start inbucket (runs within a docker container) + +CONF_SOURCE="$INBUCKET_HOME/defaults" +CONF_TARGET="/con/configuration" + +set -eo pipefail + +install_default_config() { + local file="$1" + local source="$CONF_SOURCE/$file" + local target="$CONF_TARGET/$file" + + if [ ! -e "$target" ]; then + echo "Installing default $file to $CONF_TARGET" + install "$source" "$target" + fi +} + +install_default_config "inbucket.conf" +install_default_config "greeting.html" + +exec "$INBUCKET_HOME/bin/inbucket" $* diff --git a/etc/docker/docker-run.sh b/etc/docker/docker-run.sh index 9703c86..442f2fe 100755 --- a/etc/docker/docker-run.sh +++ b/etc/docker/docker-run.sh @@ -2,4 +2,61 @@ # docker-run.sh # description: Launch Inbucket's docker image -docker run -p 9000:10080 -p 2500:10025 -p 1100:10110 jhillyerd/inbucket +# Docker Image Tag +IMAGE="jhillyerd/inbucket" + +# Ports exposed on host: +PORT_HTTP=9000 +PORT_SMTP=2500 +PORT_POP3=1100 + +# Volumes exposed on host: +VOL_CONFIG="/tmp/inbucket/config" +VOL_DATA="/tmp/inbucket/data" + +set -eo pipefail + +main() { + local run_opts="" + + for arg in $*; do + case "$arg" in + -h) + usage + exit + ;; + -r) + reset + ;; + -d) + run_opts="$run_opts -d" + ;; + *) + usage + exit 1 + ;; + esac + done + + docker run $run_opts \ + -p $PORT_HTTP:10080 \ + -p $PORT_SMTP:10025 \ + -p $PORT_POP3:10110 \ + -v "$VOL_CONFIG:/con/configuration" \ + -v "$VOL_DATA:/con/data" \ + "$IMAGE" +} + +usage() { + echo "$0 [options]" 2>&1 + echo " -d detach - detach and print container ID" 2>&1 + echo " -r reset - purge config and data before startup" 2>&1 + echo " -h help - print this message" 2>&1 +} + +reset() { + /bin/rm -rf "$VOL_CONFIG" + /bin/rm -rf "$VOL_DATA" +} + +main $* diff --git a/etc/docker/install.sh b/etc/docker/install.sh index d5887ab..10a1a2b 100755 --- a/etc/docker/install.sh +++ b/etc/docker/install.sh @@ -4,9 +4,14 @@ set -eo pipefail -installdir="${INBUCKET_HOME}" -srcdir="${INBUCKET_SRC}" +installdir="$INBUCKET_HOME" +srcdir="$INBUCKET_SRC" bindir="$installdir/bin" +defaultsdir="$installdir/defaults" +contextdir="/con/context" + +echo "### Installing OS Build Dependencies" +apk add --no-cache --virtual .build-deps git # Setup export GOBIN="$bindir" @@ -16,7 +21,7 @@ go clean # Build echo "### Fetching Dependencies" -go get -d -t -v ./... +go get -t -v ./... echo "### Testing Inbucket" go test ./... @@ -25,9 +30,19 @@ echo "### Building Inbucket" go build -o inbucket -ldflags "-X 'main.BUILDDATE=$builddate'" -v . echo "### Installing Inbucket" +set -x mkdir -p "$bindir" -mkdir -p "/etc/opt" -mv inbucket "$bindir" -install etc/docker/inbucket.conf /etc/opt/inbucket.conf -install etc/docker/greeting.html /etc/opt/inbucket-greeting.html +install inbucket "$bindir" +mkdir -p "$contextdir" +install etc/docker/defaults/start-inbucket.sh "$contextdir" cp -r themes "$installdir/" +mkdir -p "$defaultsdir" +cp etc/docker/defaults/inbucket.conf "$defaultsdir" +cp etc/docker/defaults/greeting.html "$defaultsdir" +set +x + +echo "### Removing OS Build Dependencies" +apk del .build-deps + +echo "### Removing $GOPATH" +rm -rf "$GOPATH"