Skip to main content

Docker Deployment Guide

This guide provides end-to-end instructions for deploying Scannersky using the containerized Docker Compose stack.

Docker Stack Architecture

The Docker deployment containerizes the full application stack into decoupled services:

ServiceContainer ImagePort / NetworkPurpose
djangoscannersky-django-django:latest8000 (Internal)Gunicorn WSGI app server running Django
postgrespostgres:165432 (Internal)PostgreSQL database with persistent volume postgres_data
miniominio/minio:latest9000 & 9001 (Internal)Object storage for media uploads and static assets
nginxnginx:1.27-alpine80 & 443 (Public)Reverse proxy, static/media asset router, SSL termination
mcpscannersky-django-mcp:latest8000 (Internal)Model Context Protocol HTTP server for AI assistant tools

Complete Start-to-End Docker Deployment

1. Host Prerequisites

Install Docker Engine 24+ and Docker Compose v2 on the host (Ubuntu/Debian):

sudo apt-get update && sudo apt-get install -y docker.io docker-compose-v2 git curl
sudo usermod -aG docker $USER
newgrp docker

2. Repository Setup

Private Repository Authentication: Since the repository is private, ensure your server is configured with an SSH Deploy Key or Personal Access Token before cloning. Refer to the dedicated Git Authentication Guide for complete setup options.

# Clone directly using SSH URL (recommended)
git clone -b docker/compose-migration git@github.com:codexcancerion/scannersky-django.git ~/scannersky-django
cd ~/scannersky-django

3. Environment Configuration (.env)

Run the automated environment initializer script to generate .env, populate secure random secret keys and passwords, and open the file in your terminal editor (nano / vi) for review:

bash ./deploy/scripts/setup-env.sh

What setup-env.sh does automatically:

  1. Copies .env.example to .env if .env does not already exist.
  2. Generates cryptographically secure random values for DJANGO_SECRET_KEY, DB_PASSWORD, and MINIO_ROOT_PASSWORD.
  3. Automatically opens .env in nano (or vi) so you can review or adjust DJANGO_ALLOWED_HOSTS and database names.

4. Stack Build & Launch

Build the Docker images and start the stack:

docker compose up -d --build

[!NOTE] The django container may temporarily show as unhealthy (with HTTP 503 in docker logs) after Step 4. This is expected because the required MinIO storage buckets have not been initialized yet. Proceed directly to Step 5 to provision the buckets, after which Django's health check will automatically turn healthy (200 OK).

5. MinIO Bucket Initialization & Container Startup

Provision MinIO buckets (scannersky-media and scannersky-static) and re-run docker compose up -d to start dependent containers (nginx and mcp) that were waiting for django health check:

bash ./deploy/scripts/setup-minio.sh
docker compose up -d

[!TIP] Running docker compose up -d right after setup-minio.sh starts nginx and mcp now that django is healthy. This binds Nginx to Ports 80 & 443 so the web interface becomes immediately accessible.

6. Documentation Build, Migrations & Static Collection

Build the Docusaurus static documentation and run in-container database migrations & static asset collection:

# Build Docusaurus static documentation for Nginx /docs/ endpoint
cd docusaurus && npm install && npm run build

# Run in-container database migrations and static asset collection
docker compose exec -T django python manage.py migrate --noinput
docker compose exec -T django python manage.py collectstatic --noinput

7. Data & Media Restoration (Optional / Migration)

If restoring database records or media files from a previous system installation, execute the unified restoration entrypoint:

# Run interactive restoration
# Defaults to ~/db_backups and ~/media_backups
# Ensure contents inside ~/db_backups and ~/media_backups before running the script
bash ./deploy/scripts/restore-docker.sh --all

Complete Backup & Restore Guide
For complete instructions on single-instance media backups, interactive database selection menus, and custom path overrides (DUMP_FILE and MEDIA_DIR), please refer to the dedicated Backup and Restore Guide.

8. HTTPS / Let's Encrypt Setup (Optional / Production Domains)

For domain deployments, ensure 40-ssl-check.sh has executable permissions and initialize Let's Encrypt SSL certificates:

# Ensure Nginx dynamic SSL check entrypoint is executable
chmod +x ./deploy/nginx/40-ssl-check.sh

# Provision SSL certificate and activate HTTPS on Port 443
bash ./deploy/scripts/init-letsencrypt.sh scan.kcp.edu.ph admin@kcp.edu.ph

How it works:

  1. Nginx serves HTTP on port 80 initially and handles the Let's Encrypt ACME challenge at /.well-known/acme-challenge/.
  2. init-letsencrypt.sh obtains certificates and places them in /etc/letsencrypt/live/<domain>/.
  3. deploy/nginx/40-ssl-check.sh detects the certificates upon Nginx container restart and automatically enables HTTPS termination on port 443!

9. Production Health Validation

Execute the production validation suite:

bash ./deploy/scripts/validate-production.sh

Dynamic SSL vs. HTTP-Only Mode

The Nginx container dynamically adapts based on SSL certificate presence:

  • HTTP-Only (Test/IP Deployment): If /etc/letsencrypt/live/scan.kcp.edu.ph/fullchain.pem is absent, Nginx serves HTTP on port 80 for any domain or IP without crashing.
  • HTTPS Mode: When SSL certificates exist, deploy/nginx/40-ssl-check.sh automatically enables SSL termination on port 443.

Routine Production Updates

To pull the latest code and update the container stack:

./deploy/scripts/update.sh

This script pulls latest git commits, rebuilds containers, applies migrations/collectstatic, reloads Nginx, and executes validate-production.sh.


Deployment Scripts Reference

  • deploy/scripts/setup-env.sh — Automated .env initializer & secret generator (opens editor automatically)
  • deploy/scripts/update.sh — Automated routine stack update
  • deploy/scripts/validate-production.sh — Post-cutover validation suite
  • deploy/scripts/backup-docker.sh — PostgreSQL container database backup
  • deploy/scripts/restore-docker.sh — Unified database & media restore entrypoint (supports --all, --db-only, --media-only)
  • deploy/scripts/restore-media.sh — Media backup importer to MinIO bucket (supports custom MEDIA_DIR)
  • deploy/scripts/setup-minio.sh — MinIO bucket provisioner