Modern web development is increasingly shifting toward microservices architecture, where applications are broken into smaller, manageable services. When combined with Docker, microservices become easier to build, deploy, and scale. In this blog, we’ll walk you through setting up Docker containers for a project using Django (as the backend) and React (as the frontend) following the microservices approach.
Why Use Microservices with Docker?
Before jumping into the setup, here’s why this combo is powerful:
- Scalability: Scale only the services that need more resources.
- Independent Deployment: Update and deploy each service separately.
- Environment Parity: Docker ensures consistency across development, testing, and production.
- Fault Isolation: Problems in one service won’t affect the others.
Project Structure
Here’s an overview of our project structure:
bashCopyEditproject-root/
├── backend/ # Django App
│ ├── manage.py
│ └── ...
├── frontend/ # React App
│ ├── package.json
│ └── ...
├── nginx/
│ └── default.conf
├── docker-compose.yml
├── backend/Dockerfile
├── frontend/Dockerfile
└── .env
Step 1: Dockerize the Django Backend
backend/Dockerfile
DockerfileCopyEditFROM python:3.11-slim
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY requirements.txt /app/
RUN pip install --upgrade pip && pip install -r requirements.txt
COPY . /app/
CMD ["gunicorn", "projectname.wsgi:application", "--bind", "0.0.0.0:8000"]
requirements.txt
shellCopyEditDjango>=4.0,<5.0
gunicorn
Step 2: Dockerize the React Frontend
frontend/Dockerfile
DockerfileCopyEditFROM node:20-alpine as build
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
RUN npm install
COPY . ./
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
Step 3: NGINX for Reverse Proxy
nginx/default.conf
nginxCopyEditserver {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://backend:8000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Step 4: Docker Compose for Multi-container Setup
docker-compose.yml
yamlCopyEditversion: '3.9'
services:
backend:
build: ./backend
container_name: django_backend
env_file:
- .env
volumes:
- ./backend:/app
ports:
- "8000:8000"
depends_on:
- db
frontend:
build: ./frontend
container_name: react_frontend
ports:
- "3000:80"
depends_on:
- backend
db:
image: postgres:15
container_name: postgres_db
restart: always
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: mydb
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypass
volumes:
pgdata:
Step 5: Running the Stack
With all files in place, spin up your containers:
bashCopyEditdocker-compose up --build
This will:
- Build and start your Django backend on port 8000
- Build and serve your React frontend on port 3000
- Start a PostgreSQL database service
- Use NGINX to reverse proxy requests
Best Practices for Microservices with Docker
- Use
.env
files to keep secrets and environment variables secure. - Separate services: As your project grows, consider splitting services like auth, payments, and notifications into independent Django apps or separate repositories.
- CI/CD integration: Automate container builds and deployments.
- Health checks: Add healthcheck configurations in
docker-compose.yml
for better reliability.
Conclusion
Using Docker to containerize a Django + React microservices architecture brings consistency, scalability, and ease of deployment to your development process. With docker-compose
, you can run your full-stack application locally or in production environments with minimal configuration changes.