Next.js Discord

Discord Forum

Nginx, Next.js and API in docker containers

Answered
Chinese softshell turtle posted this in #help-forum
Open in Discord
Chinese softshell turtleOP
Hello, its my first time dealing with such "issue".
I had error when making a request in development to my API from the server side of next.js (connection refused)

On the browser i am making requests such as http://localhost/api/... those directly point to my API server
But on the next.js's server enviroment for example page.tsx doing so fails. I had to make request to my API via http://{nginx_service_name}/api...

Is this how it should be?
Do i need 1 env variable for the browser and 1 env variable for the server side of next.js?
Am i understanding correctly, that on the browser i must use the domain example.com/api ,and on the server i should use the nginx service name?

Thank you!
Answered by B33fb0n3
alr, when its a 100% seperate backend, then yes the connection is via the external way if they are not in a docker network. When they are both in a docker network: great! Use the docker network alias and handle it like that. Else use the external way instead of referencing on something like nginx (the external way alr does that)
View full answer

16 Replies

Chinese softshell turtleOP
I am just trying to use http://localhost/api as base url for my API(i have separate backend server)
while this URL(http://localhost/api) works on the client, it doesnt work on the server side of next.js

  // this doesn't work on the server side of next.js
  // NEXT_PUBLIC_API_URL=http://localhost/fastapi
  await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/me`)
  
  // this does work on the server side of next.js
  // INTERNAL_API_URL=http://nginx/fastapi
  await fetch(`${process.env.INTERNAL_ADMIN_URL}/auth/me`)


This is what happens if i use process.env.NEXT_PUBLIC_API_URL on the server side
fight-recap-client  | [TypeError: fetch failed] {
fight-recap-client  |   [cause]: Error: connect ECONNREFUSED 127.0.0.1:80
fight-recap-client  |       at <unknown> (Error: connect ECONNREFUSED 127.0.0.1:80) {
fight-recap-client  |     errno: -111,
fight-recap-client  |     code: 'ECONNREFUSED',
fight-recap-client  |     syscall: 'connect',
fight-recap-client  |     address: '127.0.0.1',
fight-recap-client  |     port: 80
fight-recap-client  |   }
fight-recap-client  | }


I hope i gave the correct minimal context
Answer
Chinese softshell turtleOP
Feels weird having 2 endpoints. 1 for external(clients) and 1 for internal(docker network)

i guess this is how it is. First time i am actually doing something like that with docker
its great to work like that with docker network ^^
And yes, its the normal way. If you want to remove comlexity, place backend AND frontend in nextjs. Or migrate away from nextjs as nextjs would else have too much complexity, that its not needed
Chinese softshell turtleOP
i am learning docker and fastapi, thats why i went like that.
What would you suggest to migrate to anyway?
@Chinese softshell turtle i am learning docker and fastapi, thats why i went like that. What would you suggest to migrate to anyway?
IMO nextjs helps a lot when needing a backend: serverside first, route handlers, server actions, ... and a small part of it is react for the frontend. But when you alr have a good external backend: why needing nextjs. I guess then I would migrate away from nextjs to react and then react router or tanqstack router
Chinese softshell turtleOP
i am not guru in react, but i am using next for its ISR(this is very powerful when many people enter the website at the same time) and SSR. I dont know if pure react can do that. I am building a "media"ish web app

Also can security exists in pure react such as "you are not allowed to this route"?
@Chinese softshell turtle i am not guru in react, but i am using next for its ISR(this is very powerful when many people enter the website at the same time) and SSR. I dont know if pure react can do that. I am building a "media"ish web app Also can security exists in pure react such as "you are not allowed to this route"?
its ISR
yea ISR is very powerfull especially when it comes time based revaldiation or on demand revalidation...

Also can security exists in pure react such as "you are not allowed to this route"?
more or less. The content that will be displayed there would've been fetched from the backend. For example a route only for admins can be rendered clientside, but for getting any actual data, the frontend would make a req. to the backend to get data and ofc sends their credentials with it
happy to help
Chinese softshell turtleOP
@B33fb0n3 Hello! Sorry for pinging you.

I have a docker"ish" question about the same issue.

this is my local nginx config
server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://client:3000;
        ...
    }

    location /fastapi/ {
        proxy_pass http://server:8000/;
        ...
    }
}


And this is my prod nginx config

server {
    listen 80;
    server_name _;
    return 301 https://$host$request_uri;
}

# Frontend: example.com (HTTPS)
server {
    listen 443 ssl http2;
    server_name example.com;
    ...

    location / {
        proxy_pass http://client:3000;
    }
}

server {
    listen 443 ssl http2;
    server_name api.example.com;
    ...

    location / {
        proxy_pass http://server:8000;
        ...
    }
}


My question is when i use the server side of next.js aka server components how am i going to reach my api server?
The only way i currently see it is to call http://server:8000 ,but i dont know if this is a bad practice, since we are skipping nginx.
locally i can use nginx/fastapi, but with my production config i cannot do that. I really want to see your opinion
@Chinese softshell turtle locally i can use nginx/fastapi, but with my production config i cannot do that. I really want to see your opinion
when I would have the option to use the docker network in both cases (prod & staging), I would do that. I wouldnt want the extra roundtrip through dns server, then to your server and then through nginx to finally land at the same location. So its fine to do that 👍
Chinese softshell turtleOP
So in both scenarios i can just use the server service name instead of nginx, correct?
But externally(on the client) i use the domain/localhost and internally i just go with the server service name
I also wonder how do people deal with the builds and images (i will call it cache) that is going to be stored on the disk. This thing grows fast. Do i just run a cronjob to clean that?
Egyptian Mau
From all your queries i understand, this is your current setup, right?

How you connect the frontend (FE) or other services to API depends on where the request is originating from. Few common scenarios

1. Frontend (client-side) -> API
If the request is coming from the client-side FE, use the Nginx route i.e access the API through the configured domain/subdomain. (Ignoring the proxy options available in Next.js for now)

2. Service-to-service (internal) -> API
I believe this i the scenario you are referring to. In this case, you shouldn't route the request through Ngnix since that is meant for external traffic. Instead the services should communicate directly over the internal network. This is recommended approach and is typically much faster.