fix: resolve CORS and remote Docker access issues#681
Conversation
Adds CORS_ORIGINS and FRONTEND_BASE_URL as configurable environment variables in docker-compose.yml so users can override them without editing source files. Clarifies that NEXT_PUBLIC_API_URL is the internal backend URL used by the Next.js server-side proxy rewrite, not the external server IP. Browser requests are proxied through Next.js, so CORS and IP config are not required for remote Docker deployments.
Changes API_BASE to use the /api_be/api/v1 proxy path on the client side, routing browser requests through the Next.js rewrite rule (next.config.ts) instead of directly to the backend. - Browser requests go to /api_be/api/v1/* (same-origin, no CORS) - Next.js server-side rewrite forwards to http://localhost:8000/* - Server Components (print pages) continue using the absolute URL This fixes CORS errors for remote Docker deployments and makes PDF download work when accessing from a different machine, with no IP configuration or image rebuild required.
Adds notes explaining that CORS_ORIGINS is not needed for standard Docker or npm dev setups since browser requests are proxied through Next.js. Documents that FRONTEND_BASE_URL should remain localhost (Playwright runs inside the container).
Code Review SummaryStatus: No Issues Found | Recommendation: Merge OverviewThis PR implements a clean solution for Docker remote access by routing client-side API requests through a Next.js proxy rewrite ( Key Changes Reviewed:
Focus Areas Checked:
Files Reviewed (3 files)
|
There was a problem hiding this comment.
Pull request overview
This PR adjusts the deployment/networking model so the browser talks to the backend via a same-origin Next.js proxy rewrite, avoiding CORS issues and preventing PDF downloads from being tied to localhost on the end user’s machine in remote Docker deployments.
Changes:
- Switch frontend client-side API base to the Next.js rewrite path (
/api_be/api/v1) while keeping server-side fetches pointed at the internal backend URL. - Update
apiFetchto avoid double-prepending the base when given an already-prefixed proxy URL. - Clarify Docker/ENV configuration for proxying, CORS, and Playwright PDF generation base URL.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
docker-compose.yml |
Documents proxy-based access and adds overridable CORS_ORIGINS / FRONTEND_BASE_URL env vars for Docker deployments. |
apps/frontend/lib/api/client.ts |
Makes API base context-aware (browser uses rewrite path; server uses absolute internal URL) and updates apiFetch base handling. |
apps/backend/.env.example |
Improves documentation around FRONTEND_BASE_URL and when CORS_ORIGINS is actually needed. |
| # Browser requests are proxied through Next.js - they never contact the | ||
| # backend directly, so no CORS or IP configuration is needed for remote use. | ||
| args: | ||
| - NEXT_PUBLIC_API_URL=http://localhost:${BACKEND_PORT:-8000} |
There was a problem hiding this comment.
The comments here say the Next.js rewrite backend URL should always be reachable from inside the container (i.e., always localhost:8000), but the build arg still uses ${BACKEND_PORT}. If a user overrides BACKEND_PORT (e.g., to change the exposed host port), this will bake a different port into the frontend rewrite target and can break proxying inside the container. Consider hardcoding the internal backend port (http://localhost:8000) for NEXT_PUBLIC_API_URL, or otherwise make internal port selection/mappings consistent (rewrite target, uvicorn port, and compose port mappings all aligned).
| - NEXT_PUBLIC_API_URL=http://localhost:${BACKEND_PORT:-8000} | |
| - NEXT_PUBLIC_API_URL=http://localhost:8000 |
|
@srbhr I already fixed this is a better way, this can be closed: Test with this: ghcr.io/webysther/resume-matcheronly need this: services:
resume-matcher:
image: ghcr.io/webysther/resume-matcher
container_name: resume-matcher
ports:
- "3000:3000"
volumes:
- resume-data:/app/backend/data
restart: unless-stopped
volumes:
resume-data:
driver: localI will sent the PR in few minutes, just adjusting docs and making more tests |
|
Hey @webysther I've asked Docker to add me to the Docker Open Source, so is there a way we can also push this image to Docker? Whenever there's a new release? |
My suggestion as I see people on others projects, skip docker hub for now (mean, just comment the push to docker hub in actions), they take months to get back to you. Send only to ghcr, are the best because not api rate limit. |
Problem
Users running the app on a remote Docker server and accessing from a different machine encountered two issues:
localhost:3000by default, blocking requests from remote originsNEXT_PUBLIC_API_URLwas baked into the JS bundle ashttp://localhost:8000, so the browser on a remote machine tried to fetch from its own localhost instead of the serverRoot Cause
The frontend was making cross-origin requests directly from the browser to the backend (
http://SERVER_IP:8000). This requires CORS headers and the correct server IP baked at build time — both of which are painful to configure for self-hosted deployments.Fix
Route all browser API calls through the Next.js proxy rewrite that was already configured in
next.config.tsbut unused:apps/frontend/lib/api/client.tsAPI_BASEis now context-aware:/api_be/api/v1— same-origin proxy path, zero CORShttp://localhost:8000/api/v1— direct internal URLapiFetchupdated to avoid double-prepending the base when given a full proxy pathdocker-compose.ymlNEXT_PUBLIC_API_URLis the internal backend URL for the proxy rewrite, not the external server IPCORS_ORIGINSandFRONTEND_BASE_URLas overridable env vars (kept for non-Docker / edge-case use)apps/backend/.env.exampleCORS_ORIGINSis not needed for standard Docker or npm dev setupsResult
Summary by cubic
Proxy browser API calls through Next.js to remove CORS errors and fix PDF downloads when accessing a remote Docker host. Remote deployments now work without server IP config or image rebuilds.
Written for commit 36bd1ce. Summary will update on new commits.