diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..510ecf9
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,3 @@
+node_modules
+dist
+.env.development
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..c383575
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,20 @@
+FROM node:19.4-alpine AS frontend
+
+ARG server_url
+RUN test -n "${server_url}"
+
+COPY glebby-client /glebby-client
+WORKDIR /glebby-client
+RUN npm install
+ENV VITE_GLEBBY_SERVER_URL=${server_url}
+RUN npx vite build --outDir static
+
+FROM python:3.11-alpine
+
+COPY glebby-server /glebby-server
+WORKDIR /glebby-server
+RUN pip install -r requirements.txt
+RUN pip install gunicorn
+COPY --from=frontend /glebby-client/static /glebby-server/static
+
+CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--threads", "100", "glebby:app"]
diff --git a/glebby-server/.gitignore b/glebby-server/.gitignore
index 7f93ebf..cea93c1 100644
--- a/glebby-server/.gitignore
+++ b/glebby-server/.gitignore
@@ -1,2 +1,3 @@
 venv
 __pycache__
+static
diff --git a/glebby-server/glebby.py b/glebby-server/glebby.py
index 74a1329..b9562d6 100644
--- a/glebby-server/glebby.py
+++ b/glebby-server/glebby.py
@@ -152,9 +152,14 @@ class GlebbyState:
 state = GlebbyState()
 state.start_event_thread()
 
-app = Flask(__name__)
+# TODO: Examine Quart (basically an asyncio version of flask)
+app = Flask(__name__, static_url_path='')
 sock = Sock(app)
 
+@app.route('/')
+def index():
+    return app.send_static_file('index.html')
+
 @sock.route('/glebby')
 def echo(sock):
     client_id = state.add_client(sock)