From 3d2e247e3908be82849a3494112c9d3f98ecf87d Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Fri, 24 Oct 2025 16:39:18 -0700 Subject: [PATCH 01/14] first pass at docker setup --- TEKDB/.dockerignore | 38 ++++++++++++++++++++++++ TEKDB/Dockerfile | 58 ++++++++++++++++++++++++++++++++++++ TEKDB/docker-compose.yml | 61 ++++++++++++++++++++++---------------- TEKDB/docker/entrypoint.sh | 27 ++++++++++++++--- 4 files changed, 154 insertions(+), 30 deletions(-) create mode 100644 TEKDB/.dockerignore create mode 100644 TEKDB/Dockerfile diff --git a/TEKDB/.dockerignore b/TEKDB/.dockerignore new file mode 100644 index 00000000..1abb6152 --- /dev/null +++ b/TEKDB/.dockerignore @@ -0,0 +1,38 @@ +# Python +__pycache__/ +*.py[cod] +*.pyo +*.pyd + +# Virtual environments +env/ +venv/ +.venv/ + +# Editor & OS files +.DS_Store +.vscode/ +.idea/ + +# Git +.git +.gitignore + +# Build/dist +build/ +dist/ +*.egg-info + +# Static/local settings +media/ +static/ +local_settings.py +*.sqlite3 +*.log + +# Node +node_modules/ + +# Docker +Dockerfile +docker-compose*.yml diff --git a/TEKDB/Dockerfile b/TEKDB/Dockerfile new file mode 100644 index 00000000..612f7114 --- /dev/null +++ b/TEKDB/Dockerfile @@ -0,0 +1,58 @@ +FROM python:3.11-slim + +# Prevent Python from writing .pyc files and enable unbuffered stdout/stderr +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV PIP_NO_CACHE_DIR=1 + +# Install system dependencies +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + postgresql-client \ + postgresql-client-common \ + libpq-dev \ + postgresql \ + postgresql-contrib \ + build-essential \ + gcc \ + g++ \ + python3-dev \ + gdal-bin \ + libgdal-dev \ + libgeos-dev \ + proj-bin \ + libproj-dev \ + libjpeg-dev \ + zlib1g-dev \ + libfreetype6-dev \ + libwebp-dev \ + gettext \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# Set working directory +WORKDIR /usr/src/app + +# Copy requirements first (cache pip install step when dependencies don't change) +COPY requirements.txt /usr/src/app/ +COPY requirements.txt requirements_linux.txt /usr/src/app/ + +# Upgrade pip and install Python dependencies +RUN pip install --upgrade pip setuptools wheel \ + && pip install -r requirements.txt -r requirements_linux.txt || pip install -r requirements.txt + +# Copy the rest of the application code +COPY . /usr/src/app + +# Copy and make entrypoint executable. The repository contains `docker/entrypoint.sh` +# which runs collectstatic, migrations and launches uWSGI. +COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Expose the port the app runs on (entrypoint starts uWSGI on 8000) +EXPOSE 8000 + +# Default settings module (can be overridden at runtime) +ENV DJANGO_SETTINGS_MODULE=TEKDB.settings + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/TEKDB/docker-compose.yml b/TEKDB/docker-compose.yml index 9b514d90..4aa73e61 100644 --- a/TEKDB/docker-compose.yml +++ b/TEKDB/docker-compose.yml @@ -1,35 +1,44 @@ -version: '3.7' - services: - app: - build: /usr/local/apps/TEKDB/TEKDB - command: dockerize -wait tcp://db:5432 sh -c "python manage.py runserver 0.0.0.0:8000" + db: + image: postgis/postgis:15-3.4 + restart: always + environment: + POSTGRES_DB: tekdb + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgrespw + POSTGRES_HOST_AUTH_METHOD: trust volumes: - - ./:/usr/local/apps/TEKDB/TEKDB/ - - media_volume:/vol/web/media - - static_volume:/vol/web/static + - tekdb_db_data:/var/lib/postgresql/data ports: - - "8000:8000" - env_file: - - ./.env.dev - links: - - db + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d tekdb -h localhost -p 5432"] + interval: 10s + timeout: 5s + retries: 5 + + web: + build: + context: . + dockerfile: Dockerfile + restart: unless-stopped depends_on: - db + env_file: + - .env.dev environment: - - DEBUG=1 - db: - image: postgis/postgis:14-3.1-alpine - volumes: - - postgis-data:/var/lib/postgresql - environment: - - POSTGRES_USER=tekdb_user - - POSTGRES_PASSWORD=tekdb_password - - POSTGRES_DB=tekdb + SQL_ENGINE: django.contrib.gis.db.backends.postgis + SQL_HOST: db + SQL_PORT: 5432 + SQL_DATABASE: tekdb + SQL_USER: postgres + SQL_PASSWORD: postgrespw + SECRET_KEY: 'change-me' + DEBUG: '0' ports: - - 5432:5432 + - "8000:8000" + volumes: + - .:/usr/src/app volumes: - postgis-data: - static_volume: - media_volume: + tekdb_db_data: diff --git a/TEKDB/docker/entrypoint.sh b/TEKDB/docker/entrypoint.sh index b2eb0867..31d3fe30 100644 --- a/TEKDB/docker/entrypoint.sh +++ b/TEKDB/docker/entrypoint.sh @@ -1,8 +1,27 @@ #!/bin/sh -#set -e +# Exit on errors +set -e + +# If a SQL_HOST is provided, wait for Postgres to become available before running +# migrations. This prevents race conditions when using docker-compose where the +# web container starts before the DB is ready. +if [ -n "$SQL_HOST" ]; then + echo "Waiting for database at ${SQL_HOST}:${SQL_PORT:-5432}..." + # pg_isready is available after installing postgresql-client in the image + until pg_isready -h "$SQL_HOST" -p "${SQL_PORT:-5432}" >/dev/null 2>&1; do + echo "Postgres is unavailable - sleeping" + sleep 1 + done + echo "Postgres is up" +fi + python manage.py collectstatic --noinput python manage.py migrate --noinput -#python manage.py loaddata /usr/local/apps/TEKDB/TEKDB/TEKDB/fixtures/all_dummy_data.json -uwsgi --socket :8000 --master --enable-threads --module TEKDB.wsgi -#exec "$@" +# python manage.py loaddata /usr/local/apps/TEKDB/TEKDB/TEKDB/fixtures/all_dummy_data.json +echo "Starting uWSGI (HTTP) on :8000" +# Use HTTP socket so direct HTTP clients (browsers) can connect to the container port. +# If you proxy with nginx using the uwsgi protocol, switch back to --socket and use +# uwsgi_pass in nginx configuration. +uwsgi --http :8000 --master --enable-threads --module TEKDB.wsgi +exec "$@" From a80270899be6b1c6694f5b481143c8b1a19eee7f Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Fri, 24 Oct 2025 17:22:14 -0700 Subject: [PATCH 02/14] run loaddata in entrypoint --- TEKDB/docker/entrypoint.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/TEKDB/docker/entrypoint.sh b/TEKDB/docker/entrypoint.sh index 31d3fe30..718059d9 100644 --- a/TEKDB/docker/entrypoint.sh +++ b/TEKDB/docker/entrypoint.sh @@ -18,7 +18,8 @@ fi python manage.py collectstatic --noinput python manage.py migrate --noinput -# python manage.py loaddata /usr/local/apps/TEKDB/TEKDB/TEKDB/fixtures/all_dummy_data.json +python manage.py loaddata TEKDB/fixtures/default_users_fixture.json +python manage.py loaddata TEKDB/fixtures/default_lookups_fixture.json echo "Starting uWSGI (HTTP) on :8000" # Use HTTP socket so direct HTTP clients (browsers) can connect to the container port. # If you proxy with nginx using the uwsgi protocol, switch back to --socket and use From d2f355089b60cab7e98340540522e786047c72e1 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Thu, 30 Oct 2025 12:54:34 -0700 Subject: [PATCH 03/14] add whitenoise for static file loading --- TEKDB/Dockerfile | 2 +- TEKDB/TEKDB/settings.py | 7 +++++++ TEKDB/docker/entrypoint.sh | 5 +++-- TEKDB/requirements.txt | 3 +++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/TEKDB/Dockerfile b/TEKDB/Dockerfile index 612f7114..5125cd22 100644 --- a/TEKDB/Dockerfile +++ b/TEKDB/Dockerfile @@ -38,7 +38,7 @@ COPY requirements.txt /usr/src/app/ COPY requirements.txt requirements_linux.txt /usr/src/app/ # Upgrade pip and install Python dependencies -RUN pip install --upgrade pip setuptools wheel \ +RUN pip install --upgrade pip \ && pip install -r requirements.txt -r requirements_linux.txt || pip install -r requirements.txt # Copy the rest of the application code diff --git a/TEKDB/TEKDB/settings.py b/TEKDB/TEKDB/settings.py index eb17fe5f..f76d5299 100644 --- a/TEKDB/TEKDB/settings.py +++ b/TEKDB/TEKDB/settings.py @@ -74,6 +74,7 @@ MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', + 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', @@ -180,6 +181,12 @@ STATIC_ROOT = os.path.join(BASE_DIR, "static") +# Use WhiteNoise to serve static files when DEBUG is False (container / production) +STATICFILES_STORAGE = os.environ.get( + 'STATICFILES_STORAGE', + 'whitenoise.storage.CompressedStaticFilesStorage' +) + # STATICFILES_DIRS = [ # os.path.join(BASE_DIR, "explore", "static"), # os.path.join(BASE_DIR, "TEKDB", "static"), diff --git a/TEKDB/docker/entrypoint.sh b/TEKDB/docker/entrypoint.sh index 718059d9..fb7d99bb 100644 --- a/TEKDB/docker/entrypoint.sh +++ b/TEKDB/docker/entrypoint.sh @@ -18,8 +18,9 @@ fi python manage.py collectstatic --noinput python manage.py migrate --noinput -python manage.py loaddata TEKDB/fixtures/default_users_fixture.json -python manage.py loaddata TEKDB/fixtures/default_lookups_fixture.json +# initial data load - commented out after first run to avoid duplicates +# python manage.py loaddata TEKDB/fixtures/default_users_fixture.json +# python manage.py loaddata TEKDB/fixtures/default_lookups_fixture.json echo "Starting uWSGI (HTTP) on :8000" # Use HTTP socket so direct HTTP clients (browsers) can connect to the container port. # If you proxy with nginx using the uwsgi protocol, switch back to --socket and use diff --git a/TEKDB/requirements.txt b/TEKDB/requirements.txt index de1b8369..c2e1c9d5 100644 --- a/TEKDB/requirements.txt +++ b/TEKDB/requirements.txt @@ -29,3 +29,6 @@ urllib3>=1.26.5 #OPTIONAL, BUT LOVELY FOR DEBUGGING ipdb ipython + +# Serve static files in production containers +whitenoise From c0f2143d57a1c9c877e807ea3a85c12fba7c99cd Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Fri, 5 Dec 2025 14:47:55 -0800 Subject: [PATCH 04/14] remove postgresql from web dockerfile load fixtures if empty --- TEKDB/Dockerfile | 3 --- TEKDB/docker-compose.yml | 2 +- TEKDB/docker/entrypoint.sh | 16 +++++++++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/TEKDB/Dockerfile b/TEKDB/Dockerfile index 5125cd22..98149ddf 100644 --- a/TEKDB/Dockerfile +++ b/TEKDB/Dockerfile @@ -11,8 +11,6 @@ RUN apt-get update \ postgresql-client \ postgresql-client-common \ libpq-dev \ - postgresql \ - postgresql-contrib \ build-essential \ gcc \ g++ \ @@ -34,7 +32,6 @@ RUN apt-get update \ WORKDIR /usr/src/app # Copy requirements first (cache pip install step when dependencies don't change) -COPY requirements.txt /usr/src/app/ COPY requirements.txt requirements_linux.txt /usr/src/app/ # Upgrade pip and install Python dependencies diff --git a/TEKDB/docker-compose.yml b/TEKDB/docker-compose.yml index 4aa73e61..c175d53e 100644 --- a/TEKDB/docker-compose.yml +++ b/TEKDB/docker-compose.yml @@ -34,7 +34,7 @@ services: SQL_USER: postgres SQL_PASSWORD: postgrespw SECRET_KEY: 'change-me' - DEBUG: '0' + DEBUG: '1' ports: - "8000:8000" volumes: diff --git a/TEKDB/docker/entrypoint.sh b/TEKDB/docker/entrypoint.sh index fb7d99bb..29eabbb8 100644 --- a/TEKDB/docker/entrypoint.sh +++ b/TEKDB/docker/entrypoint.sh @@ -18,12 +18,18 @@ fi python manage.py collectstatic --noinput python manage.py migrate --noinput -# initial data load - commented out after first run to avoid duplicates -# python manage.py loaddata TEKDB/fixtures/default_users_fixture.json -# python manage.py loaddata TEKDB/fixtures/default_lookups_fixture.json +# Load default users only if no users exist +echo "Checking for existing users..." +if [ "$(python manage.py shell -c 'from django.contrib.auth import get_user_model; print(get_user_model().objects.count())')" = "0" ]; then + python manage.py loaddata TEKDB/fixtures/default_users_fixture.json +fi +# Load default lookups only if no lookups exist. Use LookupPlanningUnit as the check. +echo "Checking for existing lookups..." +if [ "$(python manage.py shell -c 'from TEKDB.models import LookupPlanningUnit; print(LookupPlanningUnit.objects.count())')" = "0" ]; then + python manage.py loaddata TEKDB/fixtures/default_lookups_fixture.json +fi echo "Starting uWSGI (HTTP) on :8000" # Use HTTP socket so direct HTTP clients (browsers) can connect to the container port. # If you proxy with nginx using the uwsgi protocol, switch back to --socket and use # uwsgi_pass in nginx configuration. -uwsgi --http :8000 --master --enable-threads --module TEKDB.wsgi -exec "$@" +uwsgi --http :8000 --master --enable-threads --module TEKDB.wsgi \ No newline at end of file From 5b31f6ca275064a0f88f2b04c401f586ae10bdf3 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 9 Dec 2025 12:59:40 -0800 Subject: [PATCH 05/14] remove unnecessary installs --- TEKDB/Dockerfile | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/TEKDB/Dockerfile b/TEKDB/Dockerfile index 98149ddf..d6ac0f7a 100644 --- a/TEKDB/Dockerfile +++ b/TEKDB/Dockerfile @@ -9,23 +9,10 @@ ENV PIP_NO_CACHE_DIR=1 RUN apt-get update \ && apt-get install -y --no-install-recommends \ postgresql-client \ - postgresql-client-common \ - libpq-dev \ - build-essential \ gcc \ - g++ \ - python3-dev \ gdal-bin \ libgdal-dev \ libgeos-dev \ - proj-bin \ - libproj-dev \ - libjpeg-dev \ - zlib1g-dev \ - libfreetype6-dev \ - libwebp-dev \ - gettext \ - curl \ && rm -rf /var/lib/apt/lists/* # Set working directory From d22dc0c148d661040f2099488e717a4244741811 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 9 Dec 2025 14:00:07 -0800 Subject: [PATCH 06/14] remove to enforce password auth --- TEKDB/docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/TEKDB/docker-compose.yml b/TEKDB/docker-compose.yml index c175d53e..5683c5db 100644 --- a/TEKDB/docker-compose.yml +++ b/TEKDB/docker-compose.yml @@ -6,7 +6,6 @@ services: POSTGRES_DB: tekdb POSTGRES_USER: postgres POSTGRES_PASSWORD: postgrespw - POSTGRES_HOST_AUTH_METHOD: trust volumes: - tekdb_db_data:/var/lib/postgresql/data ports: From 0463e136d432b14b5e70fc5abf50258d86dcbc06 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 9 Dec 2025 14:16:07 -0800 Subject: [PATCH 07/14] remove unused docker related files --- TEKDB/Dockerfile | 4 +- docker/linux/docker-compose.yml | 60 --------------- docker/windows/.env | 126 -------------------------------- 3 files changed, 2 insertions(+), 188 deletions(-) delete mode 100644 docker/linux/docker-compose.yml delete mode 100644 docker/windows/.env diff --git a/TEKDB/Dockerfile b/TEKDB/Dockerfile index d6ac0f7a..8c4072f8 100644 --- a/TEKDB/Dockerfile +++ b/TEKDB/Dockerfile @@ -23,9 +23,9 @@ COPY requirements.txt requirements_linux.txt /usr/src/app/ # Upgrade pip and install Python dependencies RUN pip install --upgrade pip \ - && pip install -r requirements.txt -r requirements_linux.txt || pip install -r requirements.txt + && pip install -r requirements.txt -r requirements_linux.txt -# Copy the rest of the application code +# Copy the application code COPY . /usr/src/app # Copy and make entrypoint executable. The repository contains `docker/entrypoint.sh` diff --git a/docker/linux/docker-compose.yml b/docker/linux/docker-compose.yml deleted file mode 100644 index 109b84fe..00000000 --- a/docker/linux/docker-compose.yml +++ /dev/null @@ -1,60 +0,0 @@ -version: '3.7' - -services: - app: - build: - context: ../../TEKDB - # command: dockerize -wait tcp://db:5432 sh -c "python manage.py migrate --noinput" - # command: dockerize -wait tcp://db:5432 sh -c "python manage.py loaddata /usr/local/apps/TEKDB/TEKDB/TEKDB/fixtures/all_dummy_data.json" - volumes: - - static_data:/vol/web - environment: - - SECRET_KEY=${SECRET_KEY} - - ALLOWED_HOSTS=${ALLOWED_HOSTS} - - SQL_ENGINE=${SQL_ENGINE} - - SQL_DATABASE=${SQL_DATABASE} - - SQL_USER=${SQL_USER} - - SQL_PASSWORD=${SQL_PASSWORD} - - SQL_HOST=${SQL_HOST} - - SQL_PORT=${SQL_PORT} - depends_on: - - ${SQL_HOST} - links: - - ${SQL_HOST} - networks: - - djangonetwork - - proxy: - build: - context: ../../proxy - volumes: - - static_data:/vol/static - # - media_data:/vol/media - ports: - - "${PROXY_PORT}:8080" - depends_on: - - app - networks: - - djangonetwork - - db: - image: postgis/postgis:14-3.1-alpine - volumes: - - postgis-data:/var/lib/postgresql - environment: - - POSTGRES_USER=${SQL_USER} - - POSTGRES_PASSWORD=${SQL_PASSWORD} - - POSTGRES_DB=${SQL_DATABASE} - ports: - - ${SQL_PORT}:5432 - networks: - - djangonetwork - -volumes: - postgis-data: - static_data: - # media_data: - -networks: - djangonetwork: - driver: bridge diff --git a/docker/windows/.env b/docker/windows/.env deleted file mode 100644 index 8fa814aa..00000000 --- a/docker/windows/.env +++ /dev/null @@ -1,126 +0,0 @@ -##################### -# REQUIRED SETTINGS # -##################### - -# These settings must absolutely be changed for any production deployment. -# Most of these are critical to the security of your database application. -# Many of these settings should be changed even for development environments. - -## SECRET_KEY: -## Used to secure the app. Can be anything -- feel free to hammer out -## a long line of numbers, letters, caps, and symbols. You will not need -## to remember or retype this ever. -SECRET_KEY=changeme - -## PROXY_PORT: -## The port the proxy server (NGINX) will serve the application on. Use 80 in -## production for HTTP or 443 for HTTPS. For dev you may prefer 80xx. -PROXY_PORT=8000 - -## ALLOWED_HOSTS: -## List of web addresses server will accept traffic from. This can be an -## IP address (127.0.0.1) or a URL (your.site.com). Separate addresses with a -## comma (no spaces). Leave the current default addresses in place unless -## you know what you're doing. -ALLOWED_HOSTS=localhost,127.0.0.1,[::1] - -## SQL_DATABASE: -## The name of your database. This can be any word (no spaces). You can leave -## the default in place, but you will get extra security by making it unique. -SQL_DATABASE=itkdb - -## SQL_USER: -## A username for the owner of your database. Can be any word (no spaces). -## It is recommended that you change this for security purposes -SQL_USER=itkdb_user - -## SQL_PASSWORD: -## A password for your database user. Can be any word (no spaces). You -## absolutely MUST change this password before you put any sensitive -## information in your database -SQL_PASSWORD=tekdb_password - -## DEFAULT_LON, DEFAULT_LAT: -## The longitudinal (LON) and latitudinal (LAT) coordinate of the geographic -## center of your region of interest. -## Unfortunately it must also be expressed in Web Mercator -## (EPSG:3857) coordinate projection. If you know your coordinates in the -## most common form (EPSG:4326 WGS 84, will look something like -## "-120.123, 40.123") you can make the conversion at this site: -## https://epsg.io/transform#s_srs=4326&t_srs=3857 -DEFAULT_LON=-13839795.69 -DEFAULT_LAT=5171448.926 - -## DEFAULT_ZOOM: -## A numeric representation for the default map scale provided when your -## region of interest is presented on a map. Here is a rough outline of -## what scale the numbers show: -## - 0: the whole world -## - 3: The U.S.A. or a small continent -## - 6: A medium-large U.S. state -## - 10: A county -## - 12: A forest -DEFAULT_ZOOM=8 - -################### -# SERVER SETTINGS # -################### - -# These are settings that may impact how the application is served. These should -# only be important for development or highly-customized deployments. - -## DEBUG: -## Set to 1 for 'true' if you are actively modifying the code base -## Leave as 0 for 'false' (default) for running in production -DEBUG=0 - -## ADMIN_SITE_HEADER: -## The title of the application shown at the top of the Admin Data-Entry -## pages. -ADMIN_SITE_HEADER=ITK DB Admin - -## TIME_ZONE: -## To see all Timezone options, see -## https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List -TIME_ZONE=America/Los_Angeles - -##################### -# DATABASE SETTINGS # -##################### - -# These are the default settings for connecting the application to the -# database. They most likely should not be changed, and only then in -# experimental development of highly-customized deployments. The descriptions -# will assume a high-familiarity with the subject matter, particularly of -# Django, RDBMSs, networking, and Docker. - -## SQL_ENGINE: -## The django database backend to use to connect to the database. -SQL_ENGINE=django.contrib.gis.db.backends.postgis - -## SQL_HOST: -## The network address of the database. The default 'db' is the variable name -## assigned and recognized by Docker from your docker-compose.yml file. -SQL_HOST=db - -## SQL_PORT: -## The port your database is accepting connections on. Default for PostgreSQL -## is 5432. -SQL_PORT=5432 - -################ -# MAP SETTINGS # -################ - -# These allow for additional customization of map behavior. - -## MAP_EXTENT_[WEST/SOUTH/EAST/NORTH]: -## These 4 settings set the extent to which the web map can be moved. They are -## coordinates expressed in the projection EPSG:3857 (Web Mercator). -## These values do not represent the extent of your region of interest -- -## they should be far greater. By default it is set large enough to cover all -## current US landmasses, including territories. -MAP_EXTENT_WEST=-24000000 -MAP_EXTENT_SOUTH=1450000 -MAP_EXTENT_EAST=-6200000 -MAP_EXTENT_NORTH=13000000 From 8244f525ba4a9d05e9429c000ad4dae519b90478 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 9 Dec 2025 14:54:40 -0800 Subject: [PATCH 08/14] use env vars in docker-compose.yaml --- TEKDB/.env.dev | 2 +- TEKDB/docker-compose.yml | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/TEKDB/.env.dev b/TEKDB/.env.dev index 4073116c..e145b076 100644 --- a/TEKDB/.env.dev +++ b/TEKDB/.env.dev @@ -3,7 +3,7 @@ SECRET_KEY=foo ALLOWED_HOSTS=localhost,127.0.0.1,[::1] SQL_ENGINE=django.contrib.gis.db.backends.postgis SQL_DATABASE=tekdb -SQL_USER=tekdb_user +SQL_USER=postgres SQL_PASSWORD=tekdb_password SQL_HOST=db SQL_PORT=5432 diff --git a/TEKDB/docker-compose.yml b/TEKDB/docker-compose.yml index 5683c5db..513d8e84 100644 --- a/TEKDB/docker-compose.yml +++ b/TEKDB/docker-compose.yml @@ -2,16 +2,17 @@ services: db: image: postgis/postgis:15-3.4 restart: always + platform: linux/amd64 environment: - POSTGRES_DB: tekdb - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgrespw + POSTGRES_DB: ${SQL_DATABASE} + POSTGRES_USER: ${SQL_USER} + POSTGRES_PASSWORD: ${SQL_PASSWORD} volumes: - tekdb_db_data:/var/lib/postgresql/data ports: - "5432:5432" healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres -d tekdb -h localhost -p 5432"] + test: ["CMD-SHELL", "pg_isready -U ${SQL_USER} -d ${SQL_DATABASE} -h localhost -p ${SQL_PORT}"] interval: 10s timeout: 5s retries: 5 @@ -26,14 +27,15 @@ services: env_file: - .env.dev environment: - SQL_ENGINE: django.contrib.gis.db.backends.postgis - SQL_HOST: db - SQL_PORT: 5432 - SQL_DATABASE: tekdb - SQL_USER: postgres - SQL_PASSWORD: postgrespw - SECRET_KEY: 'change-me' - DEBUG: '1' + ALLOWED_HOSTS: ${ALLOWED_HOSTS} + DEBUG: ${DEBUG} + SQL_ENGINE: ${SQL_ENGINE} + SQL_HOST: ${SQL_HOST} + SQL_PORT: ${SQL_PORT} + SQL_DATABASE: ${SQL_DATABASE} + SQL_USER: ${SQL_USER} + SQL_PASSWORD: ${SQL_PASSWORD} + SECRET_KEY: ${SECRET_KEY} ports: - "8000:8000" volumes: From d89604868f1fb858997e10cfddccc6e66d03b5f1 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 9 Dec 2025 15:18:53 -0800 Subject: [PATCH 09/14] pin whitenoise version --- TEKDB/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TEKDB/requirements.txt b/TEKDB/requirements.txt index 6e1d8b08..276851e8 100644 --- a/TEKDB/requirements.txt +++ b/TEKDB/requirements.txt @@ -33,6 +33,6 @@ ipdb ipython # Serve static files in production containers -whitenoise +whitenoise>=6.0.0,<7.0.0 # FORMATTING AND LINTING ruff From c4679e64d16d5369af6bf8495612d571f9b6d472 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 9 Dec 2025 16:03:52 -0800 Subject: [PATCH 10/14] ruff format --- TEKDB/TEKDB/settings.py | 19 +++++++++---------- .../explore/templatetags/disk_space_report.py | 1 + 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/TEKDB/TEKDB/settings.py b/TEKDB/TEKDB/settings.py index 91cba9b6..f6f4e8c0 100644 --- a/TEKDB/TEKDB/settings.py +++ b/TEKDB/TEKDB/settings.py @@ -74,14 +74,14 @@ ] MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'whitenoise.middleware.WhiteNoiseMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.middleware.security.SecurityMiddleware", + "whitenoise.middleware.WhiteNoiseMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", ] ROOT_URLCONF = "TEKDB.urls" @@ -186,8 +186,7 @@ # Use WhiteNoise to serve static files when DEBUG is False (container / production) STATICFILES_STORAGE = os.environ.get( - 'STATICFILES_STORAGE', - 'whitenoise.storage.CompressedStaticFilesStorage' + "STATICFILES_STORAGE", "whitenoise.storage.CompressedStaticFilesStorage" ) ########################################### ## FILEBROWSER ### diff --git a/TEKDB/explore/templatetags/disk_space_report.py b/TEKDB/explore/templatetags/disk_space_report.py index 96136c07..ff03f6e7 100644 --- a/TEKDB/explore/templatetags/disk_space_report.py +++ b/TEKDB/explore/templatetags/disk_space_report.py @@ -12,6 +12,7 @@ def bytes_to_readable(num_bytes, suffix="B"): return f"{num_bytes:.2f} {unit}{suffix}" num_bytes /= 1024 + @register.simple_tag(name="disk_space_report") def disk_space_report(): """Returns a dictionary with disk space and memory usage information.""" From 75b42b27d60117f5347920d0523c72c0a6c4c3cc Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Wed, 10 Dec 2025 10:44:40 -0800 Subject: [PATCH 11/14] wip: organize docker directory --- TEKDB/Dockerfile | 2 +- TEKDB/docker/local_settings.py | 17 ---- TEKDB/{docker => }/entrypoint.sh | 0 docker/.env.dev | 9 ++ {TEKDB => docker}/docker-compose.yml | 4 +- docker/linux/.env | 126 --------------------------- docker/linux/Dockerfile | 44 ---------- 7 files changed, 12 insertions(+), 190 deletions(-) delete mode 100644 TEKDB/docker/local_settings.py rename TEKDB/{docker => }/entrypoint.sh (100%) create mode 100644 docker/.env.dev rename {TEKDB => docker}/docker-compose.yml (93%) delete mode 100644 docker/linux/.env delete mode 100644 docker/linux/Dockerfile diff --git a/TEKDB/Dockerfile b/TEKDB/Dockerfile index 8c4072f8..f224a702 100644 --- a/TEKDB/Dockerfile +++ b/TEKDB/Dockerfile @@ -30,7 +30,7 @@ COPY . /usr/src/app # Copy and make entrypoint executable. The repository contains `docker/entrypoint.sh` # which runs collectstatic, migrations and launches uWSGI. -COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh +COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh # Expose the port the app runs on (entrypoint starts uWSGI on 8000) diff --git a/TEKDB/docker/local_settings.py b/TEKDB/docker/local_settings.py deleted file mode 100644 index 0056ff9f..00000000 --- a/TEKDB/docker/local_settings.py +++ /dev/null @@ -1,17 +0,0 @@ -TIME_ZONE = 'America/Los_Angeles' # To see all Timezone options, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List -REGISTRATION_OPEN = False -DATABASE_GEOGRAPHY = { - ###EPSG:4326### - # 'default_lon': -124.325, - # 'default_lat': 42.065, - ###EPSG:3857### - 'default_lon': -13839795.69, - 'default_lat': 5171448.926, - 'default_zoom': 8, - 'map_template': 'gis/admin/ol2osm.html', - 'map_extent': [-24000000, 1450000, -6200000, 13000000], #US Territories - 'min_zoom': 2, - 'max_zoom': 19, -} -STATIC_ROOT = '/vol/web/static' -MEDIA_ROOT = '/vol/web/media' diff --git a/TEKDB/docker/entrypoint.sh b/TEKDB/entrypoint.sh similarity index 100% rename from TEKDB/docker/entrypoint.sh rename to TEKDB/entrypoint.sh diff --git a/docker/.env.dev b/docker/.env.dev new file mode 100644 index 00000000..e145b076 --- /dev/null +++ b/docker/.env.dev @@ -0,0 +1,9 @@ +DEBUG=1 +SECRET_KEY=foo +ALLOWED_HOSTS=localhost,127.0.0.1,[::1] +SQL_ENGINE=django.contrib.gis.db.backends.postgis +SQL_DATABASE=tekdb +SQL_USER=postgres +SQL_PASSWORD=tekdb_password +SQL_HOST=db +SQL_PORT=5432 diff --git a/TEKDB/docker-compose.yml b/docker/docker-compose.yml similarity index 93% rename from TEKDB/docker-compose.yml rename to docker/docker-compose.yml index 513d8e84..a11ce15b 100644 --- a/TEKDB/docker-compose.yml +++ b/docker/docker-compose.yml @@ -19,8 +19,8 @@ services: web: build: - context: . - dockerfile: Dockerfile + context: ../TEKDB/ + dockerfile: ../TEKDB/Dockerfile restart: unless-stopped depends_on: - db diff --git a/docker/linux/.env b/docker/linux/.env deleted file mode 100644 index 8fa814aa..00000000 --- a/docker/linux/.env +++ /dev/null @@ -1,126 +0,0 @@ -##################### -# REQUIRED SETTINGS # -##################### - -# These settings must absolutely be changed for any production deployment. -# Most of these are critical to the security of your database application. -# Many of these settings should be changed even for development environments. - -## SECRET_KEY: -## Used to secure the app. Can be anything -- feel free to hammer out -## a long line of numbers, letters, caps, and symbols. You will not need -## to remember or retype this ever. -SECRET_KEY=changeme - -## PROXY_PORT: -## The port the proxy server (NGINX) will serve the application on. Use 80 in -## production for HTTP or 443 for HTTPS. For dev you may prefer 80xx. -PROXY_PORT=8000 - -## ALLOWED_HOSTS: -## List of web addresses server will accept traffic from. This can be an -## IP address (127.0.0.1) or a URL (your.site.com). Separate addresses with a -## comma (no spaces). Leave the current default addresses in place unless -## you know what you're doing. -ALLOWED_HOSTS=localhost,127.0.0.1,[::1] - -## SQL_DATABASE: -## The name of your database. This can be any word (no spaces). You can leave -## the default in place, but you will get extra security by making it unique. -SQL_DATABASE=itkdb - -## SQL_USER: -## A username for the owner of your database. Can be any word (no spaces). -## It is recommended that you change this for security purposes -SQL_USER=itkdb_user - -## SQL_PASSWORD: -## A password for your database user. Can be any word (no spaces). You -## absolutely MUST change this password before you put any sensitive -## information in your database -SQL_PASSWORD=tekdb_password - -## DEFAULT_LON, DEFAULT_LAT: -## The longitudinal (LON) and latitudinal (LAT) coordinate of the geographic -## center of your region of interest. -## Unfortunately it must also be expressed in Web Mercator -## (EPSG:3857) coordinate projection. If you know your coordinates in the -## most common form (EPSG:4326 WGS 84, will look something like -## "-120.123, 40.123") you can make the conversion at this site: -## https://epsg.io/transform#s_srs=4326&t_srs=3857 -DEFAULT_LON=-13839795.69 -DEFAULT_LAT=5171448.926 - -## DEFAULT_ZOOM: -## A numeric representation for the default map scale provided when your -## region of interest is presented on a map. Here is a rough outline of -## what scale the numbers show: -## - 0: the whole world -## - 3: The U.S.A. or a small continent -## - 6: A medium-large U.S. state -## - 10: A county -## - 12: A forest -DEFAULT_ZOOM=8 - -################### -# SERVER SETTINGS # -################### - -# These are settings that may impact how the application is served. These should -# only be important for development or highly-customized deployments. - -## DEBUG: -## Set to 1 for 'true' if you are actively modifying the code base -## Leave as 0 for 'false' (default) for running in production -DEBUG=0 - -## ADMIN_SITE_HEADER: -## The title of the application shown at the top of the Admin Data-Entry -## pages. -ADMIN_SITE_HEADER=ITK DB Admin - -## TIME_ZONE: -## To see all Timezone options, see -## https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List -TIME_ZONE=America/Los_Angeles - -##################### -# DATABASE SETTINGS # -##################### - -# These are the default settings for connecting the application to the -# database. They most likely should not be changed, and only then in -# experimental development of highly-customized deployments. The descriptions -# will assume a high-familiarity with the subject matter, particularly of -# Django, RDBMSs, networking, and Docker. - -## SQL_ENGINE: -## The django database backend to use to connect to the database. -SQL_ENGINE=django.contrib.gis.db.backends.postgis - -## SQL_HOST: -## The network address of the database. The default 'db' is the variable name -## assigned and recognized by Docker from your docker-compose.yml file. -SQL_HOST=db - -## SQL_PORT: -## The port your database is accepting connections on. Default for PostgreSQL -## is 5432. -SQL_PORT=5432 - -################ -# MAP SETTINGS # -################ - -# These allow for additional customization of map behavior. - -## MAP_EXTENT_[WEST/SOUTH/EAST/NORTH]: -## These 4 settings set the extent to which the web map can be moved. They are -## coordinates expressed in the projection EPSG:3857 (Web Mercator). -## These values do not represent the extent of your region of interest -- -## they should be far greater. By default it is set large enough to cover all -## current US landmasses, including territories. -MAP_EXTENT_WEST=-24000000 -MAP_EXTENT_SOUTH=1450000 -MAP_EXTENT_EAST=-6200000 -MAP_EXTENT_NORTH=13000000 diff --git a/docker/linux/Dockerfile b/docker/linux/Dockerfile deleted file mode 100644 index 271f67b9..00000000 --- a/docker/linux/Dockerfile +++ /dev/null @@ -1,44 +0,0 @@ -# pull official base image -#FROM python:3.9.6-alpine -FROM python:3.8.10-alpine - -# set environment variables -ENV PYTHONDONTWRITEBYTECODE 1 -ENV PYTHONUNBUFFERED 1 - -COPY ./requirements.txt . - -# install dependencies -RUN \ - apk update &&\ - apk add --no-cache --virtual .build-deps \ - python3-dev musl-dev gcc \ - binutils \ - postgresql-dev postgresql-libs \ - libffi-dev \ - pkgconfig openssl &&\ - apk add --no-cache --update \ - libpq gdal-dev && \ - pip install --upgrade pip &&\ - pip install -r requirements.txt &&\ - apk --purge del .build-deps - -# copy project -COPY ./ /usr/local/apps/TEKDB/TEKDB -COPY ./docker/entrypoint.sh /entrypoint.sh - -# set work directory -WORKDIR /usr/local/apps/TEKDB/TEKDB - -RUN chmod +x /entrypoint.sh - -RUN mkdir -p /vol/web/media -RUN mkdir -p /vol/web/static - -RUN adduser -D tekdb_user -RUN chown -R tekdb_user:tekdb_user /vol -RUN chmod -R 755 /vol/web - -USER tekdb_user - -CMD ["/entrypoint.sh"] From 10d2628b2a64c9d6ead11c7c26814d7677bba167 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Thu, 11 Dec 2025 11:07:14 -0800 Subject: [PATCH 12/14] fix volumes location --- TEKDB/entrypoint.sh | 2 ++ docker/docker-compose.yml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/TEKDB/entrypoint.sh b/TEKDB/entrypoint.sh index 29eabbb8..166c5378 100644 --- a/TEKDB/entrypoint.sh +++ b/TEKDB/entrypoint.sh @@ -16,7 +16,9 @@ if [ -n "$SQL_HOST" ]; then echo "Postgres is up" fi +echo "Collecting static files..." python manage.py collectstatic --noinput +echo "Applying database migrations..." python manage.py migrate --noinput # Load default users only if no users exist echo "Checking for existing users..." diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index a11ce15b..f865e83a 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -39,7 +39,7 @@ services: ports: - "8000:8000" volumes: - - .:/usr/src/app + - ../TEKDB:/usr/src/app volumes: tekdb_db_data: From 11d6c853eab05d36cbb73b5db50ab471ec14d785 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Thu, 18 Dec 2025 13:12:06 -0800 Subject: [PATCH 13/14] add commands for dev and prod server options --- TEKDB/Dockerfile | 5 +++- TEKDB/entrypoint.sh | 16 ++++++++---- docker/docker-compose.prod.yaml | 46 +++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 docker/docker-compose.prod.yaml diff --git a/TEKDB/Dockerfile b/TEKDB/Dockerfile index f224a702..896b7676 100644 --- a/TEKDB/Dockerfile +++ b/TEKDB/Dockerfile @@ -33,10 +33,13 @@ COPY . /usr/src/app COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh -# Expose the port the app runs on (entrypoint starts uWSGI on 8000) +# Expose the port the app runs on (entrypoint starts django development server or uWSGI on 8000) EXPOSE 8000 # Default settings module (can be overridden at runtime) ENV DJANGO_SETTINGS_MODULE=TEKDB.settings ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] + +# use development server by default +CMD ["dev"] diff --git a/TEKDB/entrypoint.sh b/TEKDB/entrypoint.sh index 166c5378..fac43bbe 100644 --- a/TEKDB/entrypoint.sh +++ b/TEKDB/entrypoint.sh @@ -30,8 +30,14 @@ echo "Checking for existing lookups..." if [ "$(python manage.py shell -c 'from TEKDB.models import LookupPlanningUnit; print(LookupPlanningUnit.objects.count())')" = "0" ]; then python manage.py loaddata TEKDB/fixtures/default_lookups_fixture.json fi -echo "Starting uWSGI (HTTP) on :8000" -# Use HTTP socket so direct HTTP clients (browsers) can connect to the container port. -# If you proxy with nginx using the uwsgi protocol, switch back to --socket and use -# uwsgi_pass in nginx configuration. -uwsgi --http :8000 --master --enable-threads --module TEKDB.wsgi \ No newline at end of file + +if [ "$1" = "prod" ]; then + echo "Starting uWSGI (HTTP) on :8000" + uwsgi --http :8000 --master --enable-threads --module TEKDB.wsgi +elif [ "$1" = "dev" ]; then + echo "Starting python development server on :8000" + python manage.py runserver 0.0.0.0:8000 +else + # Default to the passed command if not 'prod' or 'dev' + exec "$@" +fi \ No newline at end of file diff --git a/docker/docker-compose.prod.yaml b/docker/docker-compose.prod.yaml new file mode 100644 index 00000000..872e7c53 --- /dev/null +++ b/docker/docker-compose.prod.yaml @@ -0,0 +1,46 @@ +services: + db: + image: postgis/postgis:15-3.4 + restart: always + platform: linux/amd64 + environment: + POSTGRES_DB: ${SQL_DATABASE} + POSTGRES_USER: ${SQL_USER} + POSTGRES_PASSWORD: ${SQL_PASSWORD} + volumes: + - tekdb_db_data:/var/lib/postgresql/data + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${SQL_USER} -d ${SQL_DATABASE} -h localhost -p ${SQL_PORT}"] + interval: 10s + timeout: 5s + retries: 5 + + web: + build: + context: ../TEKDB/ + dockerfile: ../TEKDB/Dockerfile + command: ["prod"] + restart: unless-stopped + depends_on: + - db + env_file: + - .env.dev + environment: + ALLOWED_HOSTS: ${ALLOWED_HOSTS} + DEBUG: ${DEBUG} + SQL_ENGINE: ${SQL_ENGINE} + SQL_HOST: ${SQL_HOST} + SQL_PORT: ${SQL_PORT} + SQL_DATABASE: ${SQL_DATABASE} + SQL_USER: ${SQL_USER} + SQL_PASSWORD: ${SQL_PASSWORD} + SECRET_KEY: ${SECRET_KEY} + ports: + - "8000:8000" + volumes: + - ../TEKDB:/usr/src/app + +volumes: + tekdb_db_data: From a7cb16c566f212f27fa794616ced2dfe3698b18c Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Thu, 18 Dec 2025 13:57:44 -0800 Subject: [PATCH 14/14] update local_settings.py template --- TEKDB/TEKDB/local_settings.py.template | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/TEKDB/TEKDB/local_settings.py.template b/TEKDB/TEKDB/local_settings.py.template index 4fe76e97..dfd96e86 100644 --- a/TEKDB/TEKDB/local_settings.py.template +++ b/TEKDB/TEKDB/local_settings.py.template @@ -6,13 +6,21 @@ ALLOWED_HOSTS = [ # SECRET_KEY='fixthisdjango' # DATABASES = { -# 'default': { -# 'ENGINE': 'django.contrib.gis.db.backends.postgis', -# 'NAME': 'DB Name', -# 'USER': 'add user', -# 'PASSWORD': 'add password', -# 'HOST': 'add host', -# 'PORT': add number, +# "default": { +# "ENGINE": os.environ.get("SQL_ENGINE", "django.contrib.gis.db.backends.postgis"), +# "NAME": os.environ.get("SQL_DATABASE", "tekdb"), +# "USER": os.environ.get("SQL_USER", "postgres"), +# "PASSWORD": os.environ.get("SQL_PASSWORD", ""), +# "HOST": ( +# os.environ.get("SQL_HOST") +# or os.environ.get("DB_HOST") +# or "localhost" +# ), +# "PORT": ( +# os.environ.get("SQL_PORT") +# or os.environ.get("DB_PORT") +# or "5432" +# ), # } # }