First of all I'm new to Nginx, Docker and Kubernetes so I may made an obvious mistake but after a complete week of searching and trying stuffs, I'm facing the same error. Also, I've seen other similar questions exists but unfortunately the provided solutions does not fix my problem.
When I access my URL, I get a 502 Bad Gateway (nginx) message and when I log my nginx container from my pod, it returns this:
[error] 7#7: *102 connect() failed (111: Connection refused) while connecting to upstream, client: <ip_address>, server: _, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:9000/", host: <host_name>
My project uses Next JS 14. I'm running 3 pods and each pod has two containers: my-project-nextjs
and my-project-nginx
(the default container).
For the Docker part, I've tried different configurations. My application is in a monorepo using turbo so I follow this documentation to create my Dockerfile:
FROM node:20.9.0-alpine AS base
FROM base AS builder
RUN apk update
RUN apk add --no-cache libc6-compat
WORKDIR /app
RUN yarn global add turbo
COPY . .
RUN turbo prune @monorepo/my-project --docker
FROM base AS installer
RUN apk update
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY --from=builder /app/out/json/ .
RUN yarn install
COPY --from=builder /app/out/full/ .
COPY --from=builder /app/tsconfig.json ./tsconfig.json
RUN yarn turbo run build --filter=@monorepo/my-project
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
USER nextjs
COPY --from=installer --chown=nextjs:nodejs /app/apps/my-project/.next/standalone ./
COPY --from=installer --chown=nextjs:nodejs /app/apps/my-project/.next/static ./apps/my-project/.next/static
COPY --from=installer --chown=nextjs:nodejs /app/apps/my-project/public ./apps/my-project/public
EXPOSE 9000
ENV PORT 9000
CMD node apps/my-project/server.js
For the Dockerfile of nginx, I have tried debian:strech-line
and nginx:stable-alpine
: the result is the same, error 502. Here is the debian version:
FROM debian:stretch-slim
ENV DEBIAN_FRONTEND="noninteractive" \
TERM="xterm"
RUN echo "deb http://archive.debian.org/debian stretch main contrib non-free" > /etc/apt/sources.list
RUN apt-get update && apt-get upgrade -y &&\
apt-get install -y nginx-light
RUN echo "Acquire::http {No-Cache=True;};" > /etc/apt/apt.conf.d/no-cache &&\
apt-get -q update && \
apt-get -qy dist-upgrade && \
apt-get install -qy \
nginx-light \
nano \
&& \
apt-get -y autoremove && \
apt-get -y clean && \
rm -rf /var/lib/apt/lists/*
COPY .docker/nginx/nginx.conf /etc/nginx/nginx.conf
RUN rm -v /etc/nginx/sites-enabled/default
ADD .docker/nginx/sites-enabled /etc/nginx/sites-enabled
ADD .docker/nginx/conf.d /etc/nginx/conf.d
COPY . /app
WORKDIR /app
CMD ["nginx"]
My application configuration is, I suppose, really basic:
server {
listen 80;
server_name _;
root /app/apps/my-project/.next;
location / {
proxy_pass http://localhost:9000;
}
location /nginx-health {
access_log off;
return 200 "OK\n";
}
}
When I check my pods status, they are all running. My container my-project-nextjs
return this log:
▲ Next.js 14.2.3
- Local: http://<pod_name>:9000
- Network: http://<ip_address>:9000
✓ Starting...
✓ Ready in 161ms
So I suppose my Next JS Docker image is correct.
My container my-project-nginx
returns this log (after I tried to reach my website from its URL):
[error] 7#7: *102 connect() failed (111: Connection refused) while connecting to upstream, client: <ip_address>, server: _, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:9000/", host: <host_name>
From other solutions on SO, I thought the problem comes from the PORT or the proxy_pass. The PORT looks good to me so I don't know what I could tried. For the proxy_pass, I've tried to replace my current value (proxy_pass http://localhost:9000;
) with http://127.0.0.1:9000
, http://0.0.0.0:9000
or create an upstream (but if I'm right, it's when the containers are not in the same pod).
Do you have any ideas why I get a 502 error message?
EDIT and SOLUTION:
Here is my deployment code:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-project-deployment
labels:
app: my-project
namespace: beta
spec:
replicas: 2
selector:
matchLabels:
name: my-project
template:
metadata:
labels:
name: my-project
spec:
containers:
- name: my-project-nginx
image: <my_image>
imagePullPolicy: Always
ports:
- containerPort: 80
env:
- name: PORT
value: "80"
resources:
limits:
memory: 768Mi
requests:
memory: 256Mi
readinessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 15
periodSeconds: 20
successThreshold: 1
failureThreshold: 3
- name: my-project-nextjs
image: <my_image>
imagePullPolicy: Always
ports:
- containerPort: 9000
env:
- name: PORT
value: "9000"
- name: DD_AGENT_HOST
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: DD_SERVICE_NAME
value: "my-project-beta"
resources:
limits:
memory: 1Gi
requests:
memory: 512Mi
readinessProbe:
tcpSocket:
port: 9000
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 9000
initialDelaySeconds: 15
periodSeconds: 20
successThreshold: 1
failureThreshold: 3
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: <name>
---
apiVersion: v1
kind: Service
metadata:
name: my-project
namespace: beta
labels:
name: my-project
spec:
type: ClusterIP
ports:
- name: nginx-container
port: 80
targetPort: 80
- name: nextjs-container
port: 9000
targetPort: 9000
selector:
name: my-project
I manage to make the thing works by opening the port 9000. I've changed the proxy_pass
to my service name my-project
and add this part to fix my problem:
- name: nextjs-container
port: 9000
targetPort: 9000
In the configuration Instead of localhost, use the Kubernetes service name that exposes the my-project-nextjs container. Update it as below
location / {
proxy_pass http://<service_name>:9000;
}
The service should be something as below
apiVersion: v1
kind: Service
metadata:
name: my-project-nextjs-service
spec:
selector:
app: my-project-nextjs
ports:
- protocol: TCP
port: 9000
targetPort: 9000
Also make sure that there is a Kubernetes Service that exposes the my-project-nextjs container. And check with the below command, whether Kubernetes service is reachable from the my-project-nginx container
kubectl exec -it <nginx-pod-name> -- curl http://<service_name>:9000