Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e0bad2d
Update .gitignore to include docker environment and static/media dire…
pollardld Jul 16, 2026
0b5e2cd
Add Docker configuration and environment example files for local deve…
pollardld Jul 16, 2026
b5c380d
Add Docker configuration files for mida-portal
pollardld Jul 16, 2026
5e9f9ff
Remove editable installation line from requirements.txt
pollardld Jul 16, 2026
6c3d0b1
Add Taskfile.yml for managing Docker tasks and services
pollardld Jul 16, 2026
a2118c4
Update base task in Taskfile.yml to load environment variables before…
pollardld Jul 16, 2026
89c6b66
Update .env.example and Dockerfile for clarity and consistency
pollardld Jul 16, 2026
dec42d4
Refactor Docker Compose configuration to support madrona app dependen…
pollardld Jul 16, 2026
5fd90a6
Add db-restore.sh script for restoring PostgreSQL dumps in Docker
pollardld Jul 16, 2026
deae86f
Clean up formatting in .env.example for consistency
pollardld Jul 16, 2026
8a7051c
Merge pull request #68 from Ecotrust/dd5
pollardld Jul 16, 2026
2eca687
Reorder Docker Compose file paths for clarity and update volume bindi…
pollardld Jul 17, 2026
c652545
Merge pull request #69 from Ecotrust/dd6
pollardld Jul 17, 2026
05ae752
Add Docker quickstart section to README.md
pollardld Jul 21, 2026
98c369b
Add GitHub Actions workflow for building and publishing mida-portal i…
pollardld Jul 21, 2026
a5eb5e5
Update actions/checkout to version 6 in GitHub Actions workflow
pollardld Jul 21, 2026
4ff0003
Update BASE_TAG in Dockerfile to use 'latest' for consistency
pollardld Jul 21, 2026
4a1a4eb
Update BASE_TAG in workflow to use commit SHA for consistency
pollardld Jul 22, 2026
54d1fcb
Merge pull request #70 from Ecotrust/dd7
pollardld Jul 22, 2026
9ad603a
Update Docker Compose file to correct build context and Dockerfile path
pollardld Jul 23, 2026
264aa7a
Update BASE_TAG in workflow to use 'latest' for consistency
pollardld Aug 3, 2026
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
49 changes: 49 additions & 0 deletions .github/workflows/build-and-publish-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Build and publish mida-portal image

on:
push:
branches: [main, dockerdecouple]
workflow_dispatch:

env:
BASE_TAG: latest
IMAGE_NAME: ghcr.io/ecotrust/mida-portal

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract short SHA
id: meta
run: echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
push: true
build-args: |
BASE_TAG=${{ env.BASE_TAG }}
tags: |
${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.sha }}
${{ env.IMAGE_NAME }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
*.pyc
wcoa.egg-info/PKG-INFO
deploy/sync_prod_content.sh
docker/.env
docker/static/
docker/media/
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ Mid-Atlantic Ocean Data Portal

Django web application and Wagtail CMS for the Mid-Atlantic Ocean Data Portal.

## Docker quickstart

Use the split base/overlay workflow.

```bash
cp docker/.env.example docker/.env
task base build init
```

## Local Vagrant Development Env

requirements:
Expand Down
49 changes: 49 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
version: '3'

vars:
CORE: ../../madrona-portal
COMPOSE: docker compose -f docker/compose.yml -f {{.CORE}}/docker/compose.base.yml --env-file docker/.env

tasks:
base:
desc: build the platform base image locally
cmds:
- sh -c 'if [ -f docker/.env ]; then set -a; . docker/.env; set +a; fi; docker build -t ghcr.io/ecotrust/madrona-portal:${BASE_TAG:-latest} -f {{.CORE}}/docker/Dockerfile {{.CORE}}/../'

build:
desc: build the mida portal image
cmds:
- '{{.COMPOSE}} build'

up:
desc: start mida services
cmds:
- '{{.COMPOSE}} up'

init:
desc: first run with migrations, fixtures, and superuser bootstrap
cmds:
- DB_INIT=1 {{.COMPOSE}} up

down:
desc: stop mida services
cmds:
- '{{.COMPOSE}} down'

logs:
desc: tail app logs
cmds:
- '{{.COMPOSE}} logs -f app'

manage:
desc: run a Django manage.py command (pass with -- cmd="...")
requires:
vars:
- cmd
cmds:
- '{{.COMPOSE}} exec app python marco/manage.py {{.cmd}}'

shell:
desc: open Django shell
cmds:
- '{{.COMPOSE}} exec app python marco/manage.py shell'
26 changes: 26 additions & 0 deletions docker/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
COMPOSE_PROJECT_NAME=mida
BASE_TAG=latest

APP_PORT=8001
DB_PORT=5433

SECRET_KEY=
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1,::1
DB_ENGINE=django.contrib.gis.db.backends.postgis
DB_NAME=mida_docker_db
DB_USER=postgres
DB_PASSWORD=
REDIS_PASSWORD=

DB_INIT=0
DJANGO_SUPERUSER_USERNAME=admin
DJANGO_SUPERUSER_EMAIL=admin@example.com
DJANGO_SUPERUSER_PASSWORD=
DJANGO_ENV=development
GUNICORN_WORKERS=3

RECAPTCHA_PUBLIC_KEY=
RECAPTCHA_PRIVATE_KEY=
GA_ACCOUNT=
ARCGIS_API_KEY=
13 changes: 13 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
ARG BASE_IMAGE=ghcr.io/ecotrust/madrona-portal

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

love how minimal this dockerfile is!

ARG BASE_TAG=latest
FROM ${BASE_IMAGE}:${BASE_TAG}

# Build context is mida-portal repo root
COPY --chown=madrona_user:madrona_user . ./apps/mida-portal

RUN pip install --no-deps -e ./apps/mida-portal && \
if [ -s ./apps/mida-portal/docker/requirements.txt ]; then \
pip install -r ./apps/mida-portal/docker/requirements.txt; \
fi

ENV MP_PROJECT_CONFIG=/usr/local/apps/madrona-portal/apps/mida-portal/docker/config.mida.docker.ini

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need /usr/local/apps/madrona-portal/ here?

100 changes: 100 additions & 0 deletions docker/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
services:
app:
image: mida-portal:dev
build:
context: ..
dockerfile: docker/Dockerfile
args:
BASE_TAG: ${BASE_TAG:-latest}
env_file:
- .env
environment:
- MP_PROJECT_CONFIG=/usr/local/apps/madrona-portal/apps/mida-portal/docker/config.mida.docker.ini
volumes:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a lot of volumes. I'd be interested in one day seeing if there are alternative architectures we could use.

- ./static:/vol/web/static
- ./media:/usr/local/apps/madrona-portal/media
- type: bind
source: ../../../madrona-portal/marco
target: /usr/local/apps/madrona-portal/marco
bind:
create_host_path: false
- type: bind
source: ..
target: /usr/local/apps/madrona-portal/apps/mida-portal
bind:
create_host_path: false
- type: bind
source: ../../mp-data-manager
target: /usr/local/apps/madrona-portal/apps/mp-data-manager
bind:
create_host_path: false
- type: bind
source: ../../mp-layers
target: /usr/local/apps/madrona-portal/apps/mp-layers
bind:
create_host_path: false
- type: bind
source: ../../mp-accounts
target: /usr/local/apps/madrona-portal/apps/mp-accounts
bind:
create_host_path: false
- type: bind
source: ../../mp-drawing
target: /usr/local/apps/madrona-portal/apps/mp-drawing
bind:
create_host_path: false
- type: bind
source: ../../mp-visualize
target: /usr/local/apps/madrona-portal/apps/mp-visualize
bind:
create_host_path: false
- type: bind
source: ../../madrona-features
target: /usr/local/apps/madrona-portal/apps/madrona-features
bind:
create_host_path: false
- type: bind
source: ../../madrona-manipulators
target: /usr/local/apps/madrona-portal/apps/madrona-manipulators
bind:
create_host_path: false
- type: bind
source: ../../madrona-scenarios
target: /usr/local/apps/madrona-portal/apps/madrona-scenarios
bind:
create_host_path: false
- type: bind
source: ../../mp-map-groups
target: /usr/local/apps/madrona-portal/apps/mp-map-groups
bind:
create_host_path: false
- type: bind
source: ../../mp-explore
target: /usr/local/apps/madrona-portal/apps/mp-explore
bind:
create_host_path: false
- type: bind
source: ../../mp-proxy
target: /usr/local/apps/madrona-portal/apps/mp-proxy
bind:
create_host_path: false
- type: bind
source: ../../p97-nursery
target: /usr/local/apps/madrona-portal/apps/p97-nursery
bind:
create_host_path: false
- type: bind
source: ../../django_url_shortener
target: /usr/local/apps/madrona-portal/apps/django_url_shortener
bind:
create_host_path: false
- type: bind
source: ../../madrona-analysistools
target: /usr/local/apps/madrona-portal/apps/madrona-analysistools
bind:
create_host_path: false
- type: bind
source: ../../mp-survey
target: /usr/local/apps/madrona-portal/apps/mp-survey
bind:
create_host_path: false
88 changes: 88 additions & 0 deletions docker/config.mida.docker.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Docker-focused configuration for mida local development.
# Use with MP_PROJECT_CONFIG=config.mida.docker.ini

[APP]
APP_NAME = Mid-Atlantic Ocean Data Portal
APP_URL =
APP_TEAM_NAME = Marine Planner Team
PROJECT_APP = mida
PROJECT_SETTINGS_FILE = True
DEBUG = True
TEMPLATE_DEBUG = True
ALLOWED_HOSTS = ["localhost", "127.0.0.1", "::1"]
# SECRET_KEY is loaded from environment variable: SECRET_KEY
MEDIA_ROOT = /usr/local/apps/madrona-portal/media
MEDIA_URL = /media/
TIME_ZONE = UTC
GA_ACCOUNT =
# ReCAPTCHA keys are loaded from env vars: RECAPTCHA_PUBLIC_KEY, RECAPTCHA_PRIVATE_KEY
STATIC_ROOT = /vol/web/static
EMAIL_SUBJECT_PREFIX = [MidA]
MAP_LIBRARY = ol8
COMPRESS_ENABLED = True
STATIC_CORE = /vol/web/static/
ADDITIONAL_APPS = []
ADDITIONAL_MIDDLEWARE = []

[REGION]
# TODO(human): verify against prod config.ini/local_settings.py
NAME = Mid-Atlantic
# TODO(human): verify against prod config.ini/local_settings.py
INIT_ZOOM = 7
# TODO(human): verify against prod config.ini/local_settings.py
INIT_LAT = 38.5
# TODO(human): verify against prod config.ini/local_settings.py
INIT_LON = -73.5
# TODO(human): verify against prod config.ini/local_settings.py
MAP = ocean

[CACHES]
BACKEND = django_redis.cache.RedisCache
LOCATION = redis://tasks:6379/1
CLIENT_CLASS = django_redis.client.DefaultClient

[CELERY]
CELERY_RESULT_BACKEND = redis://tasks:6379/1
CELERY_BROKER_URL = redis://tasks:6379/0
CELERY_ALWAYS_EAGER = False
CELERY_DISABLE_RATE_LIMITS = True

[DATABASE]
ENGINE = django.contrib.gis.db.backends.postgis
NAME = mida_docker_db
HOST = db
PORT = 5432
USER = postgres
# DB password is loaded from environment variable: DB_PASSWORD

[EMAIL]
HOST = localhost
PORT = 25
# SMTP credentials are loaded from env vars: EMAIL_HOST_USER, EMAIL_HOST_PASSWORD
# TODO(human): verify from-addresses against prod config.ini/local_settings.py
DEFAULT_FROM_EMAIL = Mid-Atlantic Portal <support@mail.mida.ecotrust.org>
# TODO(human): verify from-addresses against prod config.ini/local_settings.py
SERVER_EMAIL = MidA Site Errors <midasupport@mail.mida.ecotrust.org>

[AWS]
# AWS credentials are loaded from env vars: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
AWS_SES_REGION_NAME = us-east-1
AWS_SES_REGION_ENDPOINT = email.us-east-1.amazonaws.com

[SOCIAL_AUTH]
# TODO(human): verify social auth credentials/keys against prod config.ini/local_settings.py
# FACEBOOK_KEY=
# FACEBOOK_SECRET=
# TWITTER_KEY=
# TWITTER_SECRET=
# GOOGLE_KEY=
# GOOGLE_SECRET=

[CATALOG]
# TODO(human): verify catalog settings against prod config.ini/local_settings.py
DATA_CATALOG_ENABLED = True
# TODO(human): verify catalog technology/source/query endpoint against prod
CATALOG_TECHNOLOGY = GeoPortal2
CATALOG_PROXY =
CATALOG_SOURCE =
CATALOG_QUERY_ENDPOINT =
2 changes: 2 additions & 0 deletions docker/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Project-only Python dependencies for mida Docker image.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kind of surprising that there aren't any mid a specific python dependencies. but maybe that just speaks to how intertwined the projects have been.

# Leave empty unless mida requires packages not already in the base image.
2 changes: 0 additions & 2 deletions mida/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
-e git+https://github.com/Ecotrust/mida-portal.git@master#egg=mida

# pip3 install selenium
Loading
Loading