diff --git a/.gitignore b/.gitignore
index 52c2e482..a47f56de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -169,3 +169,6 @@ cython_debug/
 #  and can be added to the global gitignore or merged into this file.  For a more nuclear
 #  option (not recommended) you can uncomment the following to ignore the entire idea folder.
 #.idea/
+
+docker/output/
+docker/data/
diff --git a/docker/.dockerignore b/docker/.dockerignore
new file mode 100644
index 00000000..5b3d79a8
--- /dev/null
+++ b/docker/.dockerignore
@@ -0,0 +1,34 @@
+# Include any files or directories that you don't want to be copied to your
+# container here (e.g., local build artifacts, temporary files, etc.).
+#
+# For more help, visit the .dockerignore file reference guide at
+# https://docs.docker.com/go/build-context-dockerignore/
+
+**/.DS_Store
+**/__pycache__
+**/.venv
+**/.classpath
+**/.dockerignore
+**/.env
+**/.git
+**/.gitignore
+**/.project
+**/.settings
+**/.toolstarget
+**/.vs
+**/.vscode
+**/*.*proj.user
+**/*.dbmdl
+**/*.jfm
+**/bin
+**/charts
+**/docker-compose*
+**/compose*
+**/Dockerfile*
+**/node_modules
+**/npm-debug.log
+**/obj
+**/secrets.dev.yaml
+**/values.dev.yaml
+LICENSE
+README.md
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 00000000..a9ed99c4
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,50 @@
+# syntax=docker/dockerfile:1
+
+# Comments are provided throughout this file to help you get started.
+# If you need more help, visit the Dockerfile reference guide at
+# https://docs.docker.com/go/dockerfile-reference/
+
+# Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7
+
+ARG PYTHON_VERSION=3
+FROM python:${PYTHON_VERSION}-slim as base
+
+# Prevents Python from writing pyc files.
+ENV PYTHONDONTWRITEBYTECODE=1
+
+# Keeps Python from buffering stdout and stderr to avoid situations where
+# the application crashes without emitting any logs due to buffering.
+ENV PYTHONUNBUFFERED=1
+
+WORKDIR /app
+
+# Create a non-privileged user that the app will run under.
+# See https://docs.docker.com/go/dockerfile-user-best-practices/
+ARG UID=10001
+RUN adduser \
+    --disabled-password \
+    --gecos "" \
+    --home "/home/appuser" \
+    --shell "/sbin/nologin" \
+    --uid "${UID}" \
+    appuser
+
+# Copy the source code into the container.
+COPY src/ src/
+
+# Download dependencies as a separate step to take advantage of Docker's caching.
+# Leverage a cache mount to /root/.cache/pip to speed up subsequent builds.
+# Leverage a bind mount to requirements.txt to avoid having to copy them into
+# into this layer.
+RUN --mount=type=cache,target=/root/.cache/pip \
+    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
+    python -m pip install -e ".[test]" --extra-index-url https://download.pytorch.org/whl/cu121
+
+# Switch to the non-privileged user to run the application.
+USER appuser
+
+# Expose the port that the application listens on.
+EXPOSE 8000
+
+# Run the application.
+CMD invoke-train-ui --host 0.0.0.0 --port 8000
diff --git a/docker/compose.yaml b/docker/compose.yaml
new file mode 100644
index 00000000..7909e999
--- /dev/null
+++ b/docker/compose.yaml
@@ -0,0 +1,31 @@
+name: invoke-training
+services:
+  server:
+    image: "local/invokeai-training:latest"
+    build:
+      context: ..
+      dockerfile: docker/Dockerfile
+    ports:
+      - 8000:8000
+    volumes:
+      - ../sample_data:/app/sample_data
+      - ./output:/app/output
+      - ./data:/home/appuser
+    deploy:
+      resources:
+        reservations:
+          devices:
+            - driver: nvidia
+              count: 1
+              capabilities: [gpu]
+  
+  tensorboard:
+    image: "local/invokeai-training:latest"
+    build:
+        context: ..
+        dockerfile: docker/Dockerfile
+    ports:
+      - 8001:8001
+    volumes:
+      - ./output:/app/output
+    command: tensorboard --logdir output/ --bind_all --port 8001