diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..3c3629e6
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+node_modules
diff --git a/.nvmrc b/.nvmrc
index 790e1105..b8e593f5 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-v20.10.0
+20.15.1
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..18a83d7a
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,82 @@
+# Build stage
+FROM python:3.12.4 as builder
+
+WORKDIR /app
+
+# Install system dependencies
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ curl \
+ build-essential \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install Python dependencies
+COPY requirements /app/requirements
+RUN pip install --no-cache-dir -r requirements/dev.txt
+
+# Install NVM and Node.js
+ENV NVM_DIR /root/.nvm
+# This should match the version referenced below in the Run stage, and in entrypoint.sh
+ENV NODE_VERSION 20.15.1
+
+COPY package.json package-lock.json /app/
+
+RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash \
+ && . "$NVM_DIR/nvm.sh" \
+ && nvm install ${NODE_VERSION} \
+ && nvm use v${NODE_VERSION} \
+ && nvm alias default v${NODE_VERSION} \
+ && npm install
+
+
+# Runtime stage
+FROM python:3.12.4
+
+WORKDIR /app
+
+# Copy Python environment from builder
+COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
+COPY --from=builder /usr/local/bin /usr/local/bin
+
+# Copy Node.js environment from builder
+COPY --from=builder /root/.nvm /root/.nvm
+ENV NVM_DIR /root/.nvm
+
+# The version in this path should match the version referenced above in the Run stage, and in entrypoint.sh
+ENV PATH $NVM_DIR/versions/node/v20.15.1/bin:$PATH
+
+COPY --from=builder /app/node_modules /app/node_modules
+
+COPY . /app
+
+# Run migrations and create initial data
+RUN python manage.py migrate && \
+ python manage.py shell <`_
* `Live Demo `_
-
* `Documentation `_
+* Quick Start: Clone and then ``docker compose up``
-* `Website `_
+Video Tour:
.. |inline-image| image:: https://sql-explorer.s3.amazonaws.com/video-thumbnail.png
:target: https://sql-explorer.s3.amazonaws.com/Sql+Explorer+5.mp4
:height: 10em
-* Demo video: |inline-image|
+|inline-image|
SQL Explorer aims to make the flow of data between people fast,
simple, and confusion-free. It is a Django-based application that you
@@ -97,9 +98,8 @@ Screenshots
Development
------------
-Included is a test_project that you can use to kick the tires. Just
-create a new virtualenv, cd into ``test_project`` and run ``start.sh`` (or
-walk through the steps yourself) to get a test instance of the app up
-and running.
+Included is a test_project that you can use to kick the tires. You can run this via ``docker compose up``
+
+You can now navigate to 127.0.0.1:8000/explorer/, log in with admin/admin, and begin exploring!
-You can now navigate to 127.0.0.1:8000/explorer/ and begin exploring!
+This will also run a Vite dev server with hot reloading for front-end changes.
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..37f61587
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,15 @@
+services:
+ web:
+ build: .
+ command: ["python", "manage.py", "runserver", "0.0.0.0:8000"]
+ ports:
+ - "8000:8000"
+ - "5173:5173"
+ volumes:
+ - .:/app
+ - node_modules:/app/node_modules
+ environment:
+ - DJANGO_SETTINGS_MODULE=test_project.settings
+
+volumes:
+ node_modules:
diff --git a/docs/development.rst b/docs/development.rst
index f1779cce..ff9939eb 100644
--- a/docs/development.rst
+++ b/docs/development.rst
@@ -1,23 +1,20 @@
Running Locally (quick start)
-----------------------------
-Included is a test_project that you can use to kick the tires. Just
-create a new virtualenv, cd into ``test_project`` and run ``start.sh`` (or
-walk through the steps yourself) to get a test instance of the app up
-and running.
+Whether you have cloned the repo, or installed via pip, included is a test_project that you can use to kick the tires.
-You can now navigate to 127.0.0.1:8000/explorer/ and begin exploring!
+Run:
+
+``docker compose up``
+
+You can now navigate to 127.0.0.1:8000/explorer/, log in with admin/admin, and begin exploring!
Installing From Source
----------------------
-If you are installing SQL Explorer from source (by cloning the repository),
-you may want to first look at simply running test_project/start.sh.
-
-If you want to install SQL Explorer from source, into an existing project,
-you can do so by cloning the repository and following the usual
-:doc:`development` instructions, and then additionally building the front-end
-dependencies:
+If you want to install SQL Explorer from source (e.g. not from the built PyPi package),
+into an existing project, you can do so by cloning the repository and following the usual
+:doc:`install` instructions, and then additionally building the front-end dependencies:
::
@@ -33,30 +30,16 @@ phase. Copy the /explorer directory into site-packages and you're ready to go.
Tests
-----
-Factory Boy is needed if you'd like to run the tests. They can be run with:
+Install the dev requirements:
+
+``pip install -r requirements/dev.txt``
+
+And then:
``python manage.py test --settings=tests.settings``
-and with coverage:
+Or with coverage:
``coverage run --source='.' manage.py test --settings=tests.settings``
``coverage combine``
``coverage report``
-
-Running Celery
---------------
-
-To run tests with Celery enabled, you will need to install Redis and Celery.
-::
-
- brew install redis
- pip install celery
- pip install redis
-
-Then run the redis server and the celery worker. A good way of doing it is:
-::
-
- screen -d -S 'redis' -m redis-server
- screen -d -S 'celery' -m celery -A test_project worker
-
-Finally, set ``EXPLORER_TASKS_ENABLED`` to True in tests.settings and run the tests.
diff --git a/docs/install.rst b/docs/install.rst
index 08d0e9a1..f16fa5ea 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -19,11 +19,7 @@ Install with pip from pypi:
$ pip install django-sql-explorer
-If you would also like to support downloading Excel files install with the dependency using:
-
-.. code-block:: shell-session
-
- $ pip install django-sql-explorer[xls]
+Take a look at available ``extras``
Add to your ``INSTALLED_APPS``, located in the ``settings.py`` file in your project folder:
diff --git a/entrypoint.sh b/entrypoint.sh
new file mode 100644
index 00000000..0de39967
--- /dev/null
+++ b/entrypoint.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# entrypoint.sh
+
+set -e
+
+# Source the nvm script to set up the environment
+# This should match the version referenced in Dockerfile
+. /root/.nvm/nvm.sh
+nvm use 20.15.1
+
+# Django
+python manage.py migrate
+python manage.py runserver 0.0.0.0:8000 &
+echo "Django server started"
+
+# Vite dev server
+export APP_VERSION=$(python -c 'from explorer import __version__; print(__version__)')
+echo "Starting Vite with APP_VERSION=${APP_VERSION}"
+npx vite --config vite.config.mjs
diff --git a/explorer/tests/settings.py b/explorer/tests/settings.py
index 9331a998..a6e83db8 100644
--- a/explorer/tests/settings.py
+++ b/explorer/tests/settings.py
@@ -1,9 +1,8 @@
from test_project.settings import * # noqa
EXPLORER_ENABLE_ANONYMOUS_STATS = False
-EXPLORER_TASKS_ENABLED = True # set to true to test async tasks
-EXPLORER_AI_API_KEY = None # set to any value to enable assistant
-EXPLORER_CHARTS_ENABLED = False
+EXPLORER_TASKS_ENABLED = True
+EXPLORER_AI_API_KEY = "foo"
CELERY_BROKER_URL = "redis://localhost:6379/0"
CELERY_TASK_ALWAYS_EAGER = True
TEST_MODE = True
diff --git a/explorer/tests/settings_base.py b/explorer/tests/settings_base.py
index af91b9e0..5445c9b4 100644
--- a/explorer/tests/settings_base.py
+++ b/explorer/tests/settings_base.py
@@ -2,3 +2,5 @@
EXPLORER_TASKS_ENABLED = False
EXPLORER_USER_UPLOADS_ENABLED = False
+EXPLORER_CHARTS_ENABLED = False
+EXPLORER_AI_API_KEY = None
diff --git a/test_project/start.sh b/test_project/start.sh
deleted file mode 100644
index 98e63f09..00000000
--- a/test_project/start.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-
-pip install -r ../requirements/dev.txt
-pip install django
-
-python ../manage.py migrate
-
-# Set up an admin user, and a sample query
-python ../manage.py shell </dev/null 2>&1; then
- nvm install
- nvm use
-else
- # Check Node version if nvm is not installed
- current_node_version=$(node -v | cut -d. -f1 | sed 's/v//')
- required_node_version=18
- if [ "$current_node_version" -lt "$required_node_version" ]; then
- echo "Node version is less than 18.0 and nvm is not installed. Please install nvm or upgrade node and re-run."
- proceed_with_npm=false
- fi
-fi
-
-if [ "$proceed_with_npm" = true ] ; then
- npm install
- # Start Django server in the background and get its PID
- python ../manage.py runserver 0:8000 &
- DJANGO_PID=$!
-
- # Set a trap to kill the Django server when the script exits
- trap "echo 'Stopping Django server'; kill $DJANGO_PID" EXIT INT
-
- # Start Vite dev server
- npm run dev
-fi
diff --git a/vite.config.mjs b/vite.config.mjs
index adfc2133..0084ca6b 100644
--- a/vite.config.mjs
+++ b/vite.config.mjs
@@ -13,6 +13,9 @@ export default defineConfig({
root: resolve(__dirname, './'),
base: '',
server: {
+ host: true,
+ port: 5173,
+ strictPort: true,
open: false,
watch: {
usePolling: true,