diff --git a/.dockerignore b/.dockerignore
index 979bf6b132087e22b4d76d2bd03294bf8b5b7134..28ec9068be8d0696b56ed5d15daf343902a034a2 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -11,4 +11,4 @@ coverage
 .grunt
 .lock-wscript
 build/Release
-node_modules
\ No newline at end of file
+node_modules
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..b174d0a318d789b67312376d7454cdc3f0239dc1
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,38 @@
+FROM node:10-alpine3.11
+
+WORKDIR /app
+
+# build audiowaveform from source
+
+RUN apk add git make cmake gcc g++ libmad-dev libid3tag-dev libsndfile-dev gd-dev boost-dev libgd libpng-dev zlib-dev
+RUN apk add zlib-static libpng-static boost-static
+
+RUN apk add autoconf automake libtool gettext
+RUN wget https://github.com/xiph/flac/archive/1.3.3.tar.gz
+RUN tar xzf 1.3.3.tar.gz
+RUN cd flac-1.3.3/ && ./autogen.sh
+RUN cd flac-1.3.3/ && ./configure --enable-shared=no
+RUN cd flac-1.3.3/ && make
+RUN cd flac-1.3.3/ && make install
+
+RUN git clone https://github.com/bbc/audiowaveform.git
+RUN mkdir audiowaveform/build/
+RUN cd audiowaveform/build/ && cmake -D ENABLE_TESTS=0 -D BUILD_STATIC=1 ..
+RUN cd audiowaveform/build/ && make
+RUN cd audiowaveform/build/ && make install
+
+# install other requirements
+
+RUN apk add graphicsmagick ffmpeg-dev ghostscript
+
+# install node package
+
+COPY package*.json ./
+RUN npm install
+COPY . .
+
+# start app
+
+EXPOSE 9666
+CMD ["node", "spacedeck.js"]
+
diff --git a/README.md b/README.md
index fcd1216936874771ac9e08822c9c27f409d7a8b5..12ff645df61b49080dcee030cc0e60df3642c98d 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ To install all node dependencies, run (do this once):
 
 # Configuration
 
-See [config/default.json](config/default.json)
+See [config/default.json](config/default.json). Set `storage_local_path` for a local sqlite database or `storage_region`, `storage_bucket`, `storage_cdn` and `storage_endpoint` for AWS S3. `mail_provider` may be one of `console` or `smtp`. Also, omit a trailing `/` for the `endpoint`.
 
 # Run (web server)
 
@@ -63,6 +63,16 @@ For advanced media conversion:
 By default, media files are uploaded to the ```storage``` folder.
 The database is stored in ```database.sqlite``` by default.
 
+# Run with Docker
+
+- configure `config/default.json`
+- configure `volumes` section inside `docker-compose.yml`
+  - point to `database.sqlite` on the host system
+  - `touch database.sqlite` if it not exists
+  - point to `storage/` on the host system
+  - `mkdir storage/` if it not exists
+- start the container with `sudo docker-compose up -f docker-compose.yml -d --build`
+
 # Hacking
 
 To rebuild the frontend CSS styles:
diff --git a/config/default.json b/config/default.json
index 9c60ac36bf218ecd74bb7f859e4b89be9fdf9be4..57ae30af510739a2f88ce754557ff57f566d2aab 100644
--- a/config/default.json
+++ b/config/default.json
@@ -6,13 +6,11 @@
   "invite_code": "top-sekrit",
 
   "storage_region": "eu-central-1",
-  //"storage_bucket": "sdeck-development",
-  //"storage_cdn": "http://localhost:9123/sdeck-development",
-  //"storage_endpoint": "http://storage:9000",
 
   "storage_bucket": "my_spacedeck_bucket",
   "storage_cdn": "/storage",
   "storage_local_path": "./storage",
+  "storage_local_db": "./database.sqlite",
 
   "redis_mock": true,
   "mongodb_host": "localhost",
@@ -23,7 +21,6 @@
   "admin_pass": "very_secret_admin_password",
   "phantom_api_secret": "very_secret_phantom_password",
 
-  // Choose "console" or "smtp"
   "mail_provider": "smtp",
   "mail_smtp_host": "your.smtp.host",
   "mail_smtp_port": 465,
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4823997f2da9615aae05cb0a75de713b173a614f
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,12 @@
+version: "2.0"
+
+services:
+  spacedeck:
+    build: .
+    container_name: spacedeck
+    ports:
+      - "9666:9666"
+    volumes:
+      - /absolute/path/to/storage:/app/storage
+      - /absolute/path/to/database.sqlite:/app/database.sqlite
+
diff --git a/models/db.js b/models/db.js
index a803473b317d97f6f5fbe89952994d0bf66f0665..1024b543e5f563bee06e6b8c69c54b5952a609fc 100644
--- a/models/db.js
+++ b/models/db.js
@@ -1,4 +1,5 @@
 const Umzug = require('umzug');
+const config = require('config')
 
 function sequel_log(a,b,c) {
   console.log(a);
@@ -17,7 +18,7 @@ const sequelize = new Sequelize('database', 'username', 'password', {
   },
 
   // SQLite only
-  storage: 'database.sqlite',
+  storage: config.get('storage_local_db'),
   logging: sequel_log,
 
   // http://docs.sequelizejs.com/manual/tutorial/querying.html#operators