Deploying Django to DigitalOcean App Platform
Platform-as-a-Service (PaaS) removes the server management burden. DigitalOcean’s App Platform is a solid option for Django apps—simpler than Kubernetes, more flexible than Heroku.
Why App Platform?
- No server management: Just push code
- Auto-scaling: Handle traffic spikes
- Managed databases: PostgreSQL, Redis included
- Free tier: Great for prototypes
- GitHub integration: Deploy on push
Preparing Your Django App
requirements.txt
Django>=3.0,<4.0
gunicorn>=20.0
psycopg2-binary>=2.8
whitenoise>=5.0
dj-database-url>=0.5
python-decouple>=3.3
Settings Updates
# settings.py
from decouple import config
import dj_database_url
# Security
SECRET_KEY = config('SECRET_KEY')
DEBUG = config('DEBUG', default=False, cast=bool)
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='').split(',')
# Database
DATABASES = {
'default': dj_database_url.config(
default=config('DATABASE_URL')
)
}
# Static files
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
# Middleware
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # Add after SecurityMiddleware
# ... rest of middleware
]
Procfile (Optional but Recommended)
web: gunicorn myproject.wsgi --log-file -
runtime.txt
python-3.9
Creating a Managed Database
- Go to DigitalOcean → Databases
- Create a PostgreSQL cluster
- Note the connection details
Or let App Platform create one for you (easier).
Deploying to App Platform
1. Create App
From DigitalOcean control panel:
- Apps → Create App
- Select GitHub (authorize if needed)
- Choose your repository
- Select branch (usually
main)
2. Configure Resources
For a typical Django app:
Web Service:
- Type: Web Service
- Environment: Python
- Build Command:
pip install -r requirements.txt && python manage.py collectstatic --noinput - Run Command:
gunicorn myproject.wsgi --log-file - - HTTP Port: 8080
- Instance Size: Basic ($5/mo) for starters
3. Add Database
- Add Resource → Database → Dev Database (free)
- Or attach existing managed database
4. Configure Environment Variables
SECRET_KEY=your-secret-key-here
DEBUG=False
ALLOWED_HOSTS=${APP_DOMAIN}
The DATABASE_URL is automatically injected when you add a database.
5. Deploy
Click “Create Resources” and watch it build.
App Spec (For Reproducibility)
Create .do/app.yaml for version-controlled configuration:
name: myproject
services:
- name: web
github:
repo: username/myproject
branch: main
build_command: |
pip install -r requirements.txt
python manage.py collectstatic --noinput
python manage.py migrate
run_command: gunicorn myproject.wsgi --log-file -
http_port: 8080
instance_count: 1
instance_size_slug: basic-xxs
envs:
- key: SECRET_KEY
scope: RUN_TIME
value: ${SECRET_KEY}
- key: DEBUG
scope: RUN_TIME
value: "False"
- key: DJANGO_SETTINGS_MODULE
scope: RUN_AND_BUILD_TIME
value: myproject.settings
- key: DATABASE_URL
scope: RUN_TIME
value: ${db.DATABASE_URL}
databases:
- name: db
engine: PG
version: "13"
Deploy with:
doctl apps create --spec .do/app.yaml
Running Migrations
During Deployment
Add to build command:
pip install -r requirements.txt && python manage.py migrate && python manage.py collectstatic --noinput
Via Console
From App Platform:
- Select your app
- Console → Web →
python manage.py migrate
Custom Domains
- App Settings → Domains
- Add your domain
- Update DNS with provided records
- SSL is automatic (Let’s Encrypt)
Scaling
Horizontal Scaling
Increase instance count:
instance_count: 3
Vertical Scaling
Upgrade instance size:
instance_size_slug: professional-xs
Background Workers (Celery)
Add a worker service:
workers:
- name: celery-worker
github:
repo: username/myproject
branch: main
build_command: pip install -r requirements.txt
run_command: celery -A myproject worker -l info
instance_count: 1
instance_size_slug: basic-xxs
envs:
- key: CELERY_BROKER_URL
scope: RUN_TIME
value: ${redis.REDIS_URL}
Add Redis for the broker:
databases:
- name: redis
engine: REDIS
version: "6"
Monitoring and Logs
Logs
App Platform streams logs:
- DigitalOcean Console → Apps → Your App → Runtime Logs
Metrics
Built-in metrics for:
- CPU usage
- Memory usage
- Bandwidth
External Monitoring
Add Sentry for error tracking:
# settings.py
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
sentry_sdk.init(
dsn=config('SENTRY_DSN'),
integrations=[DjangoIntegration()],
traces_sample_rate=0.1,
)
Cost Optimization
- Dev databases: Free, good for staging
- Basic instances: Start here, scale up when needed
- Reserved capacity: Discounts for committed usage
- Staging apps: Use separate apps, not separate resources
Final Thoughts
App Platform hits a sweet spot between Heroku’s simplicity and raw VPS flexibility. For Django projects, it’s a solid choice.
Deploy with GitHub integration. Start with the free tier. Scale when traffic demands it.
Focus on code, not servers.