I’m having a NextJS frontend application and NodeJS backend application. Both are deployed on Kubernetes. Frontend application Dockerfile looks like below.
FROM node:18.17.1-alpine
WORKDIR /app
COPY package*.json .
RUN npm i
COPY . .
RUN npm run build
CMD ["npm", "run", "start"]
EXPOSE 3000
And then Frontend application’s next.config.mjs
looks like below.
/** @type {import('next').NextConfig} */
const nextConfig = {
// distDir: "build",
images: {
domains: ["localhost", "frontend-app-URL"],
},
compiler: {
removeConsole: process.env.NODE_ENV === "production",
},
async rewrites() {
console.log("NEXT_PUBLIC_SERVER_URL:", process.env.NEXT_PUBLIC_SERVER_URL); // Log to debug
return [
{
source: "/api/:path*",
destination: `http://${process.env.NEXT_PUBLIC_SERVER_URL}/:path*`,
},
];
},
};
export default nextConfig;
And inside .env file, I have
NEXT_PUBLIC_SERVER_URL="http://backend:9001"
NEXT_PUBLIC_API_ENDPOINT="http://localhost:3000/api"
NEXT_PUBLIC_URL="http://localhost:3000/"
NODE_ENV="development"
So NEXT_PUBLIC_SERVER_URL="http://backend:9001"
is the Kubernetes service.
All the Kubernetes ingresses are set up and when I access the frontend login page using the URL it loads as expected. But when I provides the username and the password for the login page it shows below error:
POST https://my-url/api/login 500 (Internal Server
Error)And when I see the pod logs it shows
[email protected] start │ │ > next start
│ │
│ │ ▲ Next.js 14.1.0
│ │ – Local: http://localhost:3000
│ │
│ │ ✓ Ready in 627ms
│ │ TypeError: Expected “9001” to be a string
│ │ at
/app/node_modules/next/dist/compiled/path-to-regexp/index.js:237:19
│ │ at prepareDestination
(/app/node_modules/next/dist/shared/lib/router/utils/prepare-destination.js:209:18)
│ │ at handleRoute
(/app/node_modules/next/dist/server/lib/router-utils/resolve-routes.js:501:94)
│ │ at resolveRoutes
(/app/node_modules/next/dist/server/lib/router-utils/resolve-routes.js:539:34)
│ │ at process.processTicksAndRejections
(node:internal/process/task_queues:95:5)
│ │ at async handleRequest
(/app/node_modules/next/dist/server/lib/router-server.js:200:96)
│ │ at async requestHandlerImpl
(/app/node_modules/next/dist/server/lib/router-server.js:366:13)
│ │ at async Server.requestListener
(/app/node_modules/next/dist/server/lib/start-server.js:140:13)
Also, I am passing the env vars in Kubernetes
env:
- name: NEXT_PUBLIC_SERVER_URL # backend URL
value: "http://backend:9001"
- name: NEXT_PUBLIC_API_ENDPOINT #
value: "http://localhost:3000/api"
- name: NEXT_PUBLIC_URL
value: "https://my-frontend-url"
- name: NODE_ENV
value: "production"
Edited:
ClusterIP service for frontend
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: frontend
ports:
- protocol: TCP
port: 80
targetPort: 3000
And Ingress for frontend
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: frontend
annotations:
cert-manager.io/cluster-issuer: letsencrypt-production
spec:
ingressClassName: nginx
tls:
- hosts:
- my-url
secretName: my-secret
rules:
- host: my-url
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
And ClusterIP for backend
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector:
app: backend
ports:
- protocol: TCP
port: 9001
targetPort: 9001
And I have defined below in backend k8s deployment
ports:
- containerPort: 9001
And in frontend
ports:
- containerPort: 80
12