Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save enoren5/8dc4467690171b2b75e8fd1896a3f8ed to your computer and use it in GitHub Desktop.
Save enoren5/8dc4467690171b2b75e8fd1896a3f8ed to your computer and use it in GitHub Desktop.
Deploying Django projects to Heroku with Docker and Nix

This approach allows you to run the Django application on NixOS while still having the flexibility to deploy it on Heroku (or other cloud platforms) if needed.

Step-by-Step: Dockerizing the Django App

1. Install Docker on NixOS

First, install the enviornment on NixOS. To do this, you can add the following to your NixOS configuration (/etc/nixos/configuration.nix):

{
  virtualisation.docker.enable = true;
}

Then, run sudo nixos-rebuild switch to apply the changes.

2. Prepare the Django Application

Assuming your you already have a Django project with a requirements.txt (or pyproject.toml for newer versions), you need to make sure the project is ready for containerization.

The basic structure of a Django project looks like this:

my-django-app/
├── manage.py
├── myapp/
├── requirements.txt
└── other_project_files/

3. Create a Dockerfile

In the root of the Django project (my-django-app/), create a Dockerfile. This file tells Docker how to build the container image. Here's a basic Dockerfile for Django with Gunicorn as the application server and a PostgreSQL database.

# Use an official Python runtime as a parent image
FROM python:3.9-slim

# Set the working directory in the container
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# Install any needed dependencies specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Expose the port the app runs on
EXPOSE 8000

# Define environment variable for Django to allow all hosts
ENV DJANGO_ALLOWED_HOSTS=*

# Run the Django development server (or use Gunicorn in production)
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "myproject.wsgi:application"]

This Dockerfile does the following:

  • Starts with the official Python 3.9 slim image.
  • Sets /app as the working directory.
  • Copies the Django project files into the container.
  • Installs dependencies using pip from the requirements.txt.
  • Exposes port 8000, which is the default port for Django’s development server (and for Gunicorn).
  • Sets an environment variable DJANGO_ALLOWED_HOSTS to allow any host (for development purposes).
  • Runs the Django app using Gunicorn (which is more production-ready than Django’s default development server).

4. Build the Docker Image

Once the Dockerfile is in place, you can build the Docker image. Open a terminal in the root of the Django project and run:

docker build -t my-django-app .

This will create a Docker image tagged my-django-app.

5. Run the Docker Container Locally

After the image is built, you can run the container locally to test it:

docker run -p 8000:8000 my-django-app

This will run the Django app inside the Docker container and map port 8000 from the container to port 8000 on the host machine. You can then access the Django app by going to http://localhost:8000.

6. Docker Compose (Optional for Multi-Container Setup)

If your Django app uses a database (e.g., PostgreSQL), you can use Docker Compose to define multiple services (like Django and PostgreSQL) in a single configuration. Create a docker-compose.yml file:

version: '3'

services:
  db:
    image: postgres:13
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: mypassword
      POSTGRES_DB: mydatabase
    volumes:
      - pgdata:/var/lib/postgresql/data

  web:
    build: .
    command: gunicorn --bind 0.0.0.0:8000 myproject.wsgi:application
    volumes:
      - .:/app
    ports:
      - "8000:8000"
    depends_on:
      - db

volumes:
  pgdata:

This docker-compose.yml defines two services:

  • db: The PostgreSQL database.
  • web: The Django app, built from the local directory (.).

You can start the services with:

docker-compose up

This will bring up both the database and Django app. The app will be accessible on http://localhost:8000.

7. Deploying to Heroku

If you still wants to deploy to Heroku, you can use Docker to push your app to Heroku. Here’s how to do it:

  1. Install Heroku CLI (if not already installed).

  2. Login to Heroku via the command line:

    heroku login
  3. Create a Heroku app (if not already created):

    heroku create my-django-app
  4. Push the Docker container to Heroku:

    heroku container:login
    heroku container:push web --app my-django-app
    heroku container:release web --app my-django-app

This will push the Docker container to Heroku and release it as a web app.

8. Set Up Django for Production

Before deploying to production (either locally or on Heroku), you should make sure the Django app is ready for production. This includes:

  • Setting up the ALLOWED_HOSTS in the settings.py file (e.g., ALLOWED_HOSTS = ['*'] for testing or specific domains for production).
  • Configuring a production database (like PostgreSQL on Heroku or another external database).
  • Running python manage.py collectstatic to gather static files.
  • Setting up environment variables for secrets like the Django SECRET_KEY, database credentials, etc.
  • Using Gunicorn or another WSGI server to run the app instead of the default Django development server.

Summary

This approach allows you to easily containerize your Django app and run it locally on NixOS while maintaining flexibility for deployment on platforms like Heroku or others. The Docker container ensures the environment is consistent across all stages of development and production.

Would you like to explore any of the steps in more detail or have specific questions about this process?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment