Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .copier-answers.resonant.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
_commit: v0.48.1
_commit: v0.50.2
_src_path: https://github.com/kitware-resonant/cookiecutter-resonant
core_app_name: core
include_example_code: false
Expand Down
83 changes: 83 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose
{
"name": "GeoDatalytics",
"dockerComposeFile": [
"../docker-compose.yml",
"../docker-compose.override.yml",
"./docker-compose.devcontainer.yml"
],
"service": "django",
"overrideCommand": true,
// The "vscode" user and remoteUser are set by the base image label (devcontainers/base).
"workspaceFolder": "/home/vscode/geodatalytics",
"features": {
"ghcr.io/devcontainers/features/node:1": {},
"ghcr.io/rails/devcontainer/features/postgres-client:1": {
"version": 18
},
"ghcr.io/devcontainers/features/terraform:1": {},
"ghcr.io/devcontainers/features/aws-cli:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers-extra/features/heroku-cli:1": {}
},
"customizations": {
"vscode": {
"extensions": [
// Python
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.debugpy",
"ms-python.mypy-type-checker",
"charliermarsh.ruff",
// Django
"batisteo.vscode-django",
"augustocdias.tasks-shell-input",
// Other file formats
"editorconfig.editorconfig",
"mikestead.dotenv",
"tamasfe.even-better-toml",
"timonwong.shellcheck",
// Infrastructure
"ms-azuretools.vscode-containers",
"hashicorp.terraform",
"github.vscode-github-actions",
// Remove AWS extension, as only the CLI is wanted; see: https://github.com/devcontainers/features/issues/1228
"-AmazonWebServices.aws-toolkit-vscode"
],
"settings": {
"containers.containerClient": "com.microsoft.visualstudio.containers.docker",
// Container-specific Python paths
"python.defaultInterpreterPath": "/home/vscode/venv/bin/python",
// Ensure that `envFile` from any user settings is ignored; Docker Compose provides it.
"python.envFile": "",
// Reduce file watcher overhead for generated/cache directories.
"files.watcherExclude": {
"**/__pycache__/**": true,
"**/.pytest_cache/**": true,
"**/node_modules/**": true
}
}
}
},
// Prevent a prompt every time the debugger opens a port or Django auto-restarts.
"otherPortsAttributes": {
"onAutoForward": "silent"
},
"portsAttributes": {
"8000": {
"label": "Django",
// Show a dialog if the port isn't free.
"requireLocalPort": true,
"onAutoForward": "silent"
}
},
// Install a global Python and create a venv before VSCode extensions start,
// to prevent prompts and ensure test discovery works on first load.
"onCreateCommand": {
"python": ["uv", "python", "install", "--default"],
"venv": ["uv", "sync", "--all-extras", "--all-groups"]
},
// Ensure it is re-synced on restarts.
"updateContentCommand": ["uv", "sync", "--all-extras", "--all-groups"]
}
14 changes: 14 additions & 0 deletions .devcontainer/docker-compose.devcontainer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
services:
django:
# Don't expose ports, devcontainer forwarding is superior, since we can just bind to localhost.
ports: !reset []
# Don't auto-run the default command, launch.json or the terminal will be used.
command: !reset []

celery:
# Celery will be started via launch.json or the terminal.
profiles: ["celery"]

web:
# npm will be started via launch.json or the terminal.
profiles: ["web"]
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ permissions:
contents: read
jobs:
lint-client:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: Install npm
Expand All @@ -23,7 +23,7 @@ jobs:
working-directory: web

test-server:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
services:
postgres:
image: postgis/postgis:18-3.6
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/nightly_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ permissions:
contents: read
jobs:
test-server-slow:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
services:
postgres:
image: postgis/postgis:18-3.6
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ permissions:
contents: write
jobs:
version-and-release:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@v6
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Urban areas, particularly those with underserved populations and critical assets

GeoDatalytics is designed to assist urban planners, policymakers, logistics engineers, and infrastructure developers/owners in managing increasingly large, complex, and diverse datasets. By integrating climate data with other critical data types such as infrastructure, sensor, and demographic information using our advanced analytic and visualization tools, users will be empowered to make data-driven decisions.

GeoDatalytics is built with Kitware's [Resonant][girder-4-cookiecutter-link] technology stack. It consists of a series of container services, managed by `docker-compose`. These services include a Django Python server, PostgreSQL/PostGIS database, Minio object store, Vue web application, and Celery task service.
GeoDatalytics is built with Kitware's [Resonant][resonant-cookiecutter-link] technology stack. This stack includes a Django Python server, PostgreSQL/PostGIS database, Minio object store, Vue web application, and Celery task service.

## Getting Started with GeoDatalytics

Expand All @@ -42,4 +42,4 @@ To run GeoDatalytics locally with `docker-compose`, follow the instructions in t
[kitware-link]: https://kitware.com
[sds-lab-link]: https://sdslab.io
[mass-mapper-link]: https://maps.massgis.digital.mass.gov/MassMapper/MassMapper.html
[girder-4-cookiecutter-link]: https://github.com/girder/cookiecutter-girder-4
[resonant-cookiecutter-link]: https://github.com/kitware-resonant/cookiecutter-resonant
46 changes: 33 additions & 13 deletions dev/django.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
FROM ghcr.io/astral-sh/uv:debian

# Make Python more friendly to running in containers
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

# Make uv install content in well-known locations
ENV UV_PROJECT_ENVIRONMENT=/var/lib/venv \
UV_CACHE_DIR=/var/cache/uv/cache \
UV_PYTHON_INSTALL_DIR=/var/cache/uv/bin \
# The uv cache and environment are expected to be mounted on different volumes,
# so hardlinks won't work
UV_LINK_MODE=symlink
FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/

# Ensure Python output appears immediately in container logs.
ENV PYTHONUNBUFFERED=1

# Put the uv and npm caches in a separate location,
# where they can persist and be shared across containers.
# The uv cache and virtual environment are on different volumes, so hardlinks won't work.
ENV UV_CACHE_DIR=/home/vscode/pkg-cache/uv \
UV_PYTHON_INSTALL_DIR=/home/vscode/pkg-cache/uv-python \
UV_LINK_MODE=symlink \
NPM_CONFIG_CACHE=/home/vscode/pkg-cache/npm

# Put the virtual environment outside the project directory,
# to improve performance on macOS and prevent accidental usage from the host machine.
# Activate it, so `uv run` doesn't need to be prefixed.
ENV UV_PROJECT_ENVIRONMENT=/home/vscode/venv \
PATH="/home/vscode/venv/bin:$PATH"

# Put tool scratch files outside the project directory too.
ENV TOX_WORK_DIR=/home/vscode/tox \
RUFF_CACHE_DIR=/home/vscode/.cache/ruff \
MYPY_CACHE_DIR=/home/vscode/.cache/mypy

RUN ["chsh", "-s", "/usr/bin/zsh", "vscode"]

USER vscode

# Pre-create named volume mount points, so the new volume inherits `vscode` user ownership:
# https://docs.docker.com/engine/storage/volumes/#populate-a-volume-using-a-container
RUN ["mkdir", "/home/vscode/pkg-cache"]
23 changes: 23 additions & 0 deletions dev/docker-development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Docker Compose Development (without VS Code)

An alternative to the recommended [dev container](../README.md) workflow.

## Setup
1. `docker compose run --rm django ./manage.py migrate`
1. `docker compose run --rm django ./manage.py createsuperuser`

## Run
1. `docker compose up`
1. Access http://localhost:8000/
1. `Ctrl+C` to stop

To include the Celery worker: `docker compose --profile celery up`

## Update
1. `docker compose down`
1. `docker compose pull`
1. `docker compose build --pull`
1. `docker compose run --rm django ./manage.py migrate`

## Reset
Remove all data and volumes: `docker compose down -v`
2 changes: 2 additions & 0 deletions dev/export-env.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# shellcheck shell=bash
# Export environment variables from the .env file in the first argument.
# If no argument is given, default to "dev/.env.docker-compose-native".
# This file must be sourced, not run.
Expand All @@ -21,6 +22,7 @@ fi
# Using "set -a" allows .env files with spaces or comments to work seamlessly
# https://stackoverflow.com/a/45971167
set -a
# shellcheck source=.env.docker-compose-native
. "$_dotenv_file"
set +a

Expand Down
19 changes: 19 additions & 0 deletions dev/native-development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Native Development (advanced)

Runs Python on the host while using Docker Compose for services.

## Setup
1. [Install `uv`](https://docs.astral.sh/uv/getting-started/installation/)
1. Start services: `docker compose -f ./docker-compose.yml up -d`
1. Load environment: `source ./dev/export-env.sh`
1. `./manage.py migrate`
1. `./manage.py createsuperuser`

## Run
1. Ensure services are running: `docker compose -f ./docker-compose.yml up -d`
1. `source ./dev/export-env.sh`
1. `./manage.py runserver`
1. In a separate terminal: `celery --app uvdat.celery worker --loglevel INFO --without-heartbeat`
1. Access http://localhost:8000/

Stop services when done: `docker compose stop`
26 changes: 12 additions & 14 deletions docker-compose.override.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ services:
]
# Log printing is enhanced by a TTY
tty: true
environment:
UV_ENV_FILE: ./dev/.env.docker-compose
working_dir: /opt/django-project
working_dir: /home/vscode/geodatalytics
env_file: ./dev/.env.docker-compose
volumes:
- .:/opt/django-project
- uv_cache:/var/cache/uv
- .:/home/vscode/geodatalytics
- pkg_cache:/home/vscode/pkg-cache
ports:
- 8000:8000
depends_on:
Expand All @@ -41,14 +40,13 @@ services:
"--loglevel", "INFO",
"--without-heartbeat"
]
# Docker Compose does not set the TTY width, which causes Celery errors
# uv progress doesn't display properly with a Docker TTY
tty: false
environment:
UV_ENV_FILE: ./dev/.env.docker-compose
working_dir: /opt/django-project
working_dir: /home/vscode/geodatalytics
env_file: ./dev/.env.docker-compose
volumes:
- .:/opt/django-project
- uv_cache:/var/cache/uv
- .:/home/vscode/geodatalytics
- pkg_cache:/home/vscode/pkg-cache
depends_on:
postgres:
condition: service_healthy
Expand Down Expand Up @@ -80,8 +78,8 @@ services:
UV_ENV_FILE: ./dev/.env.docker-compose
working_dir: /opt/django-project
volumes:
- .:/opt/django-project
- uv_cache:/var/cache/uv
- .:/home/vscode/geodatalytics
- pkg_cache:/home/vscode/pkg-cache
shm_size: 1gb
profiles: ["gpu"] # Only runs with --profile gpu
deploy:
Expand Down Expand Up @@ -113,5 +111,5 @@ services:
- 8080:8080

volumes:
uv_cache:
pkg_cache:
web_node_modules:
Loading