Deploying Django + Postgres to Oracle Cloud

Project #125 of 10 in "Production-grade apps" progression
Python Shell
Deploying Django + Postgres to Oracle Cloud thumbnail

Updated: Oct 09, 2026

Learning plan

    1. Gunicorn
    2. Production settings / environment separation
    3. .env contracts: .exampe, .dev.example, .prod.example
    4. SECRET_KEY
    5. DEBUG
    6. ALLOWED_HOSTS
    7. CSRF_TRUSTED_ORIGINS
    8. DATABASE_URL / PostgreSQL settings
    9. Storage settings
    10. OAuth credentials
    11. Dev-only auto-reload
    12. Static files with collectstatic (make command)
    13. Media storage abstraction
    14. Local filesystem storage in dev / prod
    15. OCI Object Storage and Docker bind mount in production
    1. What's Docker?
    2. Docker images & containers
    3. .dockerignore file
    4. Dockerfile
    5. Compose.yml file: base, dev, prod
    6. Django service: web
    7. PostgreSQL service: db
    8. Persistent PostgreSQL volume
    9. .env
    10. Docker commands: ps, images, run, start, stop, restart, pull, rm
    11. Make commands: migrate, collectstatic
    12. Shell commands inside containers
    1. GitHub Actions workflow: CI.yml file
    2. Django tests: seeding, healthcheck, unit tests
    3. Act for local workflow tests
    4. Local db, lint and type checks on Railway deploys
    1. OCI setup: creating instance and subnet
    2. Security lists / network security rules (ingress, reserved IP)
    3. SSH into VM: public and private keys, git aliases
    4. Installing Docker: etc folder, GPG keys, group permission
    5. Secure copy files over SSH: scp, .env. compose.yml
    6. Prepare host directories: staticfiles, media
    1. DNS type A record
    2. Fighting firewall: iptables, netfilter-persistent
    3. Configuring Nginx: .conf file
    4. Installing TLS certificates uisng certbot
    5. Google sign in: update OAuth callback URLs 
    6. Django settings: secure cookies, ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS, HSTS
    7. Verify HTTPS
    1. Build Docker image
    2. Tag Docker image
    3. Push image to container registry
    4. Configure GitHub secrets
    5. Configure SSH authentication
    6. Create server-side deploy.sh
    7. SSH into OCI VM
    8. Pull new image
    9. docker compose up -d
    10. Run migrations
    11. Run collectstatic
    12. Run health check
    13. Fail deployment if health check fails
    1. Create Object Storage bucket
    2. Configure bucket/access policy
    3. Configure boto3
    4. Configure production bucket credentials
    5. Upload media
    6. Verify Django can read/write media
    7. Verify media is not stored inside the Docker container
    1. Create production .env
    2. Pull/build application image
    3. Start Docker Compose
    4. Run migrations
    5. Run collectstatic
    6. Check Django logs
    7. Check PostgreSQL
    8. Check media storage
    9. Restart containers and verify persistence
    1. Tag images with versions
    2. Keep previous image available
    3. Know how to deploy previous image
    4. Test rollback manually