skip to Main Content

I have NodeJS api and NextJS application in Separate docker containers when I’m in host machine its working fine, but when I’m running inside docker containers its giving CORS error.

My express config in API

app.use(cors({
    credentials: true,
    origin: 'http://localhost:3000/' // Allowing front-end running port 3000
}));

app.use(cookieParser());
app.use(bodyParser.json());
app.use(urlencoded({ extended: true }));
app.use(json());
app.enable("trust proxy");
app.use(methodOverride());

In front-end APP NextJS axios config

const axiosInstance = axios.create({ baseURL: 'http://localhost:4000/', withCredentials: true });

enter image description here

enter image description here

Its woking fine when im running API from host machine, with same configuration its giving CORS error in Docker.

4

Answers


  1. Add each localhost + port to the cors options (I left some other options just for example, not relevant to your question though):

    //options for cors midddleware
    const options: cors.CorsOptions = {
        allowedHeaders: [
            'X-ACCESS_TOKEN',
            'Access-Control-Allow-Origin',
            'Authorization',
            'Origin',
            'x-requested-with',
            'Content-Type',
            'Content-Range',
            'Content-Disposition',
            'Content-Description',
        ],
        credentials: true,
        methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
        origin: [
            'http://localhost:5001',
            'http://localhost:50000',
        ],
        preflightContinue: false,
    };
    
    const app = express();
    
    const corsOpts = cors(options);
    
    //add cors middleware
    app.use(corsOpts);
    
    Login or Signup to reply.
  2. This is common issue many solutions.

    The correct solution depends on your requirements.The simpler solution is to run the docker container with NGINX acting as reverse proxy.

    Example of nginx docker

    FROM nginx:alpine
    
    WORKDIR /etc/nginx
    COPY ./nginx.conf ./conf.d/default.conf
    EXPOSE 80
    ENTRYPOINT [ "nginx" ]
    CMD [ "-g", "daemon off;" ]
    

    Build it as cors

    docker build -t cors .
    

    Finally make sure that nginx.conf allowing origins from request

    add_header 'Access-Control-Allow-Origin' '*';
    

    Example of nginx.config

    upstream api {
      # Could be host.docker.internal - Docker for Mac/Windows - the host itself
      # Could be your API in a appropriate domain
      # Could be other container in the same network, like container_name:port
      server url:port;
    }
    
    server {
      listen 80;
      server_name localhost;
    
      location / {
    
        if ($request_method = 'OPTIONS') {
          add_header 'Access-Control-Max-Age' 1728000;
          add_header 'Access-Control-Allow-Origin' '*';
          add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,
          X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
          add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
          add_header 'Content-Type' 'application/json';
          add_header 'Content-Length' 0;
          return 204;
        }
    
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,
        X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
        add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
    
        proxy_pass http://api/;
      }
    }
    
    Login or Signup to reply.
  3. Add this line to your package.json file. then rebuild your container and start the app.

    "proxy": "http://localhost:4000",
    
    Login or Signup to reply.
  4. As i can see your API configuration seems correct, but in your NextJS create pages/api/whatever.js and call your API from handler

    import axios from 'axios';
    axios.defaults.withCredentials = true;
    
    export default async function handler(req, res){
       try {
         const response = axios.post('http://localhost:4000/<your_login_api_URL>', req.body)
       }catch(error) {
         // handle error here
       }
    
    }
    

    this will work and its safer way to mask your back end API calls from front end.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search