Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Azure Web App Service + Docker Compose + NGINX Reverse Proxy -- 502 Error in Deployment

as the title states, I have created a full stack application that uses FastAPI as the backend, and ReactJS as the frontend. I also have a third container for my Nginx reverse proxy. Reason I have this third container is so that I can make calls to my backend from the client's browser using the service/container names I create in the docker-compose.yaml file.

I then use the compose file to build and run all 3 of those containers. When I am working locally, everything works great at the localhost endpoint on my browser. However, when I try to deploy to Azure Web App Service, I am only able to load the frontend (React) home page. When I open the console, I receive an error saying 502 (Bad Gateway).

Below is a snippet of my ReactJS code that makes a post request for authentication

import React, { useEffect, useContext } from 'react';
import { Redirect, Route } from 'react-router-dom';
import Cookies from 'js-cookie';
import { AuthContext } from './contexts/AuthContext';

const PrivateRoute = ({ component: Component, ...rest }) => {
  // Import the functions to set states
  const { isAuthenticated, setIsAuthenticated, setUsername } =
    useContext(AuthContext);

  // Read in the access token; if not available, make empty string
  const accessToken =
    Cookies.get('access_token') == null ? '' : Cookies.get('access_token');

  // Create the use effect function to generate the component
  useEffect(() => {
    fetch(`${window.location.protocol}//${window.location.hostname}/backend/auth/validate_token`, {
      method: 'POST',
      mode: 'cors',
      credentials: 'include',
      headers: {
        Accept: 'application/json',
      },
      body: JSON.stringify({
        token: accessToken,
      }),
    })
      .then((response) => {
        return response.json();
      })
      .then((response) => {
        // Set the view based on the return
        if (response) {
          setIsAuthenticated(true);
          setUsername(response.username);
        } else {
          setIsAuthenticated(false);
        }
      });
  });

  return (
    <>
      <Route
        {...rest}
        render={() => {
          if (isAuthenticated) {
            return <Component {...rest} />;
          } else {
            return <Redirect to='/login' />;
          }
        }}
      />
    </>
  );
};

export { PrivateRoute };

Below is my docker compose file

version: "3"
services:
    reverse-proxy:
        container_name: reverse-proxy
        build:
            context: ./proxy
            dockerfile: Dockerfile
        image: ilecontainerregistry.azurecr.io/proxy:latest
        ports:
            - 80:80
            - 443:443
        depends_on:
            - frontend
            - backend
    frontend:
        container_name: frontend
        domainname: "usps-ile"
        # Remove the build command for configuration file in azure web app service
        build:
            context: ./frontend
            dockerfile: Dockerfile
        image: ilecontainerregistry.azurecr.io/frontend:latest
        ports:
            - 8080:80
        env_file:
            - ./frontend/.env
    backend:
        container_name: backend
        domainname: "usps-ile"
        # Remove the build command for configuration file in azure web app service
        build:
            context: ./backend
            dockerfile: Dockerfile
        image: ilecontainerregistry.azurecr.io/backend:latest
        ports:
            - 3000:3000
        env_file:
            - ./backend/app/.env

Below is my dockerfile for the nginx container

FROM nginx:latest

COPY nginx.conf /etc/nginx/

And lastly, here is my nginx.conf file

events {
    worker_connections 1024;
}

http {

    upstream backend{
        server backend:3000;
    }

    server {

        listen 80;
        listen 443;
        server_name _;

        location / {
            proxy_pass http://frontend:80/;
        }

        location /backend/ {
            proxy_pass http://backend/;
        }
    }
}

Below is a snippet from the FastAPI backend for the authentication post route in Python

@auth_router.post("auth/validate_token", tags=["Auth"])
async def validate_token(token: Token):
    '''
    This function is responsible for
    reading in the token in an object
    and validating if it is still valid
    '''

    try:

        # Get the access token from the request cookie
        authorization: str = token.token

        # Split the access token on the space "Bearer" "xxxxxxxxx-token"
        scheme, access_token = get_authorization_scheme_param(authorization)

        # Decode the token and check if it is valid
        decoded_token = jwt.decode(
            token=access_token,
            key=os.getenv("SECRET_KEY"),
            algorithms=[os.getenv("ALGORITHM")]
        )

        return decoded_token
    except Exception as e:
        return False

Thank you in advance!

like image 939
Elias Yishak Avatar asked Sep 07 '25 04:09

Elias Yishak


1 Answers

Looks like I figured out a solution that worked for me, I originally had the PORT for FastAPI exposed at 3000 (what i set it during development) but when I tried to deploy it with docker compose, I was having some issues with container communication.

I defaulted back to the normal PORT 80 for the fastapi container and changed my nginx conf file to look like the following and it worked like a charm! Hope I can help anyone else that was stuck.

events {
    worker_connections 1024;
}

http {

    server {

        listen 80;
        server_name _;

        location / {
            proxy_pass http://frontend:80/;
        }

        location /backend/ {
            proxy_pass http://backend:80/;
        }
    }
}
like image 195
Elias Yishak Avatar answered Sep 11 '25 02:09

Elias Yishak