Skip to content

Commit 40a871a

Browse files
committed
chore: Update setup for local development for Deepnote engineers
1 parent a251c6b commit 40a871a

File tree

4 files changed

+81
-114
lines changed

4 files changed

+81
-114
lines changed

CONTRIBUTING.md

Lines changed: 14 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -151,64 +151,23 @@ $ ./bin/test-local
151151

152152
## Development Workflow for Deepnote maintainers
153153

154-
### Using in Deepnote Projects
154+
### Local Toolkit Development with Webapp
155155

156-
When you push a commit, a new version of `deepnote/jupyter-for-local` is built with your commit hash (shortened!). Use it in projects by updating `common.yml`:
156+
To develop toolkit changes against a local webapp with hot-reload:
157157

158-
```yaml
159-
jupyter:
160-
image: "deepnote/jupyter-for-local:SHORTENED_COMMIT_SHA"
161-
```
162-
163-
Alternatively, to develop against a local copy of Deepnote Toolkit, first run this command to build the image:
164-
165-
```bash
166-
docker build \
167-
--build-arg "FROM_PYTHON_TAG=3.11" \
168-
-t deepnote/deepnote-toolkit-local-hotreload \
169-
-f ./dockerfiles/jupyter-for-local-hotreload/Dockerfile .
170-
```
171-
172-
Then start the container:
173-
174-
```bash
175-
# To include server logs in the output add this argument
176-
# -e WITH_SERVER_LOGS=1 \
177-
178-
# Some toolkit features (e.g. feature flags support) require
179-
# DEEPNOTE_PROJECT_ID to be set to work correctly. Add this
180-
# argument with your project id
181-
# -e DEEPNOTE_PROJECT_ID=981af2c1-fe8b-41b7-94bf-006b74cf0641 \
182-
183-
docker run \
184-
-v "$(pwd)":/deepnote-toolkit \
185-
-v /tmp/deepnote-mounts:/deepnote-mounts:shared \
186-
-p 8888:8888 \
187-
-p 2087:2087 \
188-
-p 8051:8051 \
189-
-w /deepnote-toolkit \
190-
--add-host=localstack.dev.deepnote.org:host-gateway \
191-
--rm \
192-
--name deepnote-toolkit-local-hotreload-container \
193-
deepnote/deepnote-toolkit-local-hotreload
194-
```
195-
196-
This will start a container with Deepnote Toolkit mounted inside and expose all required ports. If you change code that runs in the kernel (e.g. you updated the DataFrame formatter), you only need to restart the kernel from Deepnote's UI. If you update code that starts Jupyter itself, you need to restart the container. And if you add or modify dependencies you need to rebuild the image.
197-
198-
Now, you need to modify `common.yml` in the Deepnote app. First, replace `jupyter` service with noop image:
158+
1. Build the local development image:
159+
```bash
160+
docker build -t deepnote/jupyter-for-local:local -f ./dockerfiles/jupyter-for-local-hotreload/Dockerfile .
161+
```
199162

200-
```yml
201-
jupyter:
202-
image: 'screwdrivercd/noop-container'
203-
```
163+
2. Setup `DEEPNOTE_TOOLKIT_SOURCE_PATH` env variable pointing to folder with toolkit source. This can go either in `.zshrc` (or similar file for your shell) or set per shell session with `export DEEPNOTE_TOOLKIT_SOURCE_PATH=...`. If not set, webapp will try to resolve it to `../deepnote-toolkit` relative to webapp root folder.
204164

205-
And change `JUPYTER_HOST` variable of executor to point to host machine:
165+
3. In the webapp repository, run:
166+
```bash
167+
pnpm dev:app:local-toolkit
168+
```
206169

207-
```yml
208-
executor:
209-
environment:
210-
JUPYTER_HOST: host.docker.internal
211-
```
170+
This mounts your toolkit source into the container and installs it in editable mode. Toolkit module code changes are reflected after kernel restart (use "Restart kernel" action in the webapp).
212171

213172
### Review Applications
214173

@@ -229,6 +188,8 @@ We use Docker to ensure reproducible environments due to Jupyter libraries' bina
229188
230189
- `jupyter-for-local.Dockerfile`: Creates development environment with Jupyter integration, used for local development from docker-compose used in main monorepo.
231190
191+
- `jupyter-for-local-hotreload.Dockerfile`: Creates development environment which expectes toolkit source to be mounted at `/toolkit`. Used for development in main monorepo.
192+
232193
### Production Releases
233194
234195
To release a new version to production:
Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,52 @@
1-
ARG FROM_PYTHON_TAG
1+
# Dockerfile for local development with hot-reload support
2+
# This container expects the toolkit source to be mounted at /toolkit
3+
# and installs it in editable mode for live code changes
4+
#
5+
# Build with:
6+
# docker build -t deepnote/jupyter-for-local:local -f dockerfiles/jupyter-for-local-hotreload/Dockerfile .
7+
8+
ARG FROM_PYTHON_TAG=3.12
29
FROM deepnote/python:${FROM_PYTHON_TAG}
310

11+
ARG FROM_PYTHON_TAG
12+
13+
ENV DEBIAN_FRONTEND=noninteractive
14+
15+
# Install system dependencies
416
RUN apt-get update && \
5-
apt-get install -y openjdk-17-jdk && \
17+
apt-get install --no-install-recommends -y \
18+
rsync \
19+
git \
20+
# Required for pymssql
21+
freetds-dev \
22+
# Required for database connectivity through ODBC
23+
unixodbc-dev \
24+
# Required for secure connections (SSL/TLS)
25+
libssl-dev && \
626
apt-get clean && \
727
rm -rf /var/lib/apt/lists/*
828

9-
RUN pip install poetry==2.2.0
29+
# Install Poetry and required plugins
30+
RUN pip install --no-cache-dir poetry==2.2.0 && \
31+
poetry self add 'poetry-dynamic-versioning[plugin]>=1.0.0,<2.0.0'
1032

11-
WORKDIR /deepnote-toolkit
33+
# Configure Poetry to create virtualenv outside the mounted source directory
34+
RUN poetry config virtualenvs.path /opt/venvs
1235

13-
ENV POETRY_NO_INTERACTION=1 \
14-
POETRY_VIRTUALENVS_CREATE=1 \
15-
POETRY_VIRTUALENVS_IN_PROJECT=0 \
16-
POETRY_CACHE_DIR=/tmp/poetry_cache
36+
# Create toolkit directory (will be mounted over, but needed for initial setup)
37+
RUN mkdir -p /toolkit /opt/venvs
1738

18-
COPY pyproject.toml poetry.lock poetry.toml ./
39+
WORKDIR /toolkit
1940

20-
RUN poetry install --no-interaction --no-ansi --with server --with dev
41+
# Environment variables for development mode
42+
ENV DEEPNOTE_RUNNING_IN_DEV_MODE=true \
43+
PYTHONDONTWRITEBYTECODE=1 \
44+
PYTHONUNBUFFERED=1
2145

22-
ENV PYTHONPATH=/deepnote-toolkit:/deepnote-toolkit/installer:$PYTHONPATH \
23-
TOOLKIT_BUNDLE_PATH=/deepnote-toolkit \
24-
TOOLKIT_VERSION="local-build" \
25-
USERNAME=user \
26-
PASSWORD=password \
27-
DEEPNOTE_RUNNING_IN_DEV_MODE=true \
28-
DEEPNOTE_WEBAPP_URL="http://host.docker.internal:3002"
46+
# Copy the entrypoint script
47+
COPY dockerfiles/jupyter-for-local-hotreload/entrypoint.sh /entrypoint.sh
48+
RUN chmod +x /entrypoint.sh
2949

30-
COPY dockerfiles/jupyter-for-local-hotreload/run-installer.sh /usr/local/bin/run-installer.sh
50+
EXPOSE 8888
3151

32-
ENTRYPOINT ["/usr/local/bin/run-installer.sh"]
52+
ENTRYPOINT ["/entrypoint.sh"]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Entrypoint script for local development container
5+
# Installs toolkit in editable mode and starts servers via deepnote-toolkit CLI
6+
7+
echo "[local-toolkit] Starting local development environment..."
8+
9+
# Check if toolkit source is mounted
10+
if [ ! -f "/toolkit/pyproject.toml" ]; then
11+
echo "[local-toolkit] ERROR: Toolkit source not found at /toolkit"
12+
echo "[local-toolkit] Make sure to mount the deepnote-toolkit directory to /toolkit"
13+
exit 1
14+
fi
15+
16+
cd /toolkit
17+
18+
# Mark git directory as safe (needed for poetry-dynamic-versioning)
19+
git config --global --add safe.directory /toolkit
20+
21+
# Install dependencies and toolkit in editable mode
22+
echo "[local-toolkit] Installing toolkit in editable mode..."
23+
poetry install --extras server --no-interaction
24+
25+
echo "[local-toolkit] Starting servers..."
26+
27+
# Start servers using the toolkit CLI (handles Jupyter, LSP, config, etc.)
28+
exec poetry run deepnote-toolkit server "$@"

dockerfiles/jupyter-for-local-hotreload/run-installer.sh

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)