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..e0d9697 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,54 @@ +# 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/ + +# 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 + +# Set working directory to Django project +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/README.docker.md b/README.docker.md new file mode 100644 index 0000000..4a34db5 --- /dev/null +++ b/README.docker.md @@ -0,0 +1,18 @@ +# Docker Setup for WC Bluepages + +## Quick Start + +### Pre-requisites + +- 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. + +### 1. Build and start the containers: + +```bash +docker-compose up --build +``` + +### 2. Access the application: + +- Web application: http://localhost:8000 +- Admin interface: http://localhost:8000/admin 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..3878022 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,48 @@ +services: + db: + image: postgis/postgis:16-3.4 + platform: linux/amd64 + container_name: bluepages_db + environment: + POSTGRES_DB: bluepages + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + volumes: + - postgres_data:/var/lib/postgresql/data + - ./db_dump.sql:/tmp/db_dump.sql:ro + - ./init-db.sh:/docker-entrypoint-initdb.d/01-init-db.sh:ro + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 10s + timeout: 5s + retries: 5 + + web: + build: . + container_name: bluepages_web + 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: 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!"