CORS

CORS in Docker โ€” Why localhost Works but Container Does Not

Updated April 2026

Reading this article? Verify your fix in real-time. Test your CORS config โ€” CORSFixer โ†’

When you run your frontend and backend in separate Docker containers, they cannot reach each other via localhost. Container networking has its own namespace โ€” localhost inside a container refers to the container itself, not your host machine.

The Docker networking problem

# This works locally (no Docker):
fetch('http://localhost:8000/api')  # frontend on :3000 โ†’ backend on :8000

# This breaks in Docker:
# frontend container: localhost = the frontend container
# backend container: localhost = the backend container
# They are different machines

Fix 1 โ€” Use service names in docker-compose

Docker Compose creates a network where containers can reach each other by their service name. Use the service name instead of localhost:

# docker-compose.yml
services: frontend: build: ./frontend ports: - "3000:3000" environment: - REACT_APP_API_URL=http://backend:8000  # use service name backend: build: ./backend ports: - "8000:8000" environment: - CORS_ORIGIN=http://localhost:3000  # browser still uses localhost

The browser calls the backend using http://localhost:8000 (the host port mapping). The backend must allow the origin http://localhost:3000 for CORS.

Fix 2 โ€” For host machine access, use host.docker.internal

# From inside a container, reach the host machine:
fetch('http://host.docker.internal:8000/api')

# Or in docker-compose:
extra_hosts: - "host.docker.internal:host-gateway"

Fix 3 โ€” Nginx reverse proxy for both services

The cleanest setup: Nginx in front of both. Same origin = no CORS needed:

# nginx.conf inside the Nginx container
server { listen 80; location / { proxy_pass http://frontend:3000; } location /api/ { proxy_pass http://backend:8000/; # No CORS needed โ€” same origin from browser's perspective }
}

CORS config for Docker environment

// Express backend โ€” allow the host port the browser uses
app.use(cors({ origin: [ 'http://localhost:3000', // browser access via host port mapping 'http://frontend:3000', // container-to-container (if needed) ], credentials: true,
}));
Test your Docker CORS config โ†’