2

How to dockerize a Django, Preact, and PostgreSQL Application

 6 months ago
source link: https://www.honeybadger.io/blog/dockerize-django-preact-postgres/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

During my recent deep dive into new technologies, I found the classic issues of integrating numerous tech tools effectively. I've written about my experiences to save you the trouble I had.

One essential component I've looked into is using Docker to implement containerization. While the initial setup takes a little longer, it significantly simplifies and optimizes your technological stack.

Prerequisites

To follow along with this tutorial, make sure you have the following:

We'll start a Django application and then a Preact application, containerize them both, run the containers, and then create an API to ensure the stack works correctly.

Getting started

To start, create an empty folder; we'll name ours django-preact-docker and navigate to this folder from the terminal.

We'll follow the first steps of creating a Django application - creating a virtual environment, activating it, and then installing Django.

(If virtualenv is not installed, run pip install virtualenv)

Run these commands in the terminal:

virtualenv venv
source ./venv/bin/activate

Then, with our virtual environment running, install Django along with some other dependencies:

pip install django django-cors-headers psycopg2-binary

Now, we can create a new Django project and get it running on our local server.

“Everyone is in love with Honeybadger ... the UI is spot on.”
molly.jpg?1708454009Molly Struve, Sr. Site Reliability Engineer, Netflix
Start free trial

Setting Up Django

From the terminal, navigate to django-preact-docker, and run:

django-admin startproject backend

The above command creates a new folder, backend. Navigate into this folder:

cd backend

And then start the project:

python manage.py runserver

You can test if the server is running by going to: http://127.0.0.1:8000/

a screenshot showing the successful test server

Finally, create a requirements file that will hold our requirements for the project. While in django-preact-docker/backend, run:

pip freeze > requirements.txt

Setting up our Preact application

Head back to our root folder django-preact-docker.

In the terminal, run:

npm init preact

When prompted, change the project directory to "frontend," then hit enter for the rest of the options.

Once installed, from the terminal, navigate into django-preact-docker/frontend and run the following command to set up a development server:

npm run dev

Once the server has started, it will print a local development URL to open in your browser. Check if this is working before moving on!

a screenshot showing a successful precat response

Containerizing

Next, we must create configuration files, so Docker knows what to do.

Get Honeybadger's best Python articles in your inbox

We publish 1-2 times per month. Subscribe to get our Python articles as soon as we publish them.

We're Honeybadger. We'll never send you spam; we will send you cool stuff like exclusive content, memes, and swag.

Containerize Django

Navigate to django-preact-docker/backend and create a new file:

touch .dockerignore

Open the file and add the following:

# The file may be hidden on Finder; the default macOS shortcut is Shift-Command-. to show hidden files
venv
env
.env
Dockerfile

Next, run:

touch Dockerfile

Open it and add:

FROM python:3.8-alpine

ENV PYTHONUNBUFFERED 1

WORKDIR /app/backend

COPY requirements.txt /app/backend/

RUN apk add --update --no-cache postgresql-dev gcc python3-dev musl-dev

RUN pip install -r requirements.txt

COPY . .

CMD [ "python", "manage.py", "runserver", "0.0.0.0:8000" ]

In the above code:

  • FROM specifies the parent image that we'll be using
  • ENV sets the environment variable PYTHONUNBUFFERED to "1" to give us real-time log output.
  • WORKDIR specifies the working directory within the container.
  • COPY the requirements file to the working directory and later install the requirements.
  • RUN, install some more dependencies for psycopg-2,
  • COPY the content of our backend to the Docker container
  • The starting command for our container

Containerize Preact

Go to django-preact-docker/frontend and create a new file:

touch .dockerignore

Open the file in your text editor and add the following:

node_modules
npm-debug.log
Dockerfile
yarn-error.log

Go back to the terminal in frontend and create another Dockerfile:

touch Dockerfile

Open and edit "Dockerfile" to contain:

FROM node:16-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 5173

CMD ["npm", "run", "dev"]

Lastly, we must add the new npm run dev script. Head to frontend/package.json and change scripts too:

"scripts": {
  "dev": "vite --host 0.0.0.0",
}

Packaging our applications with Docker Compose

Next, we must create a configuration file to run our two Docker containers together. In the main folder, django-preact-docker, create a new file called docker-compose.yml:

touch docker-compose.yml

Open it and edit it to contain the following:

version: '3.9'

services:
  db:
    image: postgres:14-alpine
    ports:
      - '5432:5432'
    environment:
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_DB=postgres
    volumes:
      - ./data/db:/var/lib/postgresql/data/

  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - '5173:5173'
    volumes:
      - ./frontend:/app/frontend
    depends_on:
      - backend

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    environment:
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_DB=postgres
    ports:
      - '8000:8000'
    volumes:
      - ./backend:/app/backend
    depends_on:
      - db

The Docker Compose file tells Docker how the different containers work together.

Are you using Sentry, Rollbar, Bugsnag, or Airbrake for your monitoring? Honeybadger includes error tracking with a whole suite of amazing monitoring tools — all for probably less than you're paying now. Discover why so many companies are switching to Honeybadger here.
Start free trial

Build the containers

Go to the root django-preact-docker from the terminal and run the following command (this may take a while):

docker-compose build

Once complete, you should see the images in Docker Desktop.

You can then run the containers with the following:

docker-compose up

After this, the servers are accessible at the ports:

  • 5173 for frontend
  • 8000 for backend
  • 5432 for the database

You should check that they're running correctly first before moving on.

Press Ctrl + C or run docker-compose down to stop the containers.

Additional setup

We need to change a few settings,

Navigate to the backend folder and change settings.py to:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'postgres',
        'USER': 'postgres',
        'PASSWORD': 'postgres',
        'HOST': 'db',
        'PORT': '5432',
    }
}

Also, we need to change CORS further below in settings.py. The CORS configuration allows our different applications to communicate across different domains in the web browser:

INSTALLED_APPS = [
    'corsheaders',  # add this
]

MIDDLEWARE = [
    ...,
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    ...,
]

CORS_ALLOW_ALL_ORIGINS = True

Testing the stack works together

Finally, we'll build a simple response code to send data from the Django backend and ensure everything works together.

In backend/backend, create a new file, views.py, and paste the following:

from django.http import JsonResponse

def get_text(request):
    text = "All operational from the Django backend!"

    data = {
        'text': text,
    }

    return JsonResponse(data)

Then open urls.py and add these two lines:

from .views import get_text

And in URL patterns:

urlpatterns = [
    # other code
    path('test/', get_text),
]
from django.contrib import admin
from django.urls import path
from .views import get_text

urlpatterns = [
  path('admin/', admin.site.urls),
  path('test/', get_text),
]

You can now see this text on http://localhost:8000/test/.

To display it in our frontend, navigate to frontend/src/index.jsx and change it to the following:

import { render } from 'preact';
import preactLogo from './assets/preact.svg';
import './style.css';
import { useState, useEffect } from 'react';

export function App() {
    const [text, setText] = useState(null);

    useEffect(() => {
        fetch('http://127.0.0.1:8000/test/')
            .then(res => res.json())
            .then(data => {
                setText(data.text);
            });
    });

    return (
        <div>
            <h1>An unbeatable tech stack</h1>
            <a href="https://preactjs.com" target="_blank">
                <img src={preactLogo} alt="Preact logo" height="160" width="160" />
            </a>
            <p>Running Preact, Django, Postgres, and Docker</p>
            <p>{text}</p>
        </div>
    );
}

render(<App />, document.getElementById('app'));

Refresh and reload, and you should see a working Preact front page!

Stop digging through chat logs to find the bug-fix someone mentioned last month. Honeybadger's built-in issue tracker keeps discussion central to each error, so that if it pops up again you'll be able to pick up right where you left off.
Start free trial

Conclusion

By containerizing your technology stack with Docker, you've taken a significant step toward seamless integration and enhanced efficiency. While the initial setup might have required some effort, the benefits are clear.

Now that you've containerized your tech stack, including Django, Preact, and Postgres, you can explore, innovate, and navigate the ever-evolving tech landscape more effectively—a pivotal moment in your tech journey. Embrace the possibilities, and may your adventures be characterized by streamlined integration and boundless creativity!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK