allow running as arbitrary uid (#151)

 * Adds guards around entrypoints commands that require root
 * Broaden permissions within the container filesystem to allow
   access by non-couchdb users.
 * Added an example to the documentation which specifies `--user`.

Fixes #147
diff --git a/2.3.1/Dockerfile b/2.3.1/Dockerfile
index a266ed8..f8ad0c9 100644
--- a/2.3.1/Dockerfile
+++ b/2.3.1/Dockerfile
@@ -19,77 +19,77 @@
 
 # be sure GPG and apt-transport-https are available and functional
 RUN set -ex; \
-        apt-get update; \
-        apt-get install -y --no-install-recommends \
-                apt-transport-https \
-                ca-certificates \
-                dirmngr \
-                gnupg \
-        ; \
-        rm -rf /var/lib/apt/lists/*
+    apt-get update; \
+    apt-get install -y --no-install-recommends \
+        apt-transport-https \
+        ca-certificates \
+        dirmngr \
+        gnupg \
+     ; \
+    rm -rf /var/lib/apt/lists/*
 
 # grab gosu for easy step-down from root and tini for signal handling and zombie reaping
 # see https://github.com/apache/couchdb-docker/pull/28#discussion_r141112407
 ENV GOSU_VERSION 1.11
 ENV TINI_VERSION 0.18.0
 RUN set -ex; \
-	\
-	apt-get update; \
-	apt-get install -y --no-install-recommends wget; \
-	rm -rf /var/lib/apt/lists/*; \
-	\
-	dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
-	\
+    \
+    apt-get update; \
+    apt-get install -y --no-install-recommends wget; \
+    rm -rf /var/lib/apt/lists/*; \
+    \
+    dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
+    \
 # install gosu
-	wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-$dpkgArch"; \
-	wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
-	export GNUPGHOME="$(mktemp -d)"; \
-        echo "disable-ipv6" >> ${GNUPGHOME}/dirmngr.conf; \
-        for server in $(shuf -e pgpkeys.mit.edu \
-            ha.pool.sks-keyservers.net \
-            hkp://p80.pool.sks-keyservers.net:80 \
-            pgp.mit.edu) ; do \
-        gpg --batch --keyserver $server --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 && break || : ; \
-        done; \
-	gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
-	rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
-	chmod +x /usr/local/bin/gosu; \
-	gosu nobody true; \
+    wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-$dpkgArch"; \
+    wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
+    export GNUPGHOME="$(mktemp -d)"; \
+    echo "disable-ipv6" >> ${GNUPGHOME}/dirmngr.conf; \
+    for server in $(shuf -e pgpkeys.mit.edu \
+        ha.pool.sks-keyservers.net \
+        hkp://p80.pool.sks-keyservers.net:80 \
+        pgp.mit.edu) ; do \
+    gpg --batch --keyserver $server --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 && break || : ; \
+    done; \
+    gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
+    rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
+    chmod +x /usr/local/bin/gosu; \
+    gosu nobody true; \
     \
 # install tini
-	wget -O /usr/local/bin/tini "https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$dpkgArch"; \
-	wget -O /usr/local/bin/tini.asc "https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$dpkgArch.asc"; \
-	export GNUPGHOME="$(mktemp -d)"; \
-        echo "disable-ipv6" >> ${GNUPGHOME}/dirmngr.conf; \
-        for server in $(shuf -e pgpkeys.mit.edu \
-            ha.pool.sks-keyservers.net \
-            hkp://p80.pool.sks-keyservers.net:80 \
-            pgp.mit.edu) ; do \
-        gpg --batch --keyserver $server --recv-keys 595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7 && break || : ; \
-        done; \
-	gpg --batch --verify /usr/local/bin/tini.asc /usr/local/bin/tini; \
-	rm -rf "$GNUPGHOME" /usr/local/bin/tini.asc; \
-	chmod +x /usr/local/bin/tini; \
-        apt-get purge -y --auto-remove wget; \
-	tini --version
+    wget -O /usr/local/bin/tini "https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$dpkgArch"; \
+    wget -O /usr/local/bin/tini.asc "https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$dpkgArch.asc"; \
+    export GNUPGHOME="$(mktemp -d)"; \
+    echo "disable-ipv6" >> ${GNUPGHOME}/dirmngr.conf; \
+    for server in $(shuf -e pgpkeys.mit.edu \
+        ha.pool.sks-keyservers.net \
+        hkp://p80.pool.sks-keyservers.net:80 \
+        pgp.mit.edu) ; do \
+    gpg --batch --keyserver $server --recv-keys 595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7 && break || : ; \
+    done; \
+    gpg --batch --verify /usr/local/bin/tini.asc /usr/local/bin/tini; \
+    rm -rf "$GNUPGHOME" /usr/local/bin/tini.asc; \
+    chmod +x /usr/local/bin/tini; \
+    apt-get purge -y --auto-remove wget; \
+    tini --version
 
 # http://docs.couchdb.org/en/latest/install/unix.html#installing-the-apache-couchdb-packages
 ENV GPG_COUCH_KEY \
 # gpg: key D401AB61: public key "Bintray (by JFrog) <bintray@bintray.com> imported
-       8756C4F765C9AC3CB6B85D62379CE192D401AB61
+    8756C4F765C9AC3CB6B85D62379CE192D401AB61
 RUN set -xe; \
-        export GNUPGHOME="$(mktemp -d)"; \
-        echo "disable-ipv6" >> ${GNUPGHOME}/dirmngr.conf; \
-        for server in $(shuf -e pgpkeys.mit.edu \
-            ha.pool.sks-keyservers.net \
-            hkp://p80.pool.sks-keyservers.net:80 \
-            pgp.mit.edu) ; do \
-                gpg --batch --keyserver $server --recv-keys $GPG_COUCH_KEY && break || : ; \
-        done; \
-        gpg --batch --export $GPG_COUCH_KEY > /etc/apt/trusted.gpg.d/couchdb.gpg; \
-        command -v gpgconf && gpgconf --kill all || :; \
-        rm -rf "$GNUPGHOME"; \
-        apt-key list
+    export GNUPGHOME="$(mktemp -d)"; \
+    echo "disable-ipv6" >> ${GNUPGHOME}/dirmngr.conf; \
+    for server in $(shuf -e pgpkeys.mit.edu \
+        ha.pool.sks-keyservers.net \
+        hkp://p80.pool.sks-keyservers.net:80 \
+        pgp.mit.edu) ; do \
+        gpg --batch --keyserver $server --recv-keys $GPG_COUCH_KEY && break || : ; \
+    done; \
+    gpg --batch --export $GPG_COUCH_KEY > /etc/apt/trusted.gpg.d/couchdb.gpg; \
+    command -v gpgconf && gpgconf --kill all || :; \
+    rm -rf "$GNUPGHOME"; \
+    apt-key list
 
 ENV COUCHDB_VERSION 2.3.1
 
@@ -97,32 +97,40 @@
 
 # https://github.com/apache/couchdb-pkg/blob/master/debian/README.Debian
 RUN set -xe; \
-        apt-get update; \
-        \
-        echo "couchdb couchdb/mode select none" | debconf-set-selections; \
+    apt-get update; \
+    \
+    echo "couchdb couchdb/mode select none" | debconf-set-selections; \
 # we DO want recommends this time
-        DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-downgrades --allow-remove-essential --allow-change-held-packages \
-                couchdb="$COUCHDB_VERSION"~stretch \
-        ; \
+    DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-downgrades --allow-remove-essential --allow-change-held-packages \
+            couchdb="$COUCHDB_VERSION"~stretch \
+    ; \
 # Undo symlinks to /var/log and /var/lib
-        rmdir /var/lib/couchdb /var/log/couchdb; \
-        rm /opt/couchdb/data /opt/couchdb/var/log; \
-        mkdir -p /opt/couchdb/data /opt/couchdb/var/log; \
-        chown couchdb:couchdb /opt/couchdb/data /opt/couchdb/var/log; \
-        chmod 777 /opt/couchdb/data /opt/couchdb/var/log; \
+    rmdir /var/lib/couchdb /var/log/couchdb; \
+    rm /opt/couchdb/data /opt/couchdb/var/log; \
+    mkdir -p /opt/couchdb/data /opt/couchdb/var/log; \
+    chown couchdb:couchdb /opt/couchdb/data /opt/couchdb/var/log; \
+    chmod 777 /opt/couchdb/data /opt/couchdb/var/log; \
 # Remove file that sets logging to a file
-        rm /opt/couchdb/etc/default.d/10-filelog.ini; \
-        rm -rf /var/lib/apt/lists/*
+    rm /opt/couchdb/etc/default.d/10-filelog.ini; \
+# Check we own everything in /opt/couchdb. Matches the command in dockerfile_entrypoint.sh
+    find /opt/couchdb \! \( -user couchdb -group couchdb \) -exec chown -f couchdb:couchdb '{}' +; \
+# Setup directories and permissions for config. Technically these could be 555 and 444 respectively
+# but we keep them as 755 and 644 for consistency with CouchDB defaults and the dockerfile_entrypoint.sh.
+    find /opt/couchdb/etc -type d ! -perm 0755 -exec chmod -f 0755 '{}' +; \
+    find /opt/couchdb/etc -type f ! -perm 0644 -exec chmod -f 0644 '{}' +; \
+# only local.d needs to be writable for the docker_entrypoint.sh
+    chmod -f 0777 /opt/couchdb/etc/local.d; \
+# apt clean-up
+    rm -rf /var/lib/apt/lists/*;
 
 # Add configuration
-COPY 10-docker-default.ini /opt/couchdb/etc/default.d/
-COPY vm.args /opt/couchdb/etc/
+COPY --chown=couchdb:couchdb 10-docker-default.ini /opt/couchdb/etc/default.d/
+COPY --chown=couchdb:couchdb vm.args /opt/couchdb/etc/
+
 COPY docker-entrypoint.sh /usr/local/bin
 RUN ln -s usr/local/bin/docker-entrypoint.sh /docker-entrypoint.sh # backwards compat
 ENTRYPOINT ["tini", "--", "/docker-entrypoint.sh"]
 
-# Setup directories and permissions
-RUN find /opt/couchdb \! \( -user couchdb -group couchdb \) -exec chown -f couchdb:couchdb '{}' +
 VOLUME /opt/couchdb/data
 
 # 5984: Main CouchDB endpoint
diff --git a/2.3.1/docker-entrypoint.sh b/2.3.1/docker-entrypoint.sh
index 7fdb04b..be9e099 100755
--- a/2.3.1/docker-entrypoint.sh
+++ b/2.3.1/docker-entrypoint.sh
@@ -25,36 +25,44 @@
 fi
 
 if [ "$1" = '/opt/couchdb/bin/couchdb' ]; then
-	# Check that we own everything in /opt/couchdb and fix if necessary. We also
-	# add the `-f` flag in all the following invocations because there may be
-	# cases where some of these ownership and permissions issues are non-fatal
-	# (e.g. a config file owned by root with o+r is actually fine), and we don't
-	# to be too aggressive about crashing here ...
-	find /opt/couchdb \! \( -user couchdb -group couchdb \) -exec chown -f couchdb:couchdb '{}' +
+	# this is where runtime configuration changes will be written.
+	# we need to explicitly touch it here in case /opt/couchdb/etc has
+	# been mounted as an external volume, in which case it won't exist.
+	# If running as the couchdb user (i.e. container starts as root),
+	# write permissions will be granted below.
+	touch /opt/couchdb/etc/local.d/docker.ini
 
-	# Ensure that data files have the correct permissions. We were previously
-	# preventing any access to these files outside of couchdb:couchdb, but it
-	# turns out that CouchDB itself does not set such restrictive permissions
-	# when it creates the files. The approach taken here ensures that the
-	# contents of the datadir have the same permissions as they had when they
-	# were initially created. This should minimize any startup delay.
-	find /opt/couchdb/data -type d ! -perm 0755 -exec chmod -f 0755 '{}' +
-	find /opt/couchdb/data -type f ! -perm 0644 -exec chmod -f 0644 '{}' +
+	# if user is root, assume running under the couchdb user (default)
+	# and ensure it is able to access files and directories that may be mounted externally
+	if [ "$(id -u)" = '0' ]; then
+		# Check that we own everything in /opt/couchdb and fix if necessary. We also
+		# add the `-f` flag in all the following invocations because there may be
+		# cases where some of these ownership and permissions issues are non-fatal
+		# (e.g. a config file owned by root with o+r is actually fine), and we don't
+		# to be too aggressive about crashing here ...
+		find /opt/couchdb \! \( -user couchdb -group couchdb \) -exec chown -f couchdb:couchdb '{}' +
 
-	# Do the same thing for configuration files and directories. Technically
-	# CouchDB only needs read access to the configuration files as all online
-	# changes will be applied to the "docker.ini" file below, but we set 644
-	# for the sake of consistency.
-	find /opt/couchdb/etc -type d ! -perm 0755 -exec chmod -f 0755 '{}' +
-	find /opt/couchdb/etc -type f ! -perm 0644 -exec chmod -f 0644 '{}' +
+		# Ensure that data files have the correct permissions. We were previously
+		# preventing any access to these files outside of couchdb:couchdb, but it
+		# turns out that CouchDB itself does not set such restrictive permissions
+		# when it creates the files. The approach taken here ensures that the
+		# contents of the datadir have the same permissions as they had when they
+		# were initially created. This should minimize any startup delay.
+		find /opt/couchdb/data -type d ! -perm 0755 -exec chmod -f 0755 '{}' +
+		find /opt/couchdb/data -type f ! -perm 0644 -exec chmod -f 0644 '{}' +
+
+		# Do the same thing for configuration files and directories. Technically
+		# CouchDB only needs read access to the configuration files as all online
+		# changes will be applied to the "docker.ini" file below, but we set 644
+		# for the sake of consistency.
+		find /opt/couchdb/etc -type d ! -perm 0755 -exec chmod -f 0755 '{}' +
+		find /opt/couchdb/etc -type f ! -perm 0644 -exec chmod -f 0644 '{}' +
+	fi
 
 	if [ ! -z "$NODENAME" ] && ! grep "couchdb@" /opt/couchdb/etc/vm.args; then
 		echo "-name couchdb@$NODENAME" >> /opt/couchdb/etc/vm.args
 	fi
 
-	# Ensure that CouchDB will write custom settings in this file
-	touch /opt/couchdb/etc/local.d/docker.ini
-
 	if [ "$COUCHDB_USER" ] && [ "$COUCHDB_PASSWORD" ]; then
 		# Create admin only if not already present
 		if ! grep -Pzoqr "\[admins\]\n$COUCHDB_USER =" /opt/couchdb/etc/local.d/*.ini; then
@@ -69,7 +77,9 @@
 		fi
 	fi
 
-	chown -f couchdb:couchdb /opt/couchdb/etc/local.d/docker.ini || true
+	if [ "$(id -u)" = '0' ]; then
+		chown -f couchdb:couchdb /opt/couchdb/etc/local.d/docker.ini || true
+	fi
 
 	# if we don't find an [admins] section followed by a non-comment, display a warning
         if ! grep -Pzoqr '\[admins\]\n[^;]\w+' /opt/couchdb/etc/default.d/*.ini /opt/couchdb/etc/local.d/*.ini; then
@@ -88,8 +98,9 @@
 		EOWARN
 	fi
 
-
-	exec gosu couchdb "$@"
+	if [ "$(id -u)" = '0' ]; then
+		exec gosu couchdb "$@"
+	fi
 fi
 
 exec "$@"
diff --git a/README.md b/README.md
index 42f0a93..7f7d73a 100644
--- a/README.md
+++ b/README.md
@@ -170,6 +170,15 @@
 
 It is recommended to then mount this path to a directory on the host, as CouchDB logging can be quite voluminous.
 
+## Running under a custom UID
+
+By default, CouchDB will run as the `couchdb` user with UID 5984. Running under a different UID is supported, so long as any volume mounts have appropriate read/write permissions. For example, assuming user `myuser` has write access to `/home/couchdb/data`, the following command will run CouchDB as that user:
+
+```
+docker run --name my-couchdb --user myuser -v /home/couchdb/data:/opt/couchdb/data %%IMAGE%%:tag
+```
+
+
 -----
 
 # Development images