From 27d0ff68a59ef4acdb27f8cdbe73d22e03f53835 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 14:29:13 -0800 Subject: [PATCH 01/13] use .env.prod in docker-compose.prod.yaml --- .gitignore | 1 + docker/docker-compose.prod.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c5ba5117..c77ac2b2 100644 --- a/.gitignore +++ b/.gitignore @@ -86,6 +86,7 @@ celerybeat-schedule # dotenv .env +.env.prod # virtualenv venv/ diff --git a/docker/docker-compose.prod.yaml b/docker/docker-compose.prod.yaml index 872e7c53..2598a35b 100644 --- a/docker/docker-compose.prod.yaml +++ b/docker/docker-compose.prod.yaml @@ -26,7 +26,7 @@ services: depends_on: - db env_file: - - .env.dev + - .env.prod environment: ALLOWED_HOSTS: ${ALLOWED_HOSTS} DEBUG: ${DEBUG} From 5e5cc5bbf30fe7f0c4a368415e66415db5f2f053 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 15:13:11 -0800 Subject: [PATCH 02/13] add github action to publish docker image to github packages --- .../create-and-publish-docker-images.yml | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/create-and-publish-docker-images.yml diff --git a/.github/workflows/create-and-publish-docker-images.yml b/.github/workflows/create-and-publish-docker-images.yml new file mode 100644 index 00000000..37256b53 --- /dev/null +++ b/.github/workflows/create-and-publish-docker-images.yml @@ -0,0 +1,58 @@ +# source: https://docs.github.com/en/actions/tutorials/publish-packages/publish-docker-images#publishing-images-to-docker-hub-and-github-packages +name: Create and publish a Docker image + +# manually trigger while testing +on: + workflow_dispatch: + +# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds. +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. + permissions: + contents: read + packages: write + attestations: write + id-token: write + # + steps: + - name: Checkout repository + uses: actions/checkout@v5 + # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. + # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see [Usage](https://github.com/docker/build-push-action#usage) in the README of the `docker/build-push-action` repository. + # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. + - name: Build and push Docker image + id: push + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + # This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see [Using artifact attestations to establish provenance for builds](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds). + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v3 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true + From e91eb06f4849892ec69b6c3b10c4cf4a75cba93d Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 15:20:27 -0800 Subject: [PATCH 03/13] point push step to prod dockerfile --- .github/workflows/create-and-publish-docker-images.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-and-publish-docker-images.yml b/.github/workflows/create-and-publish-docker-images.yml index 37256b53..ffea8093 100644 --- a/.github/workflows/create-and-publish-docker-images.yml +++ b/.github/workflows/create-and-publish-docker-images.yml @@ -43,9 +43,10 @@ jobs: id: push uses: docker/build-push-action@v6 with: - context: . + context: ./TEKDB + file: ./TEKDB/prod.Dockerfile push: true - tags: ${{ steps.meta.outputs.tags }} + tags: ghcr.io/${{ github.repository }}/web:latest,ghcr.io/${{ github.repository }}/web:${{ github.sha }} labels: ${{ steps.meta.outputs.labels }} # This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see [Using artifact attestations to establish provenance for builds](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds). From ec83f25d21d5add9c63b62c94e691c17d65914d1 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 15:24:15 -0800 Subject: [PATCH 04/13] try triggering action on push --- .github/workflows/create-and-publish-docker-images.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/create-and-publish-docker-images.yml b/.github/workflows/create-and-publish-docker-images.yml index ffea8093..eb90ec3d 100644 --- a/.github/workflows/create-and-publish-docker-images.yml +++ b/.github/workflows/create-and-publish-docker-images.yml @@ -2,8 +2,7 @@ name: Create and publish a Docker image # manually trigger while testing -on: - workflow_dispatch: +on: [push, workflow_dispatch] # Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds. env: From 453f95e339610b8c2272e438ecd09dec6146adb0 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 15:35:37 -0800 Subject: [PATCH 05/13] try generating slug for repo name --- .github/workflows/create-and-publish-docker-images.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/create-and-publish-docker-images.yml b/.github/workflows/create-and-publish-docker-images.yml index eb90ec3d..85e9e4f1 100644 --- a/.github/workflows/create-and-publish-docker-images.yml +++ b/.github/workflows/create-and-publish-docker-images.yml @@ -35,9 +35,16 @@ jobs: uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + - name: Format repo slug + uses: actions/github-script@v4 + id: repo_slug + with: + result-encoding: string + script: return `ghcr.io/${github.repository.toLowerCase()}` # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see [Usage](https://github.com/docker/build-push-action#usage) in the README of the `docker/build-push-action` repository. # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. + - name: Build and push Docker image id: push uses: docker/build-push-action@v6 @@ -45,8 +52,11 @@ jobs: context: ./TEKDB file: ./TEKDB/prod.Dockerfile push: true + builder: ${{ steps.buildx.outputs.name }} tags: ghcr.io/${{ github.repository }}/web:latest,ghcr.io/${{ github.repository }}/web:${{ github.sha }} labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ steps.repo_slug.outputs.result }}:main + cache-to: type=inline # This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see [Using artifact attestations to establish provenance for builds](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds). - name: Generate artifact attestation From 4d93d8d5bdb1781c3a7d056c28b664880a81cf25 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 15:41:08 -0800 Subject: [PATCH 06/13] try getting slug for repo name as string --- .github/workflows/create-and-publish-docker-images.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-and-publish-docker-images.yml b/.github/workflows/create-and-publish-docker-images.yml index 85e9e4f1..841295de 100644 --- a/.github/workflows/create-and-publish-docker-images.yml +++ b/.github/workflows/create-and-publish-docker-images.yml @@ -36,11 +36,12 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - name: Format repo slug - uses: actions/github-script@v4 + uses: actions/github-script@v8 id: repo_slug with: result-encoding: string - script: return `ghcr.io/${github.repository.toLowerCase()}` + script: | + return `ghcr.io/${process.env.GITHUB_REPOSITORY.toLowerCase()}` # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see [Usage](https://github.com/docker/build-push-action#usage) in the README of the `docker/build-push-action` repository. # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. From 43916a5b11a81d29642eac52192ef7b4200cde92 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 15:43:54 -0800 Subject: [PATCH 07/13] try again to use lowercase repo name --- .github/workflows/create-and-publish-docker-images.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/create-and-publish-docker-images.yml b/.github/workflows/create-and-publish-docker-images.yml index 841295de..3d212206 100644 --- a/.github/workflows/create-and-publish-docker-images.yml +++ b/.github/workflows/create-and-publish-docker-images.yml @@ -7,7 +7,6 @@ on: [push, workflow_dispatch] # Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds. env: REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} jobs: build-and-push-image: @@ -35,6 +34,10 @@ jobs: uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + # note: IMAGE_NAME will be set in the next step via GITHUB_ENV + - name: Set lowercase image name + run: | + echo "IMAGE_NAME=$(echo \"${GITHUB_REPOSITORY}\" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV - name: Format repo slug uses: actions/github-script@v8 id: repo_slug @@ -53,8 +56,7 @@ jobs: context: ./TEKDB file: ./TEKDB/prod.Dockerfile push: true - builder: ${{ steps.buildx.outputs.name }} - tags: ghcr.io/${{ github.repository }}/web:latest,ghcr.io/${{ github.repository }}/web:${{ github.sha }} + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/web:latest,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/web:${{ github.sha }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ steps.repo_slug.outputs.result }}:main cache-to: type=inline From 521e7509cb4f36d0c3cc93b23535c5fac0b85858 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 15:46:19 -0800 Subject: [PATCH 08/13] try setting lowercase IMAGE_NAME env var --- .github/workflows/create-and-publish-docker-images.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/create-and-publish-docker-images.yml b/.github/workflows/create-and-publish-docker-images.yml index 3d212206..f95f4f63 100644 --- a/.github/workflows/create-and-publish-docker-images.yml +++ b/.github/workflows/create-and-publish-docker-images.yml @@ -29,15 +29,15 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. + - name: Set lowercase image name + run: | + IMAGE_NAME=$(echo "${GITHUB_REPOSITORY}" | tr '[:upper:]' '[:lower:]') + echo "IMAGE_NAME=${IMAGE_NAME}" >> $GITHUB_ENV - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - # note: IMAGE_NAME will be set in the next step via GITHUB_ENV - - name: Set lowercase image name - run: | - echo "IMAGE_NAME=$(echo \"${GITHUB_REPOSITORY}\" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV - name: Format repo slug uses: actions/github-script@v8 id: repo_slug From 05fcd1b18c342049421b519eddd7a97bc3c8aadf Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 15:49:41 -0800 Subject: [PATCH 09/13] add prod dockerfile --- TEKDB/prod.Dockerfile | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 TEKDB/prod.Dockerfile diff --git a/TEKDB/prod.Dockerfile b/TEKDB/prod.Dockerfile new file mode 100644 index 00000000..ca2d2e24 --- /dev/null +++ b/TEKDB/prod.Dockerfile @@ -0,0 +1,46 @@ +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 \ + gcc \ + gdal-bin \ + libgdal-dev \ + libgeos-dev \ + && 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 requirements_linux.txt /usr/src/app/ + +# Upgrade pip and install Python dependencies +# Note: editable packages (-e) will be installed at runtime via entrypoint.sh +RUN pip install --upgrade pip \ + && pip install -r requirements.txt -r requirements_linux.txt + +# Copy 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 entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +# 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 prod server in prod Dockerfile +CMD ["prod"] \ No newline at end of file From 76b4ab0e55886ea9830dda55d868c73ce166afe7 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 16:12:03 -0800 Subject: [PATCH 10/13] remove cache lines for build and push step --- .github/workflows/create-and-publish-docker-images.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/create-and-publish-docker-images.yml b/.github/workflows/create-and-publish-docker-images.yml index f95f4f63..be42c4fb 100644 --- a/.github/workflows/create-and-publish-docker-images.yml +++ b/.github/workflows/create-and-publish-docker-images.yml @@ -58,8 +58,6 @@ jobs: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/web:latest,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/web:${{ github.sha }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ steps.repo_slug.outputs.result }}:main - cache-to: type=inline # This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see [Using artifact attestations to establish provenance for builds](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds). - name: Generate artifact attestation From 5fb47f561ed5c21bfa8b1853b41f54d515252955 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 16:25:26 -0800 Subject: [PATCH 11/13] try token change --- .github/workflows/create-and-publish-docker-images.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/create-and-publish-docker-images.yml b/.github/workflows/create-and-publish-docker-images.yml index be42c4fb..b3eca98e 100644 --- a/.github/workflows/create-and-publish-docker-images.yml +++ b/.github/workflows/create-and-publish-docker-images.yml @@ -11,13 +11,12 @@ env: jobs: build-and-push-image: runs-on: ubuntu-latest - # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. + # Sets the permissions granted to the `PACKAGE_TOKEN` for the actions in this job. permissions: contents: read packages: write attestations: write id-token: write - # steps: - name: Checkout repository uses: actions/checkout@v5 @@ -27,7 +26,7 @@ jobs: with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + password: ${{ secrets.PACKAGE_TOKEN }} # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. - name: Set lowercase image name run: | From 942ea136f6329ee49252b4723683d82dc6b5f955 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Tue, 3 Feb 2026 16:45:15 -0800 Subject: [PATCH 12/13] remove push from trigger options --- .github/workflows/create-and-publish-docker-images.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/create-and-publish-docker-images.yml b/.github/workflows/create-and-publish-docker-images.yml index b3eca98e..658a2459 100644 --- a/.github/workflows/create-and-publish-docker-images.yml +++ b/.github/workflows/create-and-publish-docker-images.yml @@ -2,7 +2,8 @@ name: Create and publish a Docker image # manually trigger while testing -on: [push, workflow_dispatch] +on: + workflow_dispatch # Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds. env: From c83e88ce5e8dd1bf6cd3a44a1a4915998b3a862e Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Wed, 4 Feb 2026 10:47:33 -0800 Subject: [PATCH 13/13] use common docker compose and use extends --- docker/{docker-compose.yml => common.yaml} | 7 ++-- docker/docker-compose.prod.yaml | 42 ++++------------------ docker/docker-compose.yaml | 13 +++++++ 3 files changed, 21 insertions(+), 41 deletions(-) rename docker/{docker-compose.yml => common.yaml} (94%) create mode 100644 docker/docker-compose.yaml diff --git a/docker/docker-compose.yml b/docker/common.yaml similarity index 94% rename from docker/docker-compose.yml rename to docker/common.yaml index f865e83a..3ee08bef 100644 --- a/docker/docker-compose.yml +++ b/docker/common.yaml @@ -16,7 +16,7 @@ services: interval: 10s timeout: 5s retries: 5 - + web: build: context: ../TEKDB/ @@ -39,7 +39,4 @@ services: ports: - "8000:8000" volumes: - - ../TEKDB:/usr/src/app - -volumes: - tekdb_db_data: + - ../TEKDB:/usr/src/app \ No newline at end of file diff --git a/docker/docker-compose.prod.yaml b/docker/docker-compose.prod.yaml index 2598a35b..c063379b 100644 --- a/docker/docker-compose.prod.yaml +++ b/docker/docker-compose.prod.yaml @@ -1,46 +1,16 @@ 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 + extends: + file: common.yaml + service: db web: - build: - context: ../TEKDB/ - dockerfile: ../TEKDB/Dockerfile + extends: + file: common.yaml + service: web command: ["prod"] - restart: unless-stopped - depends_on: - - db env_file: - .env.prod - 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: diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml new file mode 100644 index 00000000..5a99ff86 --- /dev/null +++ b/docker/docker-compose.yaml @@ -0,0 +1,13 @@ +services: + db: + extends: + file: common.yaml + service: db + + web: + extends: + file: common.yaml + service: web + +volumes: + tekdb_db_data: