Skip to the content.

AWS Deployment Preparation

Overview

This blog documents the preparation steps for obtaining the 3 Musketeer passwords and deploying both the frontend and backend applications. The goal is to ensure a smooth deployment process without breaking the machine.

Prerequisites

- Review Documentation

  • AWS Deployment Guide: BI4

    - Prepare Code Repository

  • Backend
    • main.py
        if __name__ == "__main__":
        # change name for testing
        app.run(debug=True, host="0.0.0.0", port=8402)
      
    • Dockerfile
        # Use the official Python image from the Docker Hub
        FROM python:3.11
      
        # Set the working directory in the container
        WORKDIR /app
      
        # Copy the current directory contents into the container at /app
        COPY . /app
      
        # Install any needed packages specified in requirements.txt
        RUN pip install --no-cache-dir -r requirements.txt && \
            pip install gunicorn
      
        # Set environment variables
        ENV GUNICORN_CMD_ARGS="--workers=1 --bind=0.0.0.0:8402"
        ENV FLASK_ENV=production
      
        # Make port 8402 available to the world outside this container
        EXPOSE 8402
      
        # Run gunicorn server
        CMD ["gunicorn", "main:app"]
      
    • docker-compose.yml
        version: '3'
        services:
                web:
                        image: flask_2025
                        build: .
                        env_file:
                                - .env # This file is optional; defaults will be used if it does not exist
                        ports:
                                - "8402:8402"
                        volumes:
                                - ./instance:/instance
                        restart: unless-stopped
      
    • nginx_file
        server {
        listen 80;
        listen [::]:80;
        server_name p4csp.thetravelers.com;
      
        location / {
            proxy_pass http://web:8402;  # Use the service name in Docker Compose
      
            # Set headers to forward real IP and Host
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
      
            # Increase timeout for large responses
            proxy_read_timeout 300;
      
            # CORS settings
            if ($request_method = OPTIONS) {
                add_header "Access-Control-Allow-Credentials" "true" always;
                add_header "Access-Control-Allow-Origin" "https://nighthawkcoders.github.io" always;
                add_header "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
                add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Origin, X-Requested-With, Content-Type, Accept" always;
                return 204;
            }
        }
      
        # Optional: Redirect HTTP to HTTPS
        return 301 https://$host$request_uri;
        }
      
  • Frontend
    • assets/api/config.js
        export var pythonURI;
        if (location.hostname === "localhost") {
                pythonURI = "http://localhost:8402";
        } else if (location.hostname === "127.0.0.1") {
                pythonURI = "http://127.0.0.1:8402"; //rey
        } else {
                pythonURI =  "https://flocker.nighthawkcodingsociety.com";
        }
      
    • my own feature - landscape
        const pythonURI = (() => {
            if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
                return "http://127.0.0.1:8402"; 
            } else {
                return "https://flask2025.nighthawkcodingsociety.com";
            }
        })();
      
        async function fetchLandscapes() {
            try {
                const response = await fetch(`${pythonURI}/api/landscapes`); 
                if (!response.ok) {
                    throw new Error('Failed to fetch landscapes: ' + response.statusText);
                }
                const landscapeData = await response.json();
                displayLandscapes(landscapeData);
            } catch (error) {
                console.error('Error fetching landscapes:', error);
            }
        }