From 9b68d7ecfb27bff885fc7ec4eb342a80ced7162e Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Fri, 6 Feb 2026 12:13:24 -0800 Subject: [PATCH 1/3] try docker; not working yet --- .dockerignore | 46 +++++ Dockerfile | 47 +++++ README.docker.md | 243 +++++++++++++++++++++++++ bluepages/bluepages/docker_settings.py | 28 +++ bluepages/bluepages/settings.py | 11 +- docker-compose.yml | 48 +++++ 6 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 README.docker.md create mode 100644 bluepages/bluepages/docker_settings.py create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4e90eee --- /dev/null +++ b/.dockerignore @@ -0,0 +1,46 @@ +# Git +.git +.gitignore + +# Python +__pycache__ +*.py[cod] +*$py.class +*.so +.Python +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +*.egg-info/ +.pytest_cache/ +.coverage +htmlcov/ + +# Django +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +/static_root/ +/media_root/ + +# IDEs +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Vagrant +.vagrant/ +Vagrantfile + +# Deployment +deploy/ +*.sql diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..09c5dba --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# Use Python 3.11 slim image as base +FROM python:3.11-slim-bookworm + +# Set environment variables +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PIP_NO_CACHE_DIR=1 \ + PIP_DISABLE_PIP_VERSION_CHECK=1 + +# Install system dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc \ + g++ \ + make \ + libpq-dev \ + postgresql-client \ + gdal-bin \ + libgdal-dev \ + libproj-dev \ + proj-bin \ + binutils \ + libspatialindex-dev \ + git \ + && rm -rf /var/lib/apt/lists/* + +# Set work directory +WORKDIR /app + +# Copy requirements and install Python dependencies +COPY requirements.txt /app/ +RUN pip install --upgrade pip && \ + pip install -r requirements.txt + +# Copy project files +COPY . /app/ + +# Create necessary directories +RUN mkdir -p /app/bluepages/static_root /app/bluepages/media_root + +# Set working directory to Django project +WORKDIR /app/bluepages + +# Expose port +EXPOSE 8000 + +# Default command (can be overridden in docker-compose) +CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] diff --git a/README.docker.md b/README.docker.md new file mode 100644 index 0000000..6b7b257 --- /dev/null +++ b/README.docker.md @@ -0,0 +1,243 @@ +# Docker Setup for WC Bluepages + +## Quick Start + +### 1. Build and start the containers: + +```bash +docker-compose up --build +``` + +### 2. Run initial setup (first time only): + +```bash +# Run migrations +docker-compose exec web python manage.py migrate + +# Create a superuser +docker-compose exec web python manage.py createsuperuser + +# Load fixtures +docker-compose exec web python manage.py loaddata app/fixtures/initial.json +docker-compose exec web python manage.py loaddata address/fixtures/initial.json + +# Collect static files +docker-compose exec web python manage.py collectstatic --noinput +``` + +### 3. Access the application: + +- Web application: http://localhost:8000 +- Admin interface: http://localhost:8000/admin + +## Common Commands + +### Run management commands: + +```bash +# Run migrations +docker-compose exec web python manage.py migrate + +# Create a superuser +docker-compose exec web python manage.py createsuperuser + +# Collect static files +docker-compose exec web python manage.py collectstatic --noinput + +# Access Django shell +docker-compose exec web python manage.py shell + +# Run any Django management command +docker-compose exec web python manage.py +``` + +### Database operations: + +```bash +# Access PostgreSQL shell +docker-compose exec db psql -U postgres -d bluepages + +# Create database backup +docker-compose exec db pg_dump -U postgres bluepages > backup.sql + +# Restore database +docker-compose exec -T db psql -U postgres bluepages < backup.sql + +# Or restore from a dump file +cat backup.sql | docker-compose exec -T db psql -U postgres bluepages +``` + +### View logs: + +```bash +# All services +docker-compose logs -f + +# Specific service +docker-compose logs -f web +docker-compose logs -f db +``` + +### Stop containers: + +```bash +# Stop containers (keeps data) +docker-compose stop + +# Stop and remove containers (keeps volumes/data) +docker-compose down + +# Stop and remove containers + volumes (deletes database!) +docker-compose down -v +``` + +## Development Workflow + +### Hot Reloading + +The `web` service mounts your local code directory, so changes to Python files are reflected immediately thanks to Django's development server auto-reload. + +### Install New Python Packages + +1. Add package to `requirements.txt` +2. Rebuild the container: + +```bash +docker-compose up --build web +``` + +### Access Container Shell + +```bash +# Python/Django container +docker-compose exec web bash + +# Database container +docker-compose exec db bash +``` + +### Running Tests + +```bash +docker-compose exec web python manage.py test +``` + +## Troubleshooting + +### Container won't start + +```bash +# Check logs +docker-compose logs web +docker-compose logs db + +# Rebuild from scratch +docker-compose down -v +docker-compose up --build +``` + +### Database connection issues + +```bash +# Check if database is ready +docker-compose exec db pg_isready -U postgres + +# Check environment variables +docker-compose exec web env | grep DB_ + +# Verify database exists +docker-compose exec db psql -U postgres -l +``` + +### Permission issues with volumes + +```bash +# Fix permissions on mounted volumes +sudo chown -R $USER:$USER bluepages/static_root bluepages/media_root +``` + +### Reset everything + +```bash +# Remove all containers, volumes, and start fresh +docker-compose down -v +docker-compose up --build +``` + +## Production Deployment + +For production, create a `docker-compose.prod.yml`: + +```yaml +version: "3.8" + +services: + db: + image: postgis/postgis:16-3.4 + restart: always + environment: + POSTGRES_DB: bluepages + POSTGRES_USER: postgres + POSTGRES_PASSWORD: ${DB_PASSWORD} # Use .env file + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - internal + + web: + build: . + restart: always + command: gunicorn bluepages.wsgi:application --bind 0.0.0.0:8000 --workers 4 + volumes: + - static_volume:/app/bluepages/static_root + - media_volume:/app/bluepages/media_root + environment: + - DOCKER_CONTAINER=1 + - DEBUG=False + - DB_NAME=bluepages + - DB_USER=postgres + - DB_PASSWORD=${DB_PASSWORD} + - DB_HOST=db + - SECRET_KEY=${SECRET_KEY} + depends_on: + - db + networks: + - internal + - web + + nginx: + image: nginx:alpine + restart: always + ports: + - "80:80" + - "443:443" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - static_volume:/app/static:ro + - media_volume:/app/media:ro + - ./ssl:/etc/nginx/ssl:ro + depends_on: + - web + networks: + - web + +networks: + internal: + web: + +volumes: + postgres_data: + static_volume: + media_volume: +``` + +Run with: `docker-compose -f docker-compose.prod.yml up -d` + +## Notes + +- PostgreSQL 16 with PostGIS 3.4 (matches Ubuntu 24.04) +- Python 3.11 (compatible with Django 3.2+) +- Development server runs on port 8000 +- Database runs on port 5432 (exposed for local tools) +- Code changes are live-reloaded in development +- Data persists in Docker volumes even when containers are stopped diff --git a/bluepages/bluepages/docker_settings.py b/bluepages/bluepages/docker_settings.py new file mode 100644 index 0000000..6e7bfb9 --- /dev/null +++ b/bluepages/bluepages/docker_settings.py @@ -0,0 +1,28 @@ +""" +Docker-specific settings that override base settings.py +This file is imported at the end of settings.py when running in Docker. +""" +import os + +# Database configuration from environment variables +DATABASES = { + 'default': { + 'ENGINE': 'django.contrib.gis.db.backends.postgis', + 'NAME': os.environ.get('DB_NAME', 'bluepages'), + 'USER': os.environ.get('DB_USER', 'postgres'), + 'PASSWORD': os.environ.get('DB_PASSWORD', 'postgres'), + 'HOST': os.environ.get('DB_HOST', 'db'), + 'PORT': os.environ.get('DB_PORT', '5432'), + } +} + +# Debug mode from environment +DEBUG = os.environ.get('DEBUG', 'False') == 'True' + +# Allow all hosts in Docker (configure properly for production) +ALLOWED_HOSTS = ['*'] + +# Static and media files +STATIC_ROOT = '/app/bluepages/static_root' +MEDIA_ROOT = '/app/bluepages/media_root' +MEDIA_URL = '/media/' diff --git a/bluepages/bluepages/settings.py b/bluepages/bluepages/settings.py index 8a2e826..e576c8a 100644 --- a/bluepages/bluepages/settings.py +++ b/bluepages/bluepages/settings.py @@ -200,4 +200,13 @@ from .local_settings import * except Exception as e: print("Unable to import local_settings") - pass \ No newline at end of file + pass + +# Import Docker settings if running in Docker +if os.environ.get('DOCKER_CONTAINER'): + try: + from .docker_settings import * + print("Docker settings loaded") + except Exception as e: + print(f"Unable to import docker_settings: {e}") + pass \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f60b141 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,48 @@ +version: '3.8' + +services: + db: + image: postgis/postgis:16-3.4 + container_name: bluepages_db + environment: + POSTGRES_DB: bluepages + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 10s + timeout: 5s + retries: 5 + + web: + build: . + container_name: bluepages_web + command: python manage.py runserver 0.0.0.0:8000 + volumes: + - .:/app + - static_volume:/app/bluepages/static_root + - media_volume:/app/bluepages/media_root + ports: + - "8000:8000" + environment: + - DOCKER_CONTAINER=1 + - DEBUG=True + - DB_NAME=bluepages + - DB_USER=postgres + - DB_PASSWORD=postgres + - DB_HOST=db + - DB_PORT=5432 + depends_on: + db: + condition: service_healthy + stdin_open: true + tty: true + +volumes: + postgres_data: + static_volume: + media_volume: From 538baa8ebee14aa26fe9feae825750c8e48235fe Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Fri, 6 Feb 2026 15:49:57 -0800 Subject: [PATCH 2/3] add entrypoint and load dump into db when first initialized --- Dockerfile | 7 +++++++ docker-compose.yml | 6 +++--- docker-entrypoint.sh | 17 +++++++++++++++++ init-db.sh | 12 ++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) create mode 100755 docker-entrypoint.sh create mode 100755 init-db.sh diff --git a/Dockerfile b/Dockerfile index 09c5dba..e0d9697 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,6 +34,10 @@ RUN pip install --upgrade pip && \ # Copy project files COPY . /app/ +# Copy and set entrypoint script +COPY docker-entrypoint.sh /app/ +RUN chmod +x /app/docker-entrypoint.sh + # Create necessary directories RUN mkdir -p /app/bluepages/static_root /app/bluepages/media_root @@ -43,5 +47,8 @@ WORKDIR /app/bluepages # Expose port EXPOSE 8000 +# Use entrypoint script +ENTRYPOINT ["/app/docker-entrypoint.sh"] + # Default command (can be overridden in docker-compose) CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] diff --git a/docker-compose.yml b/docker-compose.yml index f60b141..c2ff17b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,7 @@ -version: '3.8' - services: db: image: postgis/postgis:16-3.4 + platform: linux/amd64 container_name: bluepages_db environment: POSTGRES_DB: bluepages @@ -10,6 +9,8 @@ services: POSTGRES_PASSWORD: postgres volumes: - postgres_data:/var/lib/postgresql/data + - ./db_dump_20260204.sql:/tmp/db_dump.sql:ro + - ./init-db.sh:/docker-entrypoint-initdb.d/01-init-db.sh:ro ports: - "5432:5432" healthcheck: @@ -21,7 +22,6 @@ services: web: build: . container_name: bluepages_web - command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/app - static_volume:/app/bluepages/static_root diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100755 index 0000000..8d72cbf --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +echo "Waiting for PostgreSQL..." +while ! pg_isready -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" > /dev/null 2>&1; do + sleep 1 +done +echo "PostgreSQL is ready!" + +echo "Running database migrations..." +python manage.py migrate --noinput + +echo "Collecting static files..." +python manage.py collectstatic --noinput + +echo "Starting server..." +exec "$@" diff --git a/init-db.sh b/init-db.sh new file mode 100755 index 0000000..c74b90f --- /dev/null +++ b/init-db.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +# This script runs automatically when the PostgreSQL container is first initialized +# It will only run if the database is empty (first time setup) + +echo "Importing database dump..." + +# Import the SQL dump, ignoring meta-command errors +psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -v ON_ERROR_STOP=0 < /tmp/db_dump.sql + +echo "Database import completed!" From 35f34fe7de20d24eaa658e6ce806b765d51b6f27 Mon Sep 17 00:00:00 2001 From: Paige Williams Date: Fri, 6 Feb 2026 15:56:48 -0800 Subject: [PATCH 3/3] update docs --- README.docker.md | 235 +-------------------------------------------- docker-compose.yml | 2 +- 2 files changed, 6 insertions(+), 231 deletions(-) diff --git a/README.docker.md b/README.docker.md index 6b7b257..4a34db5 100644 --- a/README.docker.md +++ b/README.docker.md @@ -2,242 +2,17 @@ ## Quick Start -### 1. Build and start the containers: +### Pre-requisites -```bash -docker-compose up --build -``` +- Have a dump of the database called `db_dump.sql` in the `wcbluepages` directory. This is necessary to alter the tables to the expected form until the migrations work correctly. -### 2. Run initial setup (first time only): +### 1. Build and start the containers: ```bash -# Run migrations -docker-compose exec web python manage.py migrate - -# Create a superuser -docker-compose exec web python manage.py createsuperuser - -# Load fixtures -docker-compose exec web python manage.py loaddata app/fixtures/initial.json -docker-compose exec web python manage.py loaddata address/fixtures/initial.json - -# Collect static files -docker-compose exec web python manage.py collectstatic --noinput +docker-compose up --build ``` -### 3. Access the application: +### 2. Access the application: - Web application: http://localhost:8000 - Admin interface: http://localhost:8000/admin - -## Common Commands - -### Run management commands: - -```bash -# Run migrations -docker-compose exec web python manage.py migrate - -# Create a superuser -docker-compose exec web python manage.py createsuperuser - -# Collect static files -docker-compose exec web python manage.py collectstatic --noinput - -# Access Django shell -docker-compose exec web python manage.py shell - -# Run any Django management command -docker-compose exec web python manage.py -``` - -### Database operations: - -```bash -# Access PostgreSQL shell -docker-compose exec db psql -U postgres -d bluepages - -# Create database backup -docker-compose exec db pg_dump -U postgres bluepages > backup.sql - -# Restore database -docker-compose exec -T db psql -U postgres bluepages < backup.sql - -# Or restore from a dump file -cat backup.sql | docker-compose exec -T db psql -U postgres bluepages -``` - -### View logs: - -```bash -# All services -docker-compose logs -f - -# Specific service -docker-compose logs -f web -docker-compose logs -f db -``` - -### Stop containers: - -```bash -# Stop containers (keeps data) -docker-compose stop - -# Stop and remove containers (keeps volumes/data) -docker-compose down - -# Stop and remove containers + volumes (deletes database!) -docker-compose down -v -``` - -## Development Workflow - -### Hot Reloading - -The `web` service mounts your local code directory, so changes to Python files are reflected immediately thanks to Django's development server auto-reload. - -### Install New Python Packages - -1. Add package to `requirements.txt` -2. Rebuild the container: - -```bash -docker-compose up --build web -``` - -### Access Container Shell - -```bash -# Python/Django container -docker-compose exec web bash - -# Database container -docker-compose exec db bash -``` - -### Running Tests - -```bash -docker-compose exec web python manage.py test -``` - -## Troubleshooting - -### Container won't start - -```bash -# Check logs -docker-compose logs web -docker-compose logs db - -# Rebuild from scratch -docker-compose down -v -docker-compose up --build -``` - -### Database connection issues - -```bash -# Check if database is ready -docker-compose exec db pg_isready -U postgres - -# Check environment variables -docker-compose exec web env | grep DB_ - -# Verify database exists -docker-compose exec db psql -U postgres -l -``` - -### Permission issues with volumes - -```bash -# Fix permissions on mounted volumes -sudo chown -R $USER:$USER bluepages/static_root bluepages/media_root -``` - -### Reset everything - -```bash -# Remove all containers, volumes, and start fresh -docker-compose down -v -docker-compose up --build -``` - -## Production Deployment - -For production, create a `docker-compose.prod.yml`: - -```yaml -version: "3.8" - -services: - db: - image: postgis/postgis:16-3.4 - restart: always - environment: - POSTGRES_DB: bluepages - POSTGRES_USER: postgres - POSTGRES_PASSWORD: ${DB_PASSWORD} # Use .env file - volumes: - - postgres_data:/var/lib/postgresql/data - networks: - - internal - - web: - build: . - restart: always - command: gunicorn bluepages.wsgi:application --bind 0.0.0.0:8000 --workers 4 - volumes: - - static_volume:/app/bluepages/static_root - - media_volume:/app/bluepages/media_root - environment: - - DOCKER_CONTAINER=1 - - DEBUG=False - - DB_NAME=bluepages - - DB_USER=postgres - - DB_PASSWORD=${DB_PASSWORD} - - DB_HOST=db - - SECRET_KEY=${SECRET_KEY} - depends_on: - - db - networks: - - internal - - web - - nginx: - image: nginx:alpine - restart: always - ports: - - "80:80" - - "443:443" - volumes: - - ./nginx.conf:/etc/nginx/nginx.conf:ro - - static_volume:/app/static:ro - - media_volume:/app/media:ro - - ./ssl:/etc/nginx/ssl:ro - depends_on: - - web - networks: - - web - -networks: - internal: - web: - -volumes: - postgres_data: - static_volume: - media_volume: -``` - -Run with: `docker-compose -f docker-compose.prod.yml up -d` - -## Notes - -- PostgreSQL 16 with PostGIS 3.4 (matches Ubuntu 24.04) -- Python 3.11 (compatible with Django 3.2+) -- Development server runs on port 8000 -- Database runs on port 5432 (exposed for local tools) -- Code changes are live-reloaded in development -- Data persists in Docker volumes even when containers are stopped diff --git a/docker-compose.yml b/docker-compose.yml index c2ff17b..3878022 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: POSTGRES_PASSWORD: postgres volumes: - postgres_data:/var/lib/postgresql/data - - ./db_dump_20260204.sql:/tmp/db_dump.sql:ro + - ./db_dump.sql:/tmp/db_dump.sql:ro - ./init-db.sh:/docker-entrypoint-initdb.d/01-init-db.sh:ro ports: - "5432:5432"