首页 > 解决方案 > Docker容器上的Next.js API URL问题

问题描述

我的问题是:

我用 Next.js 做了一个简单的网页。我从 /pages/api/ 端点以 JSON 格式获取一些内容,并将其显示在页面和组件中。在本地编译(npm run dev 或 npm run start)没问题。当我在 Windows 10 上的 Docker 上运行它时,我再也没有问题了。这适用于 Heroku 和 Vercel。我遇到的问题是:我把项目交给了 Devops 团队,他们在 Docker 上运行它。他们还将一个域定向到该项目。但是 api 端点毫无意义地尝试访问 ID URL。当我从 Chrome Devtools 中查看时,它看起来像这样:

http://013cfdde4910:3000/api/en/brands

我收到以下错误作为控制台消息。

混合内容:“https://beta..com/technologies”页面通过 HTTPS 加载,但请求了不安全的资源“http://013cfdde4910:3000/api/en/menu”。此请求已被阻止;内容必须通过 HTTPS 提供。

实际上应该是 http://localhost:3000/api/en/brands。我不明白这里的 013cfdde4910 来自哪里以及为什么。

我检查了它是否在代码中。我查看了来自 Google Devtools 的 Live 项目的 Source,即 Devops 团队发布的项目。

_next/static > 块 > 页面 > _app-eac17e226e00cc01a313.js

当我在这里搜索时,我在 3 个地方找到了 013cfdde4910 字符串。为什么建的时候会来这里?

例如,缩小后的代码如下。

.... return(0,u.useEffect)((function(){fetch("".concat("http://013cfdde4910:3000","/api/").concat(t.locale,"/) brands")).....

我可以在本地构建中将其视为 localhost,当我在 Windows 10 Docker 中发布它并查看时。那么是什么导致了 localhost -> 013cfdde4910 转换,我该如何解决呢?

我使用的 Dockerfile:

FROM node:current-alpine as base
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .

FROM base AS build
ENV NODE_ENV=production
WORKDIR /build
COPY --from=base /app ./
RUN npm run build

FROM node:current-alpine AS production
ENV NODE_ENV=production
WORKDIR /app
COPY --from=build /build/package*.json ./
COPY --from=build /build/.next ./.next
COPY --from=build /build/public ./public

RUN npm install

EXPOSE 3000
CMD npm run start

我使用 docker-compose.yml

version: "3"
services:
  ui:
    container_name: web
    restart: always
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    volumes:
      - ./:/app
      - /app/node_modules
      - /app/.next
    env_file:
      - .env

这是 next.config.js

module.exports = {
  webpackDevMiddleware: (config) => {
    config.watchOptions = {
      poll: 1000,
      aggregateTimeout: 300,
    };
    return config;
  },
  async headers() {
    return [
      {
        source: "/api/:path*",
        headers: [
          { key: "Access-Control-Allow-Credentials", value: "true" },
          { key: "Access-Control-Allow-Origin", value: "*" },
          {
            key: "Access-Control-Allow-Methods",
            value: "GET,OPTIONS,PATCH,DELETE,POST,PUT",
          },
          {
            key: "Access-Control-Allow-Headers",
            value:
              "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
          },
        ],
      },
    ];
  },
  reactStrictMode: true,
  generateEtags: false,
  i18n: {
    locales: ["en", "tr"],
    defaultLocale: "en",
    localeDetection: false,
  },
  env: {
    VERSION: process.env.VERSION,
    MODE: process.env.MODE,
    APP_NAME: process.env.APP_NAME,
    HOST: process.env.HOST,
    HOSTNAME: process.env.HOSTNAME,
    PORT: process.env.PORT,
    GA_TRACKING_ID: process.env.GA_TRACKING_ID,
  },
  generateBuildId: async () => {
    return new Date().toDateString();
  },
  eslint: {
    ignoreDuringBuilds: false,
  },
};

标签: dockerapinext.js

解决方案


感谢您发布配置,看来主机名被抓取为 docker 容器 ID - 您没有发布实际的获取代码,但我的猜测是 - 使用了这个环境变量。

   `HOSTNAME: process.env.HOSTNAME`

它要么作为环境变量传递,要么被解释为容器 ID,您需要一种方法来创建domain:3000/api/brands可能是 Docker 部署的一部分,可能是 nginx 代理。


推荐阅读