Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a Docker-based local development setup for the WC Bluepages Django app, including a PostGIS database container (optionally seeded from a SQL dump) and a web container that runs migrations/collectstatic on startup.
Changes:
- Add
docker-compose.yml+Dockerfileto build/run the app and a PostGIS DB locally. - Add container entrypoint/init scripts to import a DB dump and run Django management tasks.
- Add
docker_settings.pyand updatesettings.pyto support Docker-specific configuration; add Docker setup README and.dockerignore.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
Dockerfile |
Builds a Python image with GIS/Postgres deps and uses a custom entrypoint script. |
docker-compose.yml |
Defines db (PostGIS) and web (Django) services, volumes, and env vars. |
docker-entrypoint.sh |
Waits for DB readiness, runs migrations/collectstatic, then starts the server. |
init-db.sh |
Initializes the DB container by importing db_dump.sql on first startup. |
bluepages/bluepages/settings.py |
Loads docker_settings.py when DOCKER_CONTAINER is set. |
bluepages/bluepages/docker_settings.py |
Provides Docker-specific DB/static/media settings. |
README.docker.md |
Documents how to run locally using Docker with a required DB dump. |
.dockerignore |
Reduces Docker build context size and excludes dev artifacts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Import the SQL dump, ignoring meta-command errors | ||
| psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -v ON_ERROR_STOP=0 < /tmp/db_dump.sql |
There was a problem hiding this comment.
Using -v ON_ERROR_STOP=0 will continue on SQL errors and can silently produce a partially imported/corrupt initial database. Since this runs on first init of an empty DB, it’s safer to stop on the first error (ON_ERROR_STOP=1) and fail the container startup, or explicitly handle only expected errors.
| # Import the SQL dump, ignoring meta-command errors | |
| psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -v ON_ERROR_STOP=0 < /tmp/db_dump.sql | |
| # Import the SQL dump, stopping on the first error to avoid partial/corrupt state | |
| psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 < /tmp/db_dump.sql |
| # Copy and set entrypoint script | ||
| COPY docker-entrypoint.sh /app/ |
There was a problem hiding this comment.
COPY . /app/ already brings docker-entrypoint.sh into the image, so the later COPY docker-entrypoint.sh /app/ is redundant and can cause confusion when editing. Consider removing one of the copies (typically keep the explicit copy and move it before COPY . if you want better layer caching).
| # Copy and set entrypoint script | |
| COPY docker-entrypoint.sh /app/ | |
| # Set entrypoint script as executable |
| # Allow all hosts in Docker (configure properly for production) | ||
| ALLOWED_HOSTS = ['*'] |
There was a problem hiding this comment.
Setting ALLOWED_HOSTS = ['*'] makes the container accept requests for any Host header, which is unsafe if the port is ever exposed beyond localhost (e.g., on a shared network). Prefer restricting to local/dev hosts (localhost/127.0.0.1/0.0.0.0) or making this configurable via an env var.
| # Allow all hosts in Docker (configure properly for production) | |
| ALLOWED_HOSTS = ['*'] | |
| # Allowed hosts: configurable via env, with safe local defaults | |
| _allowed_hosts_env = os.environ.get('DJANGO_ALLOWED_HOSTS') | |
| if _allowed_hosts_env: | |
| ALLOWED_HOSTS = [h.strip() for h in _allowed_hosts_env.split(',') if h.strip()] | |
| else: | |
| ALLOWED_HOSTS = ['localhost', '127.0.0.1', '0.0.0.0'] |
| } | ||
|
|
||
| # Debug mode from environment | ||
| DEBUG = os.environ.get('DEBUG', 'False') == 'True' |
There was a problem hiding this comment.
DEBUG = os.environ.get('DEBUG', 'False') == 'True' is case-sensitive and treats values like true/1/yes as False, which is easy to misconfigure. Consider using a more robust boolean parser (e.g., normalize to lowercase and accept common truthy values).
| DEBUG = os.environ.get('DEBUG', 'False') == 'True' | |
| DEBUG = os.environ.get('DEBUG', 'False').strip().lower() in ('true', '1', 'yes', 'y', 'on') |
| image: postgis/postgis:16-3.4 | ||
| platform: linux/amd64 | ||
| container_name: bluepages_db |
There was a problem hiding this comment.
Hard-coding platform: linux/amd64 reduces portability (e.g., Apple Silicon will run under emulation, slower; some setups may fail). If this is only needed for specific environments, consider making it optional/configurable (e.g., via an env var) or documenting why it’s required.
| # Use Python 3.11 slim image as base | ||
| FROM python:3.11-slim-bookworm |
There was a problem hiding this comment.
The base requirements pin Django to <3.3 (Django 3.2.x), which is not compatible with Python 3.11 per Django’s supported Python versions. This image is likely to fail at runtime or during dependency install; either use a Python 3.10 base image or upgrade Django (and any deps) to a version that supports 3.11.
| # Use Python 3.11 slim image as base | |
| FROM python:3.11-slim-bookworm | |
| # Use Python 3.10 slim image as base (compatible with Django 3.2.x) | |
| FROM python:3.10-slim-bookworm |
| echo "Waiting for PostgreSQL..." | ||
| while ! pg_isready -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" > /dev/null 2>&1; do | ||
| sleep 1 | ||
| done |
There was a problem hiding this comment.
The PostgreSQL wait loop has no timeout, so a misconfigured DB_* env or an unavailable database will hang the container indefinitely. Add a max retry count / deadline and exit non-zero with a clear error when exceeded.
| # Import Docker settings if running in Docker | ||
| if os.environ.get('DOCKER_CONTAINER'): | ||
| try: | ||
| from .docker_settings import * |
There was a problem hiding this comment.
Import pollutes the enclosing namespace, as the imported module bluepages.docker_settings does not define 'all'.
| except Exception as e: | ||
| print("Unable to import local_settings") | ||
| pass No newline at end of file | ||
| pass |
There was a problem hiding this comment.
Unnecessary 'pass' statement.
| print("Docker settings loaded") | ||
| except Exception as e: | ||
| print(f"Unable to import docker_settings: {e}") | ||
| pass No newline at end of file |
There was a problem hiding this comment.
Unnecessary 'pass' statement.
pollardld
left a comment
There was a problem hiding this comment.
This is in good shape for use after the migration issue from the PR description is solved.
asana task
I was not able to get the app to run locally without loading a data dump. I think this is because of the migration issues @rhodges mentioned.
This does not have updated python + django versions