Personalized Deployment Blog

Introduction

Deployment is the final step in the software development lifecycle. Before we push our project live, it is crucial to ensure that everything is properly set up, from the frontend to the backend. This guide outlines the essential steps required for deploying a full-stack application, covering everything from server configuration to DNS setup.

Preparing for Deployment

Before starting, complete a thorough review of the frontend-to-backend integration. Ensure that your test server is running smoothly locally. If it doesn’t work locally, it won’t work in production.

Additionally, document the deployment process, including terms, visuals, and troubleshooting steps. Clearly define roles for Deployment Admins and prepare necessary configuration files in your repository.

Deployment Steps

1. Build and Test

Build your application locally and test it to ensure that it works as expected.

2. Configure files for Deployment

NGINX FILE (motor.stu.nginx_file)

server {
    listen 80;
    listen [::]:80;
    server_name motor.stu.nighthawkcodingsociety.com ; # Change server name to the one on R53
    # Configure CORS Headers
    location / {
        proxy_pass http://localhost:8104; # Change port to port on docker
        # Simple requests
        if ($request_method ~* "(GET|POST|PUT|DELETE)") { # Customize Request methods based on your needs
                add_header "Access-Control-Allow-Origin"  *;
        }
        # Preflighted requests
        if ($request_method = OPTIONS ) {
                add_header "Access-Control-Allow-Origin"  *;
                add_header "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, OPTIONS, HEAD"; # Make sure the request methods above match here
                add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
                return 200;
        }
    }
}

docker-compose.yml

version: '3'
services:
        web:
                image: motorsports
                build: .
                env_file:
                        - .env # This file is optional; defaults will be used if it does not exist
                ports:
                        - "8104:8104"
                volumes:
                        - ./instance:/instance
                restart: unless-stopped

Dockerfile

FROM docker.io/python:3.12.8

WORKDIR /

# --- [Install python and pip] ---
RUN apt-get update && apt-get upgrade -y && \
    apt-get install -y python3 python3-pip git
COPY . /

RUN pip install --no-cache-dir -r requirements.txt
RUN pip install gunicorn
RUN ./scripts/db_init.py

ENV GUNICORN_CMD_ARGS="--workers=3 --bind=0.0.0.0:8104"

EXPOSE 8104

# Define environment variable
ENV FLASK_ENV=production

CMD [ "gunicorn", "main:app" ]

3. Deploy to AWS EC2 using cockpit backdoor

Clone the repository to the virtual machine

git clone https://github.com/Tvick22/personal_flocker_backend.git motor_backend
cd motor_backend

Recreate the .env file

touch .env

Add the following to the .env file

ADMIN_USER='toby'
ADMIN_PASSWORD='123Toby!'
DEFAULT_USER='hop'
DEFAULT_PASSWORD='123Hop!'

Ensure that the DOCKERFILE file can initialize the database

RUN ./scripts/db_init.py

Build the docker image

docker-compose build

Run the docker image

docker-compose up -d

Ensure that the docker image is running on our port (8104)

docker ps

Ensure we are running on port 8104

curl localhost:8104

4. Configure DNS (Domain Name)

Configure the DNS to point to the EC2 instance. This can be done by creating a new record set in the hosted zone, stu.nighthawkcodingsociety.com. The hosted zone can be found in the AWS console under Route 53. The record set can be created by clicking on Create Record Set and selecting the appropriate values.

How is my frontend integrated with my backend?

The frontend is integrated with the backend by using a proxy server. The proxy server is responsible for forwarding requests to the appropriate backend server. In this case, the proxy server is NGINX, which is configured to forward requests to the backend server running on port 8104.

Step by step exapmle

  1. The frontend sends a request to the domain. (motor.stu.nighthawkcodingsociety.com)
  2. The domain name is resolved to the IP address of the server. (DNS)
  3. The IP address is sent to the proxy server where it is forwarded to the appropriate docker container based on the port (8104). (NGINX)
  4. The docker container running on port 8104 receives the request and processes it. (Python Flask)
  5. The response is sent back to the proxy server and the proxy server sends it to the frontend. (NGINX to frontend)
TCP and Certbot

In this exapmle, requrests are sent using the TCP (Transmission Control Protocol) protocol. A three-way TCP handshake establishes a reliable connection between the client (browser) and the server.

The Certbot tool is used to encrypt the data sent between the client and the server. This ensures that the data is secure and cannot be intercepted by third parties. It also enables HTTPS, which is a secure version of the HTTP protocol.

Physical Connection

In this exapmle, the physical connection between the client and the server is established using a Ethernet cable or Wi-Fi or fiber optic cable. IP packets are converted into physical signals, and these signals traverse physical infrastructure, including cables, wireless access points, and routers.

Layers of the TCP/IP Model

The TCP model is a conceptual framework that describes the functions of a communication system.

  1. Application Layer - In this case, the application layer is the frontend web server (Github Pages)
  2. Transport Layer - In this case, the transport layer is the TCP protocol and NGINX
  3. Network Layer - In this case, the network layer is the IP protocol and Router
  4. Physical Layer - In this case, the physical layer is the Ethernet cable or Wi-Fi or fiber optic cable

Example of a TCP/IP model:

tcpipmodel

Restart nginx (Dont forget to test it before though)

sudo systemctl restart nginx

Deployment

docker-compose build
docker-compose up -d

If you want to see debug messages then remove the -d tag (it stands for detach).

docker exec -it motor_backend-web-1 scripts/db_init.py

exec runs a bash command in the docker container.