Deploy Django on Bahriya

Django is a batteries-included Python web framework. In production you run it behind a WSGI server rather than the development server — gunicorn is the usual choice, listening on port 8000. This guide packages a Django project as a container image and deploys it as an HTTP container.

Updated 3 Aug 20263 min read

Django is a batteries-included Python web framework. In production you run it behind a WSGI server rather than the development server — gunicorn is the usual choice, listening on port 8000. This guide packages a Django project as a container image and deploys it as an HTTP container.

Only two things change between stacks on Bahriya: the Dockerfile that builds your image, and the port your application listens on. For Django served by gunicorn, that port is 8000.

Dockerfile

This builds on the slim Python base image, installs your requirements, collects static files, and starts gunicorn bound to 0.0.0.0:8000 so the platform can reach it.

FROM python:3.12-slim
 
ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1
 
WORKDIR /app
 
# Install dependencies first so they cache across builds
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
 
# Copy the project
COPY . .
 
# Collect static assets at build time
RUN python manage.py collectstatic --noinput
 
EXPOSE 8000
 
# Replace "myproject" with your project's WSGI module
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "3"]

Make sure gunicorn is listed in your requirements.txt. Django logs to standard output by default, which is what the platform captures.

Application settings

A few settings need attention before you deploy:

  • ALLOWED_HOSTS — add your container's hostname. Your default hostname follows the pattern <handle>.<region>.x.on.bahriya.app, and you can allow all of them with a suffix entry such as .on.bahriya.app, plus any custom domain you configure.
  • collectstatic — the Dockerfile above runs it at build time so your static files ship inside the image. Set STATIC_ROOT in your settings accordingly.
  • DEBUG — set it to False in production, driven by an environment variable.

Deploy from the Console

  1. Create (or open) a project, then create a container.
  2. Set the image to your pushed image reference, and the port to 8000.
  3. Set a health check path the app answers with a 2xx — a lightweight view such as /healthz works well.
  4. Choose your regions, set CPU and memory, and attach any secrets.
  5. Create the container and wait for it to reach a running state.

See Deploy your first container for the full walkthrough.

Deploy with the Reis CLI

reis container:create \
  --type http \
  --name "Django App" \
  --handle django-app \
  --image ghcr.io/myorg/django-app:v1.0.0 \
  --project my-project \
  --port 8000 \
  --healthcheck /healthz \
  --cpu 500 \
  --memory 512 \
  --regions falkenstein-1 \
  --env DJANGO_SETTINGS_MODULE=myproject.settings \
  --secrets SECRET_KEY=django-secret-key \
  --secrets DATABASE_URL=database-url

See Deploy an HTTP container with flags for the full flag reference.

Configuration, secrets, and databases

  • Non-sensitive configuration — pass values such as DJANGO_SETTINGS_MODULE or feature flags as plain environment variables.
  • Sensitive values — your SECRET_KEY, database password, and any API keys belong in secrets. They are encrypted at rest and injected as environment variables at runtime. Read them in settings.py with os.environ.
  • Database connections — point Django at your managed database using a connection URL or discrete host/user/password values, supplied through secrets. Bahriya does not host your database; connect to whichever database you run.

Running migrations

Run python manage.py migrate as a one-off before or after a deploy rather than inside your web process. Bahriya supports init jobs — short-lived containers that run to completion — which are a natural fit for migrations. They use the same image as your web container with a different command (python manage.py migrate). See HTTP containers for how container types relate.

Next steps