diff --git a/Dockerfile.autobuild b/Dockerfile.autobuild
new file mode 100644
index 0000000..42dfba6
--- /dev/null
+++ b/Dockerfile.autobuild
@@ -0,0 +1,44 @@
+# -----------------------------------------------------------------------------
+# docker-pinry
+#
+# Builds a basic docker image that can run Pinry (http://getpinry.com) and serve
+# all of it's assets, there are more optimal ways to do this but this is the
+# most friendly and has everything contained in a single instance.
+#
+# Authors: Isaac Bythewood
+# Updated: Mar 29th, 2016
+# Require: Docker (http://www.docker.io/)
+# -----------------------------------------------------------------------------
+
+
+# Base system is the LTS version of Ubuntu.
+FROM python:3.6-stretch
+
+RUN groupadd -g 2300 tmpgroup && usermod -g tmpgroup www-data && groupdel www-data && groupadd -g 1000 www-data && usermod -g www-data www-data && usermod -u 1000 www-data && groupdel tmpgroup
+
+RUN apt-get update
+RUN apt-get -y install nginx nginx-extras pwgen
+
+RUN mkdir -p /srv/www/; cd /srv/www/; git clone https://github.com/pinry/pinry.git
+RUN mkdir /srv/www/pinry/logs; mkdir /data
+RUN cd /srv/www/pinry && pip install pipenv && pipenv install --three --system
+RUN pip install gunicorn
+
+# Fix permissions
+RUN chown -R www-data:www-data /srv/www
+
+
+# Load in all of our config files.
+ADD docker-contents/nginx/nginx.conf /etc/nginx/nginx.conf
+ADD docker-contents/nginx/sites-enabled/default /etc/nginx/sites-enabled/default
+
+# Fix permissions
+RUN mkdir /scripts/
+ADD docker-contents/scripts/* /scripts/
+RUN chown -R www-data:www-data /data
+RUN mkdir /var/log/gunicorn
+
+# 80 is for nginx web, /data contains static files and database /start runs it.
+expose 80
+volume ["/data"]
+cmd ["/scripts/start.sh"]
diff --git a/docker-contents/CONTRIBUTORS.rst b/docker-contents/CONTRIBUTORS.rst
new file mode 100644
index 0000000..7a5a178
--- /dev/null
+++ b/docker-contents/CONTRIBUTORS.rst
@@ -0,0 +1,14 @@
+Contributors
+============
+
+The core contributors for Pinry have been/currently are:
+
+* Isaac Bythewood
+* Krzysztof Klimonda
+
+For a full list of contributors check out the `GitHub Contributors Graph`_.
+
+.. Links
+
+.. _GitHub Contributors Graph: https://github.com/pinry/pinry/graphs/contributors
+
diff --git a/docker-contents/LICENSE.rst b/docker-contents/LICENSE.rst
new file mode 100644
index 0000000..f090ecc
--- /dev/null
+++ b/docker-contents/LICENSE.rst
@@ -0,0 +1,27 @@
+License (Simplified BSD)
+========================
+
+| Copyright (c) Pinry Contributors
+| All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/docker-contents/README.rst b/docker-contents/README.rst
new file mode 100644
index 0000000..9dbdadd
--- /dev/null
+++ b/docker-contents/README.rst
@@ -0,0 +1,137 @@
+docker-pinry
+============
+
+.. image:: https://travis-ci.org/pinry/docker-pinry.svg?branch=master
+ :target: https://travis-ci.org/pinry/docker-pinry
+
+A nice and easy way to get a pinry instance up and running using docker. For
+help on getting started with docker see the `official getting started guide`_.
+For more information on Pinry and a demo check out it's `website`_.
+
+
+Getting docker-pinry
+---------------------
+
+Running this will get the latest version of both
+docker-pinry and pinry itself::
+
+ git clone https://github.com/pinry/docker-pinry
+ cd docker-pinry
+ ./bootstrap.sh
+
+Now you can start your container by command like this::
+
+ # this is where your database and pins localted
+ mkdir data
+ # use absolute path for docker to avoid using default data-volume (we use directory instead)
+ ./start_docker.sh `readlink -f data`
+
+Please visit `http://your-ip` to visit your instance and register a new account, enjoy it.
+
+
+Configuring docker-pinry
+------------------------
+Enable signups for new users by editing ``pinry/local_settings.py``::
+
+ ALLOW_NEW_REGISTRATIONS = True
+
+`Additional pinry configuration settings`_
+
+Building docker-pinry again
+---------------------------
+
+Running this will build you a docker image with the latest version of both
+docker-pinry and pinry itself::
+
+ ./build_docker.sh
+
+
+Running docker-pinry in manual way
+----------------------------------
+
+Running the start command for the first time will setup your production secret
+key, database and static files. It is important that you decide what port you
+want and what location on the host machine you wish to store your files. If this
+is the only thing running on your system and you wish to make it public without
+a proxy then you can set ``-p=80:80``. The setting ``-p=10000:80`` assumes you
+are wanting to proxy to this instance using something like nginx. Also note that
+you must have your host mount directory created first (``mkdir -p /mnt/pinry``)
+
+Then you have two choice to run docker-pinry
+
+Fist one, with automaticlly configured default arguments::
+
+ ./start_docker.sh /mnt/pinry
+
+
+Second one, start docker by hand with customized arguments::
+
+ SETTINGS_PATH=$(readlink -f ./pinry/local_settings.py) \
+ DATA_PATH=$(readlink -f /mnt/pinry) \
+ sudo docker run -d=true -p=10000:80 \
+ -v=${DATA_PATH}:/data \
+ -v=${SETTINGS_PATH}:/srv/www/pinry/pinry/settings/local_settings.py \
+ pinry/pinry /scripts/start.sh
+
+If it's the first run it'll take a few seconds but it will print out your
+container ID which should be used to start and stop the container in the future
+using the commands::
+
+ sudo docker start
+ sudo docker stop
+
+
+Running docker-pinry with docker-compose
+-----------------------------------------
+
+
+Just config your ``docker-compose.yml`` and then run::
+
+ sudo pip install -U docker-compose
+ sudo docker-compose up -d
+
+
+Notes on the run commands
+`````````````````````````
+
+* ``-v`` is the volume you are mounting ``-v=host_dir:docker_dir``
+* ``pinry/pinry`` is simply what I called my docker build of this image
+* ``-d=true`` allows this to run cleanly as a daemon, remove for debugging
+* ``-p`` is the port it connects to, ``-p=host_port:docker_port``
+* Follow comments in ``local_settings.py`` to understand how the site configured
+
+Using docker-pinry
+------------------
+Open a browser to ``http://:10000`` and register. Replace YOUR-HOSTNAME with the name
+of the machine docker is running on, likely localhost.
+
+You can map ``http://localhost:10000`` to your outer nginx for SSL or just change
+the default port-mapping to ``80:80`` to serve your site directly, just enjoy!
+
+
+Why include nginx and not just map to gunicorn directly?
+-----------------------------------------------------------
+
+Because gunicorn/django can't serve static files very well and it is unwise to do
+so for security reasons. I built this so that people can have a full hosted
+solution in a container. If you have a host machine running nginx then of course
+there is no point to run nginx in the container as well, you can simply disable
+nginx, map gunicorn to a port and then set your host machine's nginx to display
+your media and static files since that directory is shared between the container
+and host.
+
+
+Why use sqlite3?
+----------------
+
+Because it has a very low resource cost and most pinry websites are small
+personal ones. Why have a full on database for that? If you need more power
+than you can easily modify the `pinry/local_settings.py` to point to a
+stronger database solution.
+
+
+.. Links
+
+.. _official getting started guide: http://www.docker.io/gettingstarted/
+.. _website: http://getpinry.com/
+.. _additional pinry configuration settings: https://github.com/pinry/docker-pinry/blob/master/pinry/local_settings.example.py
diff --git a/docker-contents/bootstrap.sh b/docker-contents/bootstrap.sh
new file mode 100644
index 0000000..2aab8b8
--- /dev/null
+++ b/docker-contents/bootstrap.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+# Force users to login before seeing any pins.
+if [ "${ALLOW_NEW_REGISTRATIONS}" = "" ]; then
+ ALLOW_NEW_REGISTRATIONS=true
+fi
+
+if [[ "$(docker images -q pinry/pinry 2> /dev/null)" == "" ]]; then
+ echo "No docker image found, building..." && ./build_docker.sh
+fi
+
+echo "=================================================================================="
+echo "Note: Please copy this key and keep it in a secure place."
+echo "Then you should manually edit your pinry/local_settings.py"
+echo "and replace SECRET_KEY with new secret-key if you had previously generated a"
+echo "pinry/local_settings.py."
+echo "If no previous pinry/local_settings.py generated, you can have a look and edit it."
+echo "If you want to use docker-compose, just edit docker-compose.yml and use 'docker-compose up'"
+
+SECRET_KEY=$(sudo docker run pinry/pinry /scripts/gen_key.sh)
+
+echo ""
+echo "Your secret-key is(also saved/overwritten your pinry/production_secret_key.txt):"
+echo ""
+echo ${SECRET_KEY}
+echo "=================================================================================="
+
+# Create local_settings.py
+if [ ! -f ./pinry/local_settings.py ];
+then
+ cp ./pinry/local_settings.example.py ./pinry/local_settings.py
+ sed -i "s/secret\_key\_place\_holder/${SECRET_KEY}/" ./pinry/local_settings.py
+
+ # Force users to login before seeing any pins.
+ if [ "${PRIVATE}" = "true" ]; then
+ sed -i "s/PUBLIC = True/PUBLIC = False/" ./pinry/local_settings.py
+ fi
+
+ # Enable people from creating new accounts.
+ if [ "${ALLOW_NEW_REGISTRATIONS}" = "true" ]; then
+ sed -i "s/ALLOW_NEW_REGISTRATIONS = False/ALLOW_NEW_REGISTRATIONS = True/" ./pinry/local_settings.py
+ fi
+fi
+
+# Copy to docker-compose.yml
+if [ ! -f ./docker-compose.yml ];
+then
+ cp ./docker-compose.example.yml ./docker-compose.yml
+fi
diff --git a/docker-contents/build_docker.sh b/docker-contents/build_docker.sh
new file mode 100644
index 0000000..a91c34c
--- /dev/null
+++ b/docker-contents/build_docker.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+sudo docker build --no-cache -t pinry/pinry${@} .
diff --git a/docker-contents/docker-compose.example.yml b/docker-contents/docker-compose.example.yml
new file mode 100644
index 0000000..61abd05
--- /dev/null
+++ b/docker-contents/docker-compose.example.yml
@@ -0,0 +1,16 @@
+version: '3'
+
+services:
+ web:
+ build: .
+ command: >
+ bash -c "/scripts/start.sh"
+ ports:
+# if you use "127.0.0.1", no one except you can visit it from within
+# - "127.0.0.1:10000:8000"
+ - "80:80"
+ volumes:
+ # overwrite local_settings, you can always modify your local_settings file
+ - ./pinry/local_settings.py:/srv/www/pinry/pinry/settings/local_settings.py
+ - ./data/:/data/
+ restart: always
diff --git a/docker-contents/nginx/nginx.conf b/docker-contents/nginx/nginx.conf
new file mode 100644
index 0000000..d77653e
--- /dev/null
+++ b/docker-contents/nginx/nginx.conf
@@ -0,0 +1,35 @@
+user www-data;
+worker_processes 4;
+pid /run/nginx.pid;
+
+events {
+ worker_connections 768;
+}
+
+http {
+ sendfile on;
+ tcp_nopush on;
+ tcp_nodelay on;
+ keepalive_timeout 65;
+ types_hash_max_size 2048;
+ client_max_body_size 1m;
+
+ server_names_hash_bucket_size 64;
+
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ access_log /var/log/nginx/access.log;
+ error_log /var/log/nginx/error.log;
+
+ gzip on;
+ gzip_disable "msie6";
+ gzip_vary on;
+ gzip_proxied any;
+ gzip_comp_level 6;
+ gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
+
+ include /etc/nginx/conf.d/*.conf;
+ include /etc/nginx/sites-enabled/*;
+}
+
diff --git a/docker-contents/nginx/sites-enabled/default b/docker-contents/nginx/sites-enabled/default
new file mode 100644
index 0000000..02180d7
--- /dev/null
+++ b/docker-contents/nginx/sites-enabled/default
@@ -0,0 +1,26 @@
+server {
+ listen 80 default;
+ server_name _;
+
+ access_log /srv/www/pinry/logs/access.log;
+ error_log /srv/www/pinry/logs/error.log;
+
+ location /media {
+ alias /data/static/media;
+ expires max;
+ access_log off;
+ }
+
+ location /static {
+ alias /data/static;
+ expires max;
+ access_log off;
+ }
+
+ location / {
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $remote_addr;
+ proxy_pass http://localhost:8000;
+ }
+}
diff --git a/docker-contents/pinry/.gitignore b/docker-contents/pinry/.gitignore
new file mode 100644
index 0000000..49ce140
--- /dev/null
+++ b/docker-contents/pinry/.gitignore
@@ -0,0 +1,2 @@
+local_settings.py
+production_secret_key.txt
\ No newline at end of file
diff --git a/docker-contents/pinry/local_settings.example.py b/docker-contents/pinry/local_settings.example.py
new file mode 100644
index 0000000..d66ba5a
--- /dev/null
+++ b/docker-contents/pinry/local_settings.example.py
@@ -0,0 +1,44 @@
+import os
+
+
+# Please don't change following settings unless you know what you are doing
+STATIC_ROOT = '/data/static'
+
+MEDIA_ROOT = os.path.join(STATIC_ROOT, 'media')
+
+# SECURITY WARNING: keep the secret key used in production secret!
+# Or just write your own secret-key here instead of using a env-variable
+SECRET_KEY = "secret_key_place_holder"
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = False
+TEMPLATE_DEBUG = DEBUG
+
+# SECURITY WARNING: use your actual domain name in production!
+ALLOWED_HOSTS = ['*']
+
+# Database
+# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': '/data/production.db',
+ }
+}
+
+# Allow users to register by themselves
+ALLOW_NEW_REGISTRATIONS = False
+
+# Delete image files once you remove your pin
+IMAGE_AUTO_DELETE = True
+
+# thumbnail size control
+IMAGE_SIZES = {
+ 'thumbnail': {'size': [240, 0]},
+ 'standard': {'size': [600, 0]},
+ 'square': {'crop': True, 'size': [125, 125]},
+}
+
+# Whether people can view pins without login
+PUBLIC = True
diff --git a/docker-contents/scripts/_start_gunicorn.sh b/docker-contents/scripts/_start_gunicorn.sh
new file mode 100644
index 0000000..00bd77e
--- /dev/null
+++ b/docker-contents/scripts/_start_gunicorn.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+gunicorn pinry.wsgi -b 0.0.0.0:8000 -w 4 \
+ --capture-output --timeout 30 --user www-data --group www-data
\ No newline at end of file
diff --git a/docker-contents/scripts/gen_key.sh b/docker-contents/scripts/gen_key.sh
new file mode 100644
index 0000000..ddc28e0
--- /dev/null
+++ b/docker-contents/scripts/gen_key.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# Check for secret key if one doesn't exist create.
+if [ ! -f /data/production_secret_key.txt ]
+then
+ cd /data
+ PRODUCTION_SECRET_KEY=`pwgen -c -n -1 65`
+ echo $PRODUCTION_SECRET_KEY > /data/production_secret_key.txt
+else
+ PRODUCTION_SECRET_KEY=`cat /data/production_secret_key.txt`
+fi
+
+echo ${PRODUCTION_SECRET_KEY}
diff --git a/docker-contents/scripts/start.sh b/docker-contents/scripts/start.sh
new file mode 100644
index 0000000..68251c9
--- /dev/null
+++ b/docker-contents/scripts/start.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# docker-pinry /start script
+#
+# Will setup database and static files if they don't exist already, if they do
+# just continues to run docker-pinry.
+#
+# Authors: Isaac Bythewood
+# Updated: Aug 19th, 2014
+# -----------------------------------------------------------------------------
+
+
+# If static files don't exist collect them
+if [ ! -d /data/static ]
+then
+ cd /srv/www/pinry
+ python manage.py collectstatic --noinput
+fi
+
+# If database doesn't exist yet create it
+if [ ! -f /data/production.db ]
+then
+ cd /srv/www/pinry
+ python manage.py migrate --noinput --settings=pinry.settings.docker
+fi
+
+# Fix all settings after all commands are run
+chown -R www-data:www-data /data
+
+# start all process
+/usr/sbin/nginx
+
+cd /srv/www/pinry/
+/scripts/_start_gunicorn.sh
diff --git a/docker-contents/start_docker.sh b/docker-contents/start_docker.sh
new file mode 100644
index 0000000..c6b1d93
--- /dev/null
+++ b/docker-contents/start_docker.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+DATA_PATH=${1}
+HERE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+SETTINGS_PATH="${HERE}/pinry/local_settings.py"
+
+if [ "${DATA_PATH}" = "" ]
+then
+ echo "usage: start_docker.sh /abs/path/to/your/data/store"
+ exit 1
+fi
+
+sudo docker run -d=true -p=80:80 \
+ -v=${DATA_PATH}:/data \
+ -v=${SETTINGS_PATH}:/srv/www/pinry/pinry/settings/local_settings.py \
+ pinry/pinry /scripts/start.sh
diff --git a/docker-contents/tests/http_status_code.sh b/docker-contents/tests/http_status_code.sh
new file mode 100644
index 0000000..6295288
--- /dev/null
+++ b/docker-contents/tests/http_status_code.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+set -e
+
+usage() {
+ cat <