How to setup Django + Postgres + Node.js with Docker
Tags: django, postgres, docker, node
Published: 2023-09-09 16:15:49


Many Django developers aspire to integrate Tailwind CSS into their projects, but they often find the process a bit complex. In this tutorial, we'll guide you through the steps to seamlessly incorporate Tailwind CSS into your Django project without any hassle.

Our primary goal in this tutorial is to replace the default `db.sqlite` database provided by Django with PostgreSQL for development purposes. Additionally, we'll show you how to containerize your entire project using Docker, making collaboration and deployment a breeze.

## Prerequisites

Before we dive into the tutorial, ensure that you have the following tools and technologies installed on your computer:

- [Docker](https://docs.docker.com/engine/install/)
- [docker-compose](https://docs.docker.com/compose/install/)
- [PostgreSQL](https://www.postgresql.org/download/)
- [Django](https://docs.djangoproject.com/en/3.2/topics/install/)
- [Node.js](https://nodejs.org/en/download/)

If you haven't installed these dependencies yet, you can find installation instructions on their respective websites.

Now, with the prerequisites in place, let's proceed with the tutorial.

## Setting up PostgreSQL with Django Using Environment Variables

To ensure a secure and flexible configuration, we'll use environment variables (env files) to manage sensitive database settings, such as credentials and connection details.

### Step 1: Create a PostgreSQL Database

First, let's create a PostgreSQL database for your Django project. Open a terminal and run the following command, replacing `mydb` with your desired database name:

```bash
createdb mydb
```

Confirm your db was created successfully by running:

```bash
psql -U your_username -l
```

### Step 2: Install the Required Python Packages
To work with PostgreSQL in Django and load environment variables from a `.env` file, you'll need the `psycopg2-binary` and `python-dotenv` packages. Install them using `pip`:

```bash
pip install psycopg2-binary python-dotenv
```

### Step 3: Configure Django to Use PostgreSQL with python-dotenv
Now, let's configure your Django project to use PostgreSQL as the database while loading sensitive settings from a `.env` file.

1. Create a `.env` file in your project's root directory (if it doesn't already exist).
2. Add the following environment variables to your `.env` file, replacing the placeholders with your actual PostgreSQL credentials. I will be using the default postgres database which the need to create one.

```ini
SECRET_KEY="your_django_secret_key"
DB_ENGINE=django.db.backends.postgresql
DB_NAME=postgres
DB_USER=postgres
DB_PASSWORD=postgres
DB_HOST=db # Make sure your DB_HOST is set to just "db" without the quote. We will understand why after we set up docker
DB_PORT=5432
DEBUG=True
```
3. Next, open your Django project's settings file (usually `settings.py`) and configure the database settings using `python-dotenv`:

Your default DATABASE will look like this
```python
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
```

Delete it and replace it with this:
```python
import os
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

# Move the code above to the top of your settings.py file

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('DB_NAME'),
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': os.environ.get('DB_HOST'),
        'PORT': os.environ.get('DB_PORT', default='5432'),
    }
}
```

With these changes, your Django project will now use the environment variables defined in the `.env` file to connect to the PostgreSQL database while keeping sensitive information secure.

## Setting up PostgreSQL + Django with Docker

In this guide, we'll walk you through the process of setting up PostgreSQL and Django within Docker containers, making it easy to manage and collaborate on your project. Additionally, we'll include instructions for integrating Tailwind CSS if needed.

## Step 1: Create Docker Configuration Files

In your project root directory, create two files named `docker-compose.yml` and `Docker`.

### `docker-compose.yml`

```yaml
version: '3'

services:
  db:
    image: postgres
    ports:
      - "5432:5432"
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}

  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/usr/src/app
    ports:
      - '8000:8000'
    depends_on:
      - db
```

### `Docker`

```docker
FROM python:3.9
ENV PYTHONUNBUFFERED 1

# set working directory
WORKDIR /usr/src/app

# Copy and install Python dependencies
COPY requirements.txt /usr/src/app/
RUN pip install -r requirements.txt

# Copy Node.js-related files (for Tailwind CSS integration)
COPY package.json /usr/src/app/
COPY package-lock.json /usr/src/app/

# Install Node.js dependencies (for Tailwind CSS integration)
RUN apt update && apt install -y nodejs npm
RUN npm install

# Copy the rest of your application
COPY . /usr/src/app/
```

**Note**: If you don't intend to use Tailwind CSS, you can remove the lines that copy package.json and `package-lock.json`, as well as the lines that `update` and `install npm`.

If you however intend to use tailwindcss and you haven't set it up yet, you can read my article on [How to setup TailwindCSS with Django](https://dev.to/jazzdev/setting-up-tailwindcss-with-django-easy-guide-2o6j). 

## Step 2: Build and Run Docker Containers
With the Docker configuration files in place, you can now build and run your Docker containers:

```bash
docker-compose build
docker-compose up
```

Your Django application will be accessible at `http://localhost:8000`.

If after running `docker-compose up` you get an error like:

```python
django.db.utils.OperationalError: connection to server at "db" (172.26.0.2), port 5432 failed: Connection refused
xproject-web-1  |       Is the server running on that host and accepting TCP/IP connections?
```

Step to fix:
1. **Check PostgreSQL Service Status**: Verify if the PostgreSQL service is running by using the following command:

```bash
sudo service postgresql status
```

If the service is not running, you can start it with:

```bash
sudo service postgresql start
```

2. **Check Listen Addresses**: In the `postgresql.conf` file, there's a configuration parameter called `listen_addresses`. Ensure that it's set to listen on the appropriate IP addresses or is set to `'*'`, which allows connections from any IP address:

```bash
sudo nano /etc/postgresql/<version>/main/postgresql.conf
```

Replace `<version>` with your postgresql version. Enter only the whole number of your version. If you version is `15.4`, replace `<version>` with only `15` You can check your version with:

```bash
psql --version
```

If you encounter other errors, you can drop me a comment and i will be happy to help.

## Conclusion
You've successfully set up PostgreSQL and Django within Docker containers, allowing for easy management and collaboration. If you're using Tailwind CSS, the Docker configuration includes the necessary setup to integrate it into your project. Now you can focus on developing your Django application with a containerized environment.

Happy coding!