DEV Community

Kiran Parajuli
Kiran Parajuli

Posted on • Edited on

Dockerizing Your Django Vue Application: A Step-by-Step Guide

In this comprehensive guide, we will walk you through the process of dockerizing your Django and Vue applications.

Prerequisites

  • Docker (version 20.x.x or higher)
  • Docker-compose (version 2.x.x or higher)
  • Django application (Django + Gunicorn)
  • Vue application (Vue + Vite)

Folder Structure

To facilitate this guide, we assume the following folder structure for your project. You can customize it as needed, but remember to adjust the commands accordingly:

. ├── backend (Django application) │ ├── Dockerfile ├── frontend (vue application) │ ├── Dockerfile ├── docker-compose.yml 
Enter fullscreen mode Exit fullscreen mode

Dockerfile for Django Application

For the Django application, we'll make the following assumptions:

  1. Port to expose: 8000
  2. Serve using: gunicorn
  3. Database: postgres

Gunicorn Configuration

workers = 4 max_requests = 1000 timeout = 30 bind = "0.0.0.0:8000" preload_app = True accesslog = "logs/gunicorn_access.log" errorlog = "logs/gunicorn_error.log" 
Enter fullscreen mode Exit fullscreen mode

Note: We use 0.0.0.0 for binding to allow access from outside the container.

Dockerfile for Backend

In this section, we'll prepare the playground for your Django application. We will use Docker Compose to run the application. Here are the assumptions:

  1. Port to expose: 8000
  2. Serve using: Gunicorn
  3. Database: PostgreSQL
  4. Dependencies Listed in: requirements.txt
FROM python:3.10 WORKDIR /app COPY requirements.txt /app/ RUN pip install --no-cache-dir -r requirements.txt EXPOSE 8000 CMD ["gunicorn", "backend.wsgi:application", "--config", "gunicorn.py"] 
Enter fullscreen mode Exit fullscreen mode

Note: We won't copy all files to the container; instead, we'll use volumes to mount files from Docker Compose to preserve hot-reloading functionality.

Dockerfile for Frontend

Similarly, we'll prepare the playground for your Vue application. We will use Docker Compose to run the application. For Vue, we'll assume:

  1. Port to expose: 3000
  2. Serve using: Vite

To make it work with Docker, add the following to your package.json:

{ "scripts": { "dev:docker": "vite --host" } } 
Enter fullscreen mode Exit fullscreen mode

Note: We use vite with the --host flag to make it accessible from outside the container.

FROM node:20-alpine3.17 WORKDIR /app COPY package.json pnpm-lock.yaml /app/ RUN npm install -g pnpm RUN pnpm install EXPOSE 3000 CMD ["pnpm", "dev:docker"] 
Enter fullscreen mode Exit fullscreen mode

Just like with the Django application, we won't copy all files to the container, relying on Docker Compose volumes for file mounting to maintain hot-reloading.

Docker compose

Now, let's dive into Docker Compose to run your application.

version: '3.8' services: postgres: container_name: db image: postgres:16.0-alpine restart: always environment: POSTGRES_USER: einstein POSTGRES_PASSWORD: relativity POSTGRES_DB: einstein volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: [ "CMD", "pg_isready", "-U", "einstein" ] interval: 5s timeout: 5s retries: 5 ports: - "5433:5432" backend: container_name: backend build: context: ./backend volumes: - ./backend/:/app - ./backend/.env.docker:/app/.env - ./backend/logs:/app/logs depends_on: postgres: condition: service_healthy ports: - "8000:8000" healthcheck: test: [ "CMD", "curl", "-f", "http://localhost:8000/healthcheck" ] interval: 5s timeout: 5s retries: 5 frontend: container_name: web build: context: ./frontend volumes: - ./frontend:/app - ./frontend/.env.example:/app/.env depends_on: backend: condition: service_healthy ports: - "3000:3000" volumes: pgdata: media: static: 
Enter fullscreen mode Exit fullscreen mode

To break it down:

  1. We use depends_on and healthcheck to ensure dependent services are up and running before starting. PostgreSQL is used as the database for the Django application, so we ensure that the postgres service is operational before launching the backend service. A similar approach is used for the frontend service.
  2. Volumes are employed to mount files from the host machine to the container. We mount backend and frontend folders to their respective containers and include the .env.docker file containing environment variables.
  3. Ports are exposed to make container ports accessible from the host machine. In this configuration, we've mapped 8000 and 3000 from the backend and frontend containers, respectively. Additionally, PostgreSQL's port is mapped to 5433 on the host to avoid conflicts.

Running the application

With everything set up, it's time to run your application:

docker compose up 
Enter fullscreen mode Exit fullscreen mode

This command will spin up PostgreSQL with the specified database and user. It will also start the backend and frontend services. Access your application at http://localhost:3000.

To run migrations, execute the following command:

docker compose exec backend python manage.py migrate 
Enter fullscreen mode Exit fullscreen mode

The choice to run migrations after the application is up allows for easy updates to models without manual migration execution.

To create a superuser, run:

docker compose exec backend python manage.py createsuperuser 
Enter fullscreen mode Exit fullscreen mode

Avoid putting superuser creation in the Dockerfile to prevent errors if the superuser already exists.

To collect static files, use this command:

docker compose exec backend python manage.py collectstatic 
Enter fullscreen mode Exit fullscreen mode

Conclusion

Congratulations, you've successfully dockerized your Django Vue application! Now, you can deploy it to your preferred cloud provider or use it for the development environment. Happy coding!

Top comments (1)

Collapse
 
queen_of_engineers42 profile image
Sarah Murray • Edited

I'm having an issue with vite/pnpm where it is refusing to find the @rollup/linux binary even though it's installed. Attached image of error below.
Image description

So I followed the recommendation in this thread to use a pnpm override in my package.json and now it's generating this error:
Image description

Any suggestions?