Pages

Deploying High-Performance Django on Coolify


Part 1: Initial Setup in Coolify Dashboard

Step 1: Accessing Coolify

  1. Open your browser and navigate to your Coolify instance (e.g., https://coolify.yourdomain.com)
  2. Log in with your credentials
  3. You'll see the main dashboard with "Projects" and "Resources" sections

Step 2: Creating a New Project

  1. Click the "New Project" button in the top right corner
  2. Fill in the form:
    • Name: "Django-High-Performance"
    • Description: "High-performance Django application with PostgreSQL"
    • Click "Create Project"

Step 3: Setting up PostgreSQL Database

  1. In your project, click "New Resource"
  2. Select "Database" from the resource types
  3. Choose "PostgreSQL"
  4. Fill in the configuration:
    Name: postgres-main
    Version: 15
    Username: django_user
    Password: [generate a secure password]
    Database Name: django_db
    Port: 5432
  5. Under "Advanced Settings":
    Memory Limit: 12288 (12GB in MB)
    CPU Limit: 4
  6. Click "Create Database"
  7. After creation, click on the database resource
  8. Go to "Settings" tab
  9. Under "Configuration", add these settings:
    max_connections = 200
    shared_buffers = 4GB
    effective_cache_size = 12GB
    maintenance_work_mem = 1GB
  10. Click "Save Configuration" and "Restart Database"

Step 4: Setting up PgBouncer

  1. Click "New Resource"
  2. Select "Service" → "Docker"
  3. Configuration:
    Name: pgbouncer
    Image: edoburu/pgbouncer:1.18.0
    Port: 6432
  4. Click "Add Volume" and add:
    Host Path: /data/pgbouncer/pgbouncer.ini
    Container Path: /etc/pgbouncer/pgbouncer.ini
  5. Add another volume:
    Host Path: /data/pgbouncer/userlist.txt
    Container Path: /etc/pgbouncer/userlist.txt
  6. Under "Environment Variables", add:
    DB_HOST=postgres-main
    DB_PORT=5432
    DB_USER=django_user
    DB_PASSWORD=[your-postgres-password]
  7. Click "Create Service"

Step 5: Setting up Redis

  1. Click "New Resource"
  2. Select "Database" → "Redis"
  3. Configure:
    Name: redis-cache
    Version: 7
    Password: [generate secure password]
    Memory Limit: 4096 (4GB in MB)
    CPU Limit: 2
  4. Click "Create Redis"

Part 2: Preparing Your Application

Step 1: Project Files Setup

Create these files in your Django project:

Dockerfile:

FROM python:3.11-slim

ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1

WORKDIR /app

RUN apt-get update && apt-get install -y \
    build-essential \
    postgresql-client \
    libpq-dev \
    && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt \
    gunicorn[gevent] \
    redis \
    hiredis \
    django-redis \
    psycopg2-binary

COPY . .

RUN python manage.py collectstatic --noinput

RUN useradd -m myuser
RUN chown -R myuser:myuser /app
USER myuser

CMD ["gunicorn", "--config", "gunicorn.conf.py", "core.wsgi:application"]

gunicorn.conf.py:

import multiprocessing

workers = multiprocessing.cpu_count() * 2 + 1
worker_class = 'gevent'
worker_connections = 1000
timeout = 30
keepalive = 2
max_requests = 1000
max_requests_jitter = 200
preload_app = True
bind = "0.0.0.0:8000"

# Logging
accesslog = '-'
errorlog = '-'
loglevel = 'info'

Step 2: Update Django Settings

Update settings.py:

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
DEBUG = os.getenv('DJANGO_DEBUG', 'False') == 'True'
ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '').split(',')

# Database
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.getenv('POSTGRES_DB'),
        'USER': os.getenv('POSTGRES_USER'),
        'PASSWORD': os.getenv('POSTGRES_PASSWORD'),
        'HOST': os.getenv('POSTGRES_HOST'),
        'PORT': os.getenv('POSTGRES_PORT'),
        'CONN_MAX_AGE': 0,
    }
}

# Cache
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': os.getenv('REDIS_URL'),
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'PARSER_CLASS': 'redis.connection.HiredisParser',
            'CONNECTION_POOL_CLASS_KWARGS': {
                'max_connections': 50,
                'timeout': 20,
            }
        }
    }
}

# Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'

Part 3: Deploying the Application

Step 1: Creating the Application Service

  1. In Coolify dashboard, click "New Resource"
  2. Select "Application" → "Docker"
  3. Select your Git repository
  4. Configure Build:
    Branch: main (or your preferred branch)
    Dockerfile Path: ./Dockerfile
    Port: 8000
  5. Under "Advanced Settings":
    Memory Limit: 8192 (8GB in MB)
    CPU Limit: 8
    Instance Count: 2

Step 2: Environment Variables

  1. Click on "Environment Variables"
  2. Add the following (click "Add" after each):
    # Django
    DJANGO_SECRET_KEY=[generate a secure key]
    DJANGO_DEBUG=False
    DJANGO_ALLOWED_HOSTS=your-domain.com
    DJANGO_CSRF_TRUSTED_ORIGINS=https://your-domain.com
    
    # Database
    POSTGRES_DB=django_db
    POSTGRES_USER=django_user
    POSTGRES_PASSWORD=[your-postgres-password]
    POSTGRES_HOST=pgbouncer
    POSTGRES_PORT=6432
    
    # Redis
    REDIS_URL=redis://:[redis-password]@redis-cache:6379/0
    
    # Port
    PORT=8000

Step 3: Network Configuration

  1. Go to "Network" tab
  2. Click "Add to Network"
  3. Select the network containing your database and Redis
  4. Click "Add"

Step 4: Initial Deployment

  1. Click "Deploy" button
  2. Watch the build logs (click "View Logs")
  3. Wait for the build to complete

Step 5: Database Migration

  1. After successful deployment, click "Terminal"
  2. Run:
    python manage.py migrate
    python manage.py createsuperuser

Part 4: Post-Deployment Configuration

Step 1: Domain Setup

  1. Go to "Settings" tab
  2. Under "Domains", click "Add Domain"
  3. Enter your domain
  4. Enable "HTTPS/SSL"
  5. Choose "Let's Encrypt"
  6. Click "Add Domain"

Step 2: Monitoring Setup

  1. Go to "Monitoring" tab
  2. Enable "Resource Monitoring"
  3. Configure alerts:
    • Click "Add Alert"
    • Set CPU Usage > 80%
    • Add email notification
  4. Repeat for:
    • Memory Usage > 80%
    • Error Rate > 1%

Common Issues and Solutions

Problem 1: Database Connection Failed

If you see "could not connect to database" errors:

  1. Check network connectivity:
    # In application terminal
    nc -zv pgbouncer 6432
  2. Verify environment variables:
    # In application terminal
    env | grep POSTGRES
  3. Check PgBouncer logs:
    • Go to PgBouncer service
    • Click "Logs"

Problem 2: Redis Connection Issues

If cache errors occur:

  1. Verify Redis connection:
    # In Django shell
    from django.core.cache import cache
    cache.set('test', 'working')
    cache.get('test')
  2. Check Redis URL format
  3. Verify network connectivity

Problem 3: Static Files Not Loading

  1. Check STATIC_ROOT setting
  2. Run collectstatic again:
    python manage.py collectstatic --clear --noinput
  3. Verify whitenoise configuration

Performance Monitoring

Step 1: Database Monitoring

Run these queries in PostgreSQL:

-- Current connections
SELECT count(*) FROM pg_stat_activity;

-- Connection states
SELECT state, count(*) 
FROM pg_stat_activity 
GROUP BY state;

-- Slow queries
SELECT pid, age(clock_timestamp(), query_start), usename, query 
FROM pg_stat_activity 
WHERE state != 'idle' 
  AND query NOT ILIKE '%pg_stat_activity%' 
ORDER BY query_start desc;

Step 2: Application Monitoring

  1. Check Gunicorn workers:
    # In application terminal
    ps aux | grep gunicorn
  2. Monitor request latency:
    • Go to "Metrics" tab
    • Look for "Request Duration"
    • Check "95th percentile" latency

No comments:

Post a Comment