Dockerizing a Django and React Application: Docker + Django + React
By Andrew on 9/12/2024
Table of Contents
- Introduction
- Prerequisites
- Project Structure
- Dockerizing the Django Backend
- Dockerizing the React Frontend
- Setting Up Docker Compose
- Managing Environment Variables
- Building and Running the Containers
- Testing the Application
- Next Steps
Introduction
In this guide, we’ll walk through the process of Dockerizing a full-stack application consisting of a Django backend and a React frontend. By the end of this tutorial, you’ll have a Dockerized application that can be easily deployed and scaled.
If you want a completely dockerized production ready starter kit check out SlimSaaS.com. The starter kit is preconfigured with docker, traefik, automatic let’s encrypt ssl, hot reloading, reverse proxies, and more!
Prerequisites
Before we begin, make sure you have the following installed:
- Docker: Install Docker for your operating system.
- Docker Compose: Included with Docker Desktop on Windows and macOS. On Linux, install it separately: Install Docker Compose.
- Basic Knowledge: Familiarity with Django, React, and command-line operations.
Project Structure
Let’s assume the following directory structure for our project:
myapp/
├── backend/
│ ├── manage.py
│ ├── myapp/
│ │ ├── settings.py
│ │ └── ...
│ ├── requirements.txt
│ └── Dockerfile
├── frontend/
│ ├── package.json
│ ├── src/
│ ├── public/
│ └── Dockerfile
└── docker-compose.yml
Dockerizing the Django Backend
First, we’ll focus on containerizing the Django backend.
Creating the Dockerfile for Django
Create a file named Dockerfile
inside the backend/
directory:
# backend/Dockerfile
# Use an official Python runtime as a parent image
FROM python:3.9-slim
# Set the working directory in the container
WORKDIR /usr/src/app
# Install dependencies
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
# Copy the current directory contents into the container
COPY . .
# Expose port 8000 for the Django app
EXPOSE 8000
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
# Run the Django development server
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
Explanation:
- FROM python:3.9-slim: Uses a lightweight Python image.
- WORKDIR: Sets the working directory in the container.
- COPY requirements.txt ./: Copies the requirements file.
- RUN pip install: Installs Python dependencies.
- COPY . .: Copies the Django project files.
- EXPOSE 8000: Exposes port 8000.
- ENV: Sets environment variables to prevent Python from writing
.pyc
files and to enable output buffering. - CMD: Runs the Django development server.
Setting Up requirements.txt
In the backend/
directory, create a requirements.txt
file:
Django>=3.2,<4.0
djangorestframework
Add any additional Python packages your project requires.
Dockerizing the React Frontend
Next, we’ll containerize the React frontend.
Creating the Dockerfile for React
Create a file named Dockerfile
inside the frontend/
directory:
# frontend/Dockerfile
# Use an official Node runtime as a parent image
FROM node:14-alpine
# Set the working directory in the container
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
# Copy the app source code
COPY . .
# Build the app
RUN yarn build
# Use a lightweight web server to serve the static files
FROM nginx:alpine
COPY --from=0 /usr/src/app/build /usr/share/nginx/html
# Expose port 80
EXPOSE 80
# Start Nginx
CMD ["nginx", "-g", "daemon off;"]
Explanation:
- FROM node:14-alpine: Uses a lightweight Node.js image.
- WORKDIR: Sets the working directory.
- COPY package.json yarn.lock ./: Copies dependency files.
- RUN yarn install: Installs Node.js dependencies.
- COPY . .: Copies the React project files.
- RUN yarn build: Builds the React app for production.
- FROM nginx:alpine: Uses Nginx to serve the static files.
- COPY —from=0: Copies the build output from the previous stage.
- EXPOSE 80: Exposes port 80.
- CMD: Starts Nginx.
Note: We’re using multi-stage builds to keep the final image small.
Setting Up Docker Compose
Docker Compose allows us to run multi-container Docker applications. Create a docker-compose.yml
file in the root myapp/
directory:
# docker-compose.yml
version: '3.8'
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- '8000:8000'
volumes:
- ./backend:/usr/src/app
depends_on:
- db
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- '3000:80'
depends_on:
- backend
db:
image: postgres:13-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: myapp_db
volumes:
- postgres_data:/var/lib/postgresql/data/
volumes:
postgres_data:
Explanation:
- backend service builds from
./backend/Dockerfile
and exposes port 8000. - frontend service builds from
./frontend/Dockerfile
and maps port 80 inside the container to port 3000 on the host. - db service uses a PostgreSQL image with environment variables for setup.
- volumes persist database data between container restarts.
Managing Environment Variables
Create a .env
file in the root directory to store environment variables:
# .env
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=myapp_db
Update docker-compose.yml
to include:
env_file:
- .env
Add this under each service that requires these environment variables.
Building and Running the Containers
Navigate to your project’s root directory and run:
docker-compose up --build
This command builds the images and starts the containers.
To run the containers in detached mode:
docker-compose up --build -d
To stop the containers:
docker-compose down
Testing the Application
- Django Backend: Visit http://localhost:8000 to see the Django app running.
- React Frontend: Visit http://localhost:3000 to see the React app.
Ensure that both frontend and backend are communicating properly. You might need to update API endpoint URLs in your React app to point to the backend service.
Next Steps
- Implement Hot Reloading: For development, set up hot reloading to reflect code changes without rebuilding images.
- Add a Reverse Proxy: Use Nginx as a reverse proxy to route traffic between frontend and backend.
- Secure Your Application: Implement environment-specific settings and secure your environment variables.
- CI/CD Integration: Integrate with Continuous Integration and Continuous Deployment pipelines for automated testing and deployment.
If you want a completely dockerized production ready starter kit check out slimsaas.com
Build Faster