I have an application with React 19 and FastAPI, my backend runs on localhost:8000/api/....
Here is my nginx.conf
:
server {
listen 80; # Nginx should listen on port 80 inside the container
server_name _; # Or your actual domain if you have one
root /usr/share/nginx/html;
index index.html;
# API proxy configuration (if needed)
location /api/ {
proxy_pass http://app:8000/; # Assuming 'app' is your backend service name in docker-compose
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
# This is crucial for SPA routing.
# It tries to serve the file if it exists, then the directory,
# otherwise it serves /index.html which lets your React router take over.
try_files $uri $uri/ /index.html;
}
# Optional: You can keep this, but try_files in the location block is more direct for SPA routing.
error_page 404 /index.html;
}
My docker-compose.yml
:
version: '3.8'
services:
frontend:
build:
context: .
dockerfile: Dockerfile # Referencing the Dockerfile in frontend folder
container_name: react-frontend
ports:
- '5173:80' # Nginx exposes the app on port 5173
networks:
- backend
networks:
backend:
external: true
name: task-management-network
and my docker-compose.yml
for backend:
services:
app:
build:
context: ./
dockerfile: Dockerfile
dns:
- 8.8.8.8 # Google's public DNS
container_name: fastapi-app
ports:
- "8000:8000"
depends_on:
- db
- redis
networks:
- backend
volumes:
- .:/app # Mount the app directory to the container for live updates
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload # Enable hot-reloading
networks:
backend:
name: task-management-network
My .env.production
VITE_API_BASE_URL=""
VITE_API_V1_URL="/api/v1"
My Vite config:
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
});
and in Axios config I use like this:
const baseURL = import.meta.env.VITE_API_V1_URL;
The problem is when the frontend side calls an API, instead of http://localhost:8000/api/v1/profile
, it uses the base frontend URL which is not correct: http://localhost:5173/api/v1/profile
(this is wrong). Does anyone know how to fix it?
To forward requests from /api/v1/profile
to http://app:8000/api/v1/profile
, you need configure the Nginx as follows:
location /api/ {
proxy_pass http://app:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
This configuration ensures that the /api/ prefix is preserved in the forwarded request.
Here are two schemes to help you connect the front-end and the back-end:
Using API proxy ensures that there is no CORS problem. Just like your nginx configuration file, the final access to api is actually done by accessing nginx.
Configure appropriate CORS rules and write the back-end URL directly to the front-end. This scheme is more used in the back-end load-balancing environment.
For more details on Nginx proxying, refer to the DocumentNginx Official Document about porxy.