NextJS TypeError: не удалось получить данные. код: «ECONNREFUSED» из Docker

Я запускаю приложение Next.js в Docker. Однако при вызове моего API я получаю следующую ошибку

TypeError: fetch failed
   at node:internal/deps/undici/undici:13178:13
   at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
   at async m (/app/.next/server/chunks/961.js:3:716)
   at async b (/app/.next/server/pages/user/administration.js:51:1030)
   at async e3 (/app/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected][email protected]/node_modules/next/dist/compiled/next-server/pages.runtime.prod.js:31:594)
   at async doRender (/app/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected][email protected]/node_modules/next/dist/server/base-server.js:1425:30)
   at async cacheEntry.responseCache.get.routeKind (/app/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected][email protected]/node_modules/next/dist/server/base-server.js:1599:28)
   at async NextNodeServer.renderToResponseWithComponentsImpl (/app/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected][email protected]/node_modules/next/dist/server/base-server.js:1507:28)
   at async NextNodeServer.renderPageComponent (/app/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected][email protected]/node_modules/next/dist/server/base-server.js:1924:24)
   at async NextNodeServer.renderToResponseImpl (/app/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected][email protected]/node_modules/next/dist/server/base-server.js:1962:32) {
 [cause]: AggregateError [ECONNREFUSED]:
     at internalConnectMultiple (node:net:1118:18)
     at afterConnectMultiple (node:net:1685:7)
     at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
   code: 'ECONNREFUSED',
   [errors]: [ [Error], [Error] ]

Это происходит только при вызове API из getServerSideProps. При вызове со стороны клиента все работает как положено, включая аутентифицированные и общедоступные вызовы API.

API создан на базе .NET Core и работает на localhost:5068 (не в Docker). Приложение Next работает на localhost:3050 из Docker.

Все работает так, как ожидалось, когда я запускаю приложение Next локально. Итак, я предполагаю, что мне нужна некоторая конфигурация где-то в Next (или .NET API), чтобы выполнить успешный вызов из getServerSideProps, когда Next работает в контексте Docker.

Докерфайл

FROM node:22.4-alpine AS base

FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json pnpm-lock.yaml* ./
RUN corepack enable pnpm && pnpm i --frozen-lockfile

FROM base AS builder
ENV NEXT_PRIVATE_STANDALONE true
ENV NEXT_PUBLIC_BACKEND_ROOT_URI http://localhost:5068
ENV NEXT_PUBLIC_FRONTEND_URI http://localhost:3050
WORKDIR /app
COPY . .
COPY --from=deps /app/node_modules ./node_modules
RUN corepack enable pnpm && pnpm run build

FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
RUN mkdir .next
RUN chown nextjs:nodejs .next
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3050
ENV PORT 3050
CMD HOSTNAME = "0.0.0.0" node server.js

Докер Составление

services:
  sweetnotes.fe:
    image: myimage
    container_name: mycontainer
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - '3050:3050'
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Kubernetes - это портативная, расширяемая платформа с открытым исходным кодом для управления контейнерными рабочими нагрузками и сервисами, которая...
Как создать PHP Image с нуля
Как создать PHP Image с нуля
Сегодня мы создадим PHP Image from Scratch для того, чтобы легко развернуть базовые PHP-приложения. Пожалуйста, имейте в виду, что это разработка для...
0
0
122
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

По умолчанию контейнеры Docker запускаются в виртуальной сети Docker, созданной Docker для изоляции контейнеров от хоста. Для сетевых целей вы можете рассматривать каждый контейнер как отдельную машину. А localhost в контейнере означает сам контейнер.

Чтобы получить доступ к хосту из контейнера, вам необходимо добавить хост к известным именам хостов контейнера, используя extra_hosts в вашем файле компоновки. В качестве имени хоста обычно используют имя host.docker.internal.

В вашем случае это будет выглядеть так

services:
  sweetnotes.fe:
    image: myimage
    container_name: mycontainer
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - '3050:3050'
    extra_hosts:
      - 'host.docker.internal:host-gateway'

Затем вы можете изменить URL-адрес бэкэнда на

ENV NEXT_PUBLIC_BACKEND_ROOT_URI http://host.docker.internal:5068

в вашем Dockerfile, и он должен работать после восстановления образа.

Спасибо. Добавление extra_hosts и изменение внутреннего URI на http://host.docker.internal:5068 решает проблему, когда Next вызывает серверную часть API из getServerSideProps. Однако клиентская часть перестала работать. Мне пришлось создать две переменные среды: одну для использования на стороне сервера и одну на стороне клиента, и соответствующим образом обработать их в коде JS. NEXT_PUBLIC_BACKEND_CLIENT_SIDE_ROOT_URI http://localhost:5068 и NEXT_PUBLIC_BACKEND_SERVER_SIDE_ROOT_URI http://host.docker.internal:5068 Знаете, почему такое поведение?

esausilva 16.07.2024 15:58

Это потому, что клиент работает в браузере на хост-компьютере. Отсюда адрес localhost. Контейнер работает в сети Docker Bridge, и оттуда хост имеет другой адрес.

Hans Kilian 17.07.2024 14:51

Имеет смысл. Большое спасибо!

esausilva 17.07.2024 15:07

Другие вопросы по теме