diff --git a/.containerignore b/.containerignore
new file mode 120000
index 0000000000000000000000000000000000000000..3e4e48b0b5fe6b468434d6767749b399319f2da2
--- /dev/null
+++ b/.containerignore
@@ -0,0 +1 @@
+.gitignore
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 11c022d2e867e6ecad7c0c90c933ba7b17e388c3..5fc546cb4db079a33cd463c7e7e5752245b9ab9b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 *.pdf
 /instance
 /schilder2000/static
+/gunicorn.conf.py
 
 # Byte-compiled / optimized / DLL files
 __pycache__/
diff --git a/Containerfile b/Containerfile
new file mode 100644
index 0000000000000000000000000000000000000000..250a2cf65d2fb1ce3f556203261985cecea7215a
--- /dev/null
+++ b/Containerfile
@@ -0,0 +1,26 @@
+FROM docker.io/library/node:20-alpine AS build-node
+WORKDIR /usr/app
+COPY . .
+RUN ["npm", "ci"]
+RUN ["npm", "run", "build"]
+
+FROM docker.io/library/python:3.12-alpine AS build-python
+WORKDIR /usr/src/app
+COPY . .
+COPY --from=build-node /usr/app/schilder2000/static ./schilder2000/static
+RUN ["apk", "add", "git"]
+RUN ["pip", "install", "build"]
+RUN ["pyproject-build", "-C", "without-npm"]
+
+FROM docker.io/library/python:3.12-alpine
+RUN ["apk", "add", "pango", "font-terminus", "font-inconsolata", "font-dejavu", "font-noto", "font-noto-cjk", "font-awesome", "font-noto-extra", "libldap", "mariadb-connector-c"]
+COPY --from=build-python /usr/src/app/dist/schilder2000-*.whl /tmp/
+RUN apk add -t .build-deps build-base mysql-dev openldap-dev git && \
+	pip install gunicorn /tmp/schilder2000-*.whl schilder2000[all] && \
+	rm /tmp/schilder2000-*.whl && \
+	apk del .build-deps
+VOLUME /usr/local/var/schilder2000-instance/
+COPY examples /usr/local/var/schilder2000-instance
+WORKDIR /usr/local/var/schilder2000-instance/
+ENV FLASK_APP=schilder2000
+CMD ["gunicorn", "schilder2000:create_app()"]
diff --git a/examples/gunicorn.conf.py b/examples/gunicorn.conf.py
new file mode 100644
index 0000000000000000000000000000000000000000..cf53d5ca520f2bea836be59938422bc5dfbdf6c5
--- /dev/null
+++ b/examples/gunicorn.conf.py
@@ -0,0 +1,3 @@
+wsgi_app = "schilder2000:create_app()"
+bind = "[::]:8080"
+accesslog = "-"