Прежде всего, я новичок в Nginx, Docker и Kubernetes, поэтому, возможно, я допустил очевидную ошибку, но после целой недели поиска и проб я столкнулся с той же ошибкой. Кроме того, я видел и другие подобные вопросы, но, к сожалению, предложенные решения не решили мою проблему.
Когда я обращаюсь к своему URL-адресу, я получаю сообщение 502 Bad Gateway (nginx), и когда я регистрирую свой контейнер nginx из своего модуля, он возвращает следующее:
[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>
В моем проекте используется Next JS 14. Я использую 3 модуля, и каждый модуль имеет два контейнера: my-project-nextjs
и my-project-nginx
(контейнер по умолчанию).
Что касается Docker, я пробовал разные конфигурации. Мое приложение находится в монорепозитории с использованием Turbo, поэтому я следую этой документации, чтобы создать свой 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
Для Dockerfile nginx я попробовал debian:strech-line
и nginx:stable-alpine
: результат тот же, ошибка 502. Вот версия Debian:
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"]
Конфигурация моего приложения, я полагаю, очень проста:
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";
}
}
Когда я проверяю состояние своих модулей, они все работают. Мой контейнер my-project-nextjs
возвращает этот журнал:
▲ Next.js 14.2.3
- Local: http://<pod_name>:9000
- Network: http://<ip_address>:9000
✓ Starting...
✓ Ready in 161ms
Поэтому я полагаю, что мой образ Next JS Docker правильный.
Мой контейнер my-project-nginx
возвращает этот журнал (после того, как я попытался перейти на свой сайт по его 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>
Судя по другим решениям SO, я думал, что проблема связана с ПОРТОМ или proxy_pass. ПОРТ мне кажется хорошим, поэтому я не знаю, что можно попробовать. Для proxy_pass я попытался заменить свое текущее значение (proxy_pass http://localhost:9000;
) на http://127.0.0.1:9000
, http://0.0.0.0:9000
или создать восходящий поток (но, если я прав, это когда контейнеры находятся в разных модулях).
Есть ли у вас идеи, почему я получаю сообщение об ошибке 502?
РЕДАКТИРОВАТЬ и РЕШЕНИЕ:
Вот мой код развертывания:
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
Мне удалось заставить эту штуку работать, открыв порт 9000. Я изменил proxy_pass
на имя своей службы my-project
и добавил эту часть, чтобы решить мою проблему:
- name: nextjs-container
port: 9000
targetPort: 9000
В конфигурации вместо localhost используйте имя службы Kubernetes, которое предоставляет контейнер my-project-nextjs. Обновите его, как показано ниже
location / {
proxy_pass http://<service_name>:9000;
}
Сервис должен быть примерно таким, как показано ниже.
apiVersion: v1
kind: Service
metadata:
name: my-project-nextjs-service
spec:
selector:
app: my-project-nextjs
ports:
- protocol: TCP
port: 9000
targetPort: 9000
Также убедитесь, что существует служба Kubernetes, которая предоставляет контейнер my-project-nextjs. И с помощью приведенной ниже команды проверьте, доступен ли сервис Kubernetes из контейнера my-project-nginx.
kubectl exec -it <nginx-pod-name> -- curl http://<service_name>:9000