Deploy Django on Divio
Deploy Django on Divio, a cloud platform built around Django and Docker: structure the project for Divio’s Dockerfile, read DEFAULT_DATABASE_DSN and storage DSNs, configure release commands for migrations, and promote changes from test to live environments.
Problem statement
You want a managed platform where Django is the expected workload rather than one runtime among many, with separate test and live environments, managed PostgreSQL and media storage, and a local development setup that matches the cloud. Divio is built around exactly that: every project is a Docker image, services are attached per environment, and their connection details arrive as DSN environment variables your settings read.
- Create the project in the Divio Control Panel, choosing a Django template or importing your repository.
- Keep a
Dockerfilethat installs requirements and runscollectstatic; Divio builds it on deploy. - Read services from environment variables:
DEFAULT_DATABASE_DSNfor PostgreSQL,DEFAULT_STORAGE_DSNfor media storage, plusDOMAINandDOMAIN_ALIASES. - Add
python manage.py migrateas a release command so it runs before new containers take traffic. - Deploy to the test environment, check it, then deploy the same commit to live.
Step-by-step solution
1. Set up the project and local environment
Install the Divio CLI and pull the project locally:
pip install divio-cli
divio login
divio app setup shop
cd shop && docker compose up
The local setup uses Docker Compose with a database container, so development matches the cloud image. Push code to the project's Git remote (Divio's own, or a connected GitHub or GitLab repository).
2. Write settings that read Divio's variables
import os
import dj_database_url
SECRET_KEY = os.environ["SECRET_KEY"]
DEBUG = os.environ.get("DEBUG", "false").lower() == "true"
DATABASES = {"default": dj_database_url.parse(os.environ["DEFAULT_DATABASE_DSN"], conn_max_age=60)}
DOMAIN = os.environ.get("DOMAIN", "localhost")
ALLOWED_HOSTS = [DOMAIN] + [d for d in os.environ.get("DOMAIN_ALIASES", "").split(",") if d]
CSRF_TRUSTED_ORIGINS = [f"https://{h}" for h in ALLOWED_HOSTS if h != "localhost"]
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
Check the Control Panel's environment variable list for your project: Divio documents the variables its services provide, and newer projects may expose additional ones.
3. Configure media storage
DEFAULT_STORAGE_DSN describes an S3-compatible bucket, typically in the form s3://KEY:SECRET@bucket.endpoint/?domain=.... Parse it into django-storages options:
from urllib.parse import urlparse, parse_qs
dsn = urlparse(os.environ["DEFAULT_STORAGE_DSN"])
STORAGES = {
"default": {
"BACKEND": "storages.backends.s3.S3Storage",
"OPTIONS": {
"access_key": dsn.username,
"secret_key": dsn.password,
"bucket_name": dsn.hostname.split(".", 1)[0],
"endpoint_url": f"https://{dsn.hostname.split('.', 1)[1]}",
"custom_domain": parse_qs(dsn.query).get("domain", [None])[0],
},
},
"staticfiles": {"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"},
}
Adjust the parsing to the exact DSN format your project shows; providers differ slightly. Static files can be collected at build time and served with WhiteNoise.
4. Add release commands
In the Control Panel, under the environment's release commands, add:
python manage.py migrate --noinput
Release commands run in a container with the new image after the build and before the new version receives traffic. A failing command aborts the deployment.
5. Promote from test to live
Deploy the branch to the test environment, check it, then deploy the same commit to live, from the Control Panel or the CLI:
divio app deploy test
divio app deploy live
Copy live data to test (divio app pull db live locally, or environment copy features) when you need realistic testing, and anonymize personal data.
Explanation
Divio runs every project as a Docker image built from your Dockerfile, so there is no buildpack magic to work around and the same image runs locally, in test, and in live. Services such as PostgreSQL, storage, and caches are provisioned per environment and described to the app through DSN variables, which keeps credentials out of the code. The release command step is the platform's hook for work that must happen once per deploy, before traffic moves.
Edge cases / notes
- Legacy Aldryn projects. Older Divio projects used the Aldryn addons framework for settings; newer projects use plain Django settings reading environment variables.
- Workers. Celery requires a worker service on supported plans; check what your subscription includes.
- Build-time settings.
collectstaticruns during the image build without service variables, so settings must import without them.
Next steps
- Compare platforms in Alternatives to Heroku for Hosting Django.
- Use the test environment well with Set Up a Django Staging Environment.
- Review media configuration in Store Django Media Files on S3.
FAQ
Is Divio only for Django?
It supports other stacks, but it was built around Django and its tooling and templates reflect that.
How do I run migrations on Divio?
Add python manage.py migrate --noinput as a release command for each environment.
Where does the database URL come from?
From DEFAULT_DATABASE_DSN, set by the database service for each environment.
Can I develop locally with the same setup?
Yes. The Divio CLI sets up a local Docker Compose environment that matches the cloud image.