DEV Community

Daniel Favour
Daniel Favour

Posted on • Updated on

Containerize a full-stack app (React + Django)

I completed this task while participating in HNG DevOps task and thought to write on the process taken to achieve this.

Project Task

The task is focused on containerizing the given applications written in react and django, running the containers with Docker Compose and using Nginx reverse proxy to serve the frontend application as the default page.

Prerequisites

To get started, it's important to have the below

  • An active AWS Account
  • A Docker Hub Account
  • Knowledge of containers

GitHub

To see the completed project, you can visit the GitHub Repo here.

Getting Started

Create an ec2 instance (vm) from your AWS Console and login.

sudo apt update
sudo apt upgrade
Enter fullscreen mode Exit fullscreen mode

Clone the below repo into it

git clone https://github.com/ibitolamayowa/devops-django-react-task.git

Enter fullscreen mode Exit fullscreen mode

Install docker

You can refer to this article to install Docker

Check that Docker is running

sudo systemctl status docker
Enter fullscreen mode Exit fullscreen mode

docker running

Log out and log back in to add the user

To add a password

sudo passwd
Enter fullscreen mode Exit fullscreen mode

Containerizing the application

cd into it , then cd into frontend

cd devops-django-react-task/
cd frontend/
cd src
cd components/
Enter fullscreen mode Exit fullscreen mode

We would first start by editing the App.js file in this location

sudo nano App.js
Enter fullscreen mode Exit fullscreen mode

The file should look like the below, you should change the name to your name.

Create Dockerfile file for frontend

Now move back to the frontend directory, you should be in this directory /devops-django-react-task/frontend

To create your Dockerfile, use the below command

sudo nano Dockerfile
Enter fullscreen mode Exit fullscreen mode

Paste the below into the file and save

# ==== CONFIGURE =====
# Use a Node 16 base image
FROM node:16-alpine
# Set the working directory to /frontend inside the container
WORKDIR /frontend
# Copy frontend files
COPY . .
# ==== BUILD =====
# Install dependencies (npm ci makes sure the exact versions in the lockfile gets installed)
RUN npm i
# Build the app                                                                                         
RUN npm run build
# ==== RUN =======
# Set the env to "production"                                                                           
ENV NODE_ENV production
# Expose the port on which the app will be running (3000 is the default that `serve` uses)
EXPOSE 3000
# Start the app                                                                                        
CMD [ "npx", "serve", "build" ]
Enter fullscreen mode Exit fullscreen mode

Save and exit.

Build Docker Image

Now you would build the docker image from the Dockerfile file you just created

Ensure you are in the frontend directory where the Dockerfile and application are present while doing this.

docker build -t frontend .
Enter fullscreen mode Exit fullscreen mode

frontend image building

frontend image building

To see the built image, run

docker images
Enter fullscreen mode Exit fullscreen mode

Now you need to push the image to docker hub

docker login
Enter fullscreen mode Exit fullscreen mode

docker login

After logging into your account, tag the image and push it

##docker tag imagename username/tag

docker tag frontend favourd205/frontend

docker push favourd205/frontend
Enter fullscreen mode Exit fullscreen mode

Create Dockerfile for Backend (API)

Now cd back to the api folder, you should be in this directory path

cd ..
cd api/
Enter fullscreen mode Exit fullscreen mode

We would first edit the requirements.txt file here as the current psycopg2==2.9.5 version in the file is not supported.

To do this, run the below command

sudo nano requirements.txt
Enter fullscreen mode Exit fullscreen mode

Replace the psycopg2==2.9.5 with psycopg2-binary

requirement

Now we can create the Dockerfile file. To do this run the below command

sudo nano Dockerfile
Enter fullscreen mode Exit fullscreen mode

copy and paste the below into it

FROM python:3.8-alpine

ENV PYTHONDONTWRITEBYTECODE 1

ENV PYTHONBUFFERED=1

RUN mkdir /backend

WORKDIR /backend

COPY . /backend/

RUN pip install -r requirements.txt

EXPOSE 8000

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
Enter fullscreen mode Exit fullscreen mode

Now to build the image

docker build -t backend .

Enter fullscreen mode Exit fullscreen mode

NB: Its best practice to do build the image in a virtual environment, it is also possible to build the image without a virtual environment like the below

backend image building

Now we can push the image

docker tag backend favourd205/backend

docker push favourd205/backend
Enter fullscreen mode Exit fullscreen mode

Check your Docker Hub registry and you should see the two images there

docker hub

Running the Docker Containers

Now to run the containers you would need docker compose, install docker compose on the virtual machine.

To install docker compose, refer to this
cd out of the api directory and ensure you are on this path devops-django-react-task. That is where the installation should happen.

After installation, create a docker-compose.yaml file and paste the below into it

sudo nano docker-compose.yaml
Enter fullscreen mode Exit fullscreen mode

Pate the below into the file


version: "3"

services:
    frontend:
        image: favourd205/frontend:latest
        container_name: frontend
        ports:
          - 3000:3000
        depends_on: 
          - backend  

    backend:
        image: favourd205/backend:latest
        container_name: backend
        command: python manage.py runserver 0.0.0.0:8000
        ports:
            - "8000:8000"

Enter fullscreen mode Exit fullscreen mode

After saving, run

docker-compose up -d 

or 

docker-compose up --detach
Enter fullscreen mode Exit fullscreen mode

=====remember to allow all traffic

This should run and bring up the two container images

Navigate to your instance ip address on the assigned ports and your applications should be running

Frontend runs on port 3000

frontend

Backend runs on port 8000

backend

Routing frontend with Nginx

Now you should install nginx for reverse proxy

sudo apt update
sudo apt install nginx
Enter fullscreen mode Exit fullscreen mode
Confirm that nginx is running

sudo service nginx status

or 

sudo systemctl status nginx
Enter fullscreen mode Exit fullscreen mode

nginx running

For reverse proxy, enter nginx directory

cd /etc/nginx/
ls
Enter fullscreen mode Exit fullscreen mode

nginx directories

Now you can see all nginx files, we need to edit the nginx.conf file

sudo nano nginx.conf
Enter fullscreen mode Exit fullscreen mode

delete all the configurations in the file and use the below

events{
    worker_connections 1024;
}
http { 
    keepalive_timeout 5;
        upstream frontend {
            keepalive 50;
            server 54.173.78.222;


}
server {
   listen 80;
location / {
        proxy_set_header  X-Real-lP $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Proto $scheme;
        proxy_set_header        Host $host;
        proxy_pass http://54.173.78.222:3000;
}
}
}
Enter fullscreen mode Exit fullscreen mode

NB: Ensure to change the server IP address in the configuration to yours as well as the proxy pass IP address
Confirm the above configuration syntax is correct

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

It should return successful

nginx syntax

Now reload nginx

sudo nginx -s reload
Enter fullscreen mode Exit fullscreen mode

Now copy your IP address again but this time do not add any port number to it, the frontend application is supposed to be running by default on the IP address.

default nginx

Top comments (0)