I have a dockerized app using Next.js and FastApi. Depending if fetch is called from client or server component different URLs need to be used.
Currently client components use
http://localhost:8000/
and server components
http://server:8000
How can this be fixed so the same URL can be used?
services:
db:
container_name: weatherdb
image: postgres
volumes:
- ./db_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- 5432:5432
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: pass
client:
container_name: client
build:
context: ./client
dockerfile: ./Dockerfile
volumes:
- ./client:/app
ports:
- 3000:3000
environment:
- NEXT_PUBLIC_PYTHON_API=http://server:8000
server:
container_name: server
build:
context: ./server
dockerfile: ./Dockerfile
volumes:
- ./server:/usr/src/app
ports:
- "8000:8000"
environment:
DB_NAME: weatherdb
DB_HOST: weatherdb
DB_PORT: 5432
DB_USER: postgres
DB_PASS: pass
depends_on:
- db
volumes:
db_data:
Client Dockerfile
FROM node:18-alpine
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
WORKDIR /app
EXPOSE 3000
CMD ["pnpm", "run", "dev"]
Server Dockerfile
FROM python:3
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
I have tried to use same URL for both server and client components. http://server/
in client component causes ERR_NAME_NOT_RESOLVED
.
http://localhost/
in client component results in the following stack trace
TypeError: fetch failed
at node:internal/deps/undici/undici:12625:11
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Debug (/app/.next/server/chunks/ssr/_85a404._.js:55:21)
How about selecting the right url dynamically within your application. Sample say.
export const getApiUrl = () => {
if (typeof window === 'undefined') {
// Server
return process.env.SERVER_PYTHON_API;
} else {
// Client
return process.env.NEXT_PUBLIC_PYTHON_API;
}
};
Then when making API calls, use the function to get the correct URL. Sample like
const fetchData = async () => {
const apiUrl = getApiUrl();
const response = await fetch(`${apiUrl}/your-endpoint`);
const data = await response.json();
return data;
};
With this you can work with both URL's. And update docker compose env with both url
environment:
- NEXT_PUBLIC_PYTHON_API=http://localhost:8000
- SERVER_PYTHON_API=http://server:8000