diff --git a/.docker/entrypoint.sh b/.docker/entrypoint.sh
new file mode 100644
index 0000000000000000000000000000000000000000..0ecff72338fc62dc9b9c1be69222c6a16fa4c061
--- /dev/null
+++ b/.docker/entrypoint.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+function wait_for_db()
+{
+  while ! ./manage.py sqlflush > /dev/null 2>&1 ;do
+    echo "Waiting for the db to be ready."
+    sleep 1
+  done
+}
+
+if [ "$SECRET_KEY" == "" ] ;then
+  echo "Need the environment variable SECRET_KEY."
+  exit 1
+fi
+
+echo "" > ./AKPlanning/settings_secrets.py # Reset file in case we ran before
+echo "SECRET_KEY = '$SECRET_KEY'" >> ./AKPlanning/settings_secrets.py
+echo "HOSTS = $HOSTS" >> ./AKPlanning/settings_secrets.py
+echo "DB_NAME = '$DB_NAME'" >> ./AKPlanning/settings_secrets.py
+echo "DB_USER = '$DB_USER'" >> ./AKPlanning/settings_secrets.py
+echo "DB_PASSWORD = '$DB_PASSWORD'" >> ./AKPlanning/settings_secrets.py
+echo "DB_HOST = '$DB_HOST'" >> ./AKPlanning/settings_secrets.py
+
+if [ "$AUTO_MIGRATE_DB" == "true" ] ;then
+  wait_for_db
+  echo "Applying DB migrations"
+  ./manage.py migrate
+fi
+
+if [ "$DJANGO_SUPERUSER_PASSWORD" != "" ] ;then
+  wait_for_db
+  echo "Trying to create superuser."
+  ./manage.py createsuperuser --noinput
+fi
+
+env | while IFS= read -r line; do
+    value=${line#*=}
+    name=${line%%=*}
+    case $name in EXTRA_DJANGO_SETTING*)
+      echo -e "$value" > "./AKPlanning/settings/$name.py"
+    esac
+done
+
+./manage.py collectstatic --noinput
+./manage.py compilemessages -l de_DE
+uwsgi --ini .docker/uwsgi.ini
diff --git a/.docker/extra_requirements.txt b/.docker/extra_requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b64ab47dac5a3f12d7817e2c402f71d83f5c1102
--- /dev/null
+++ b/.docker/extra_requirements.txt
@@ -0,0 +1 @@
+uwsgi==2.0.19.1
diff --git a/.docker/uwsgi.ini b/.docker/uwsgi.ini
new file mode 100644
index 0000000000000000000000000000000000000000..7115f719b2439ceb4e2a882fa49cc8b80d5d56d2
--- /dev/null
+++ b/.docker/uwsgi.ini
@@ -0,0 +1,6 @@
+[uwsgi]
+socket = 0.0.0.0:3035
+wsgi-file = AKPlanning/wsgi.py
+env = DJANGO_SETTINGS_MODULE=AKPlanning.settings_production
+processes = 4
+threads = 2
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..ba3357efd35d688947d54565fb72214acbe627c9
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,11 @@
+apache-akplanning.conf
+CODE_OF_CONDUCT.md
+CONTRIBUTING.md
+CONTRIBUTORS.md
+.git
+.gitignore
+.gitlab-ci.yml
+INSTALL.md
+LICENSE.md
+README.md
+uwsgi-akplanning.ini
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..32041dcb86e187e2803dac267f672bc8f4339806
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,15 @@
+FROM python:3-alpine
+
+RUN apk add --no-cache gcc python3-dev musl-dev libffi-dev mariadb-connector-c-dev gettext
+
+ADD . /app
+WORKDIR /app
+
+RUN pip install -r requirements.txt -r .docker/extra_requirements.txt
+
+ENV DJANGO_SETTINGS_MODULE=AKPlanning.settings_production
+
+RUN mkdir /app/AKPlanning/settings
+
+EXPOSE 3035
+CMD ["sh", "/app/.docker/entrypoint.sh"]
diff --git a/INSTALL.md b/INSTALL.md
index 407945e82631fc8b733940804cd5ac0c5075561f..f242088a0f8ae324465347de2848f236d4902b3c 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -104,6 +104,140 @@ is not stored in any repository or similar, and disable DEBUG mode (``settings.p
 1. restart uwsgi ``sudo systemctl restart uwsgi``
 1. execute the update script ``./Utils/update.sh --prod``
 
+
+## Deployment Setup using Docker
+This project also provides a docker file for easy deployment.
+
+The container described by the docker file only contains the project itself.
+Additional containers for the database and webserver are needed to use it.
+
+The following [docker-compose](https://docs.docker.com/compose/) file shows a typical usage:
+```
+version: "3"
+
+networks:
+  akplanning:
+    external: false
+
+volumes:
+  static-files:
+
+services:
+  mariadb:
+    image: mariadb:10
+    restart: always
+    environment:
+      MYSQL_ROOT_PASSWORD: supermegasecrey
+      MYSQL_DATABASE: akplanning
+      MYSQL_USER: akplanning
+      MYSQL_PASSWORD: secret
+      TZ: Europe/Berlin
+    networks:
+      - akplanning
+
+  akplanning-server:
+    image: neumantm/akplanning:2021-03-10
+    restart: always
+    environment:
+      SECRET_KEY: superlongandsupersecret
+      DB_HOST: mariadb
+      DB_USER: akplanning
+      DB_NAME: akplanning
+      DB_PASSWORD: secret
+      HOSTS: "['akplanning.example.net', 'akplanning.example.de']"
+      TZ: Europe/Berlin
+      AUTO_MIGRATE_DB: 'true'
+      DJANGO_SUPERUSER_USERNAME: admin
+      DJANGO_SUPERUSER_EMAIL: admin@example.com
+      DJANGO_SUPERUSER_PASSWORD: supersecret
+      EXTRA_DJANGO_SETTING_FOO: DJANGO_FOO = True\nDJANGO_BAR = False
+    depends_on:
+      - mariadb
+    networks:
+      - akplanning
+    volumes:
+      - static-files:/app/static
+
+  web-server:
+    image: nginx
+    restart: always
+    volumes:
+      - /path/to/nginx.conf:/etc/nginx/nginx.conf:ro
+      - static-files:/var/www/akplanning-static
+    ports:
+      - "8080:80"
+    depends_on:
+      - akplanning-server
+    networks:
+      - akplanning
+```
+
+The `nginx.conf` would look like this:
+
+```
+user  nginx;
+worker_processes  1;
+error_log  /var/log/nginx/error.log warn;
+pid        /var/run/nginx.pid;
+
+events {
+    worker_connections  1024;
+}
+
+http {
+    include       /etc/nginx/mime.types;
+    default_type  application/octet-stream;
+    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                      '$status $body_bytes_sent "$http_referer" '
+                      '"$http_user_agent" "$http_x_forwarded_for"';
+    access_log  /var/log/nginx/access.log  main;
+    sendfile        on;
+    keepalive_timeout  65;
+    server {
+        listen      80;
+        server_name localhost:8080;
+
+        location /static/ {
+            alias /var/www/akplanning-static/;
+        }
+
+        location / {
+            include /etc/nginx/uwsgi_params;
+            uwsgi_pass uwsgi://akplanning-server:3035;
+        }
+    }
+}
+```
+### Initializing and migrating database
+On the first start, the database must be initialized (the Tables created and so on).
+When updating the project the database must be migrated.
+Both are done using the `migrate` command.
+
+This can be done manually by running the following command after the container has started:
+`docker-compose exec -it akplanning-server ./manage.py migrate`
+
+It can also be done automatically on each container start by setting `AUTO_MIGRATE_DB` to the string `true`
+(as shown in the docker-compose file above).
+
+Database migration may lead to the corruption or loss of data in some cases.
+Make sure you have a backup before running the command and be very careful with enabling auto migration.
+
+### Creating initial superuser
+There are two ways to create the initial superuser when using the docker container.
+For both the database must have been intialized before.
+
+The first way is already shown in the docker-compose file above:
+Using the environment variables `DJANGO_SUPERUSER_{USERNAME,EMAIL,PASSWORD}`.
+
+The second way is to run the following command after the container has started:
+`docker-compose exec -it akplanning-server ./manage.py createsuperuser`
+
+### Extra django settings
+For simple cases you can pass environment variables starting with `EXTRA_DJANGO_SETTING`.
+The content of such variables is written into python files, which are loaded as settings.
+
+For more complex scenarios you can also mount a docker volume to `/app/AKPlanning/settings` and add any number of python files to the volume.
+
 ## Updates
 
 To update the setup to the current version on the main branch of the repository use the update
@@ -111,3 +245,7 @@ script ``Utils/update.sh`` or ``Utils/update.sh --prod`` in production.
 
 Afterwards, you may check your setup by executing ``Utils/check.sh`` or ``Utils/check.sh --prod`` in production.
 
+### Updating when using docker
+
+To update when using docker, just switch the tag of the image for `akplanning-server`.
+Then (if `AUTO_MIGRATE_DB` is not enabled), do a database migration as described in [Initializing and migrating database](#initializing-and-migrating-database)