NextJS 符号链接未更新并导致 Kubernetes 部署中的应用程序崩溃

问题描述 投票:0回答:1

简介

我有 NextJS 应用程序的 Kubernetes 部署,我想在开发模式下运行该应用程序,以便更新文件会导致应用程序立即热重载,特别是我想只更新“config”文件夹中的一些 JSON 文件。我创建了一个 docker 容器,它复制除“配置文件”之外的必要文件,配置文件使用 Kubernetes ConfigMaps 附加到容器,作为卷安装。

我在 Windows WSL2 上的 minikube 上运行。

问题

当我第一次运行容器时,它工作正常,但如果我导航到某些页面或更改配置映射中的值,我会收到此错误(或使用不同文件的错误,如

PlanModel.config.json
):

> @ dev-base /usr/src/app
> next dev

▲ Next.js 14.2.3

- Local: http://localhost:3000

✓ Starting...
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out
if you'd not like to participate in this anonymous program, by visiting the following URL:https://nextjs.org/telemetry

✓ Ready in 3s
○ Compiling /middleware ...
✓ Compiled /middleware in 2.3s (216 modules) ○ Compiling / ...
Browserslist: caniuse-lite is outdated. Please run:
npx update-browserslist-db@latest
Why you should do it regularly: https://github.com/browserslist/update-db#readme  
 ✓ Compiled / in 18.6s (4401 modules)
cookie is: undefined
GET / 200 in 19523ms
✓ Compiled in 1339ms (1847 modules)
cookie is: undefined
GET / 200 in 68ms
cookie is: undefined
GET / 200 in 46ms
cookie is: undefined
GET / 200 in 37ms
⨯ ./config/ai/..2024_09_30_15_42_23.830652425/actions.config.json
Module build failed: Error: ENOENT: no such file or directory, open '/usr/src/app/config/ai/..2024_09_30_15_42_23.830652425/actions.config.json'

Import trace for requested module:
./config/ai/..2024_09_30_15_42_23.830652425/actions.config.json
./lib/chat/actions.config.tsx
./lib/chat/actions.tsx
./app/(chat)/page.tsx

有时,应用程序不会立即收到此错误,而是继续工作,但没有热重载。

在这两种情况下,我都在容器中打开了一个 shell,并手动验证了文件是否存在且正确。

可能的问题

我注意到 Kubernetes 为 configmap 中的文件创建了符号链接。特别是,符号链接是这样的:

actions.config.json -> ..data/actions.config.json -> ..2024_09_30_15_42_23.830652425/actions.config.json

我发现 NextJS 在开发模式下跟踪符号链接存在问题,因为 webpack (https://github.com/vercel/next.js/issues/53175, https://github.com/webpack/手表包/拉/232)。我不知道如何解决这个问题。我想我可以使用不创建符号链接的不同 Kubernetes 方法(但我仍然需要可以轻松更新配置文件),或者解决这个 NextJS 问题。

更多背景

我想构建一个平台,允许用户通过更改一些“配置文件”(实际上是 JSON 文件)来自定义 NextJS 应用程序。这些配置文件由 NextJS 应用程序(静态)导入,并确定应用程序的颜色、样式和行为。这样我的用户就可以访问显示以下内容的编辑器:

  • 他们的定制应用程序的最终(生产)版本:这将部署到全世界
  • 定制应用程序的预览(开发)版本:用户将看到该版本作为实际应用程序的预览,并且在用户编辑应用程序时自动刷新

我没有创建一个与我已经创建的略有不同的新 NextJS 应用程序,并且为了允许实时更改,我只是决定在开发模式下运行它。

无论如何,“最终版本”和“预览版本”都必须大规模运行,我决定使用 kubernetes。我创建了一个 API,可以动态生成两个版本的 kubernetes 清单。

我遇到的问题是预览版本,我有这个缩短的示例文件:

apiVersion: v1
kind: Namespace
metadata:
  labels:
    app_id: myId
    app_subdomain: testapp
  name: myId
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-environment
  namespace: myId
data:
  # App configuration
  APP_ID: myId

  # Postgres database, MongoDB database, etc env variables
---
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app_id: myId
    app_subdomain: testapp
  name: app-config
  namespace: myId
data:
  theme.config.json: |
    CONTENT
---
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app_id: myId
    app_subdomain: testapp
  name: app-config-ai
  namespace: myId
data:
  actions.config.json: |
    CONTENT
---
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app_id: myId
    app_subdomain: testapp
  name: app-config-components
  namespace: myId
data:
  button-scroll-to-bottom.config.json: |
    CONTENT
  chat-history.config.json: |
    CONTENT
  chat-message-actions.config.json: |
    CONTENT
---
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app_id: myId
    app_subdomain: testapp
  name: app-config-components-ui
  namespace: myId
data:
  sheet.config.json: |
    CONTENT
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app_id: myId
    app_subdomain: testapp
  name: app
  namespace: myId
spec:
  replicas: 1
  selector:
    matchLabels:
      app_id: myId
  template:
    metadata:
      labels:
        app_id: myId
        app_subdomain: testapp
    spec:
      containers:
        - name: nginx
          image: my-nginx:latest
          imagePullPolicy: Always
          ports:
            - containerPort: 80
        - name: app
          image: my-app-configurable:latest
          imagePullPolicy: Always
          envFrom:
            - configMapRef:
                name: app-environment
          ports:
            - containerPort: 3000
          volumeMounts: # /usr/src/app/ is the root directory of the app in the container
            - name: app-config
              mountPath: /usr/src/app/config
            - name: app-config-ai
              mountPath: /usr/src/app/config/ai
            - name: app-config-components
              mountPath: /usr/src/app/config/components
            - name: app-config-components-ui
              mountPath: /usr/src/app/config/components/ui
      volumes:
        - name: app-config
          configMap:
            name: app-config
        - name: app-config-ai
          configMap:
            name: app-config-ai
        - name: app-config-components
          configMap:
            name: app-config-components
        - name: app-config-components-ui
          configMap:
            name: app-config-components-ui
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app_id: myId
    app_subdomain: testapp
  name: nginx-service
  namespace: myId
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app_id: myId
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app_id: myId
    app_subdomain: testapp
  name: app
  namespace: myId
spec:
  ports:
    - port: 3000
      protocol: TCP
      targetPort: 3000
  selector:
    app_id: myId
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  labels:
    app_id: myId
    app_subdomain: testapp
  name: nginx
  namespace: myId
spec:
  rules:
    - host: testapp.zshape.ai
      http:
        paths:
          - backend:
              service:
                name: nginx-service
                port:
                  number: 80
            path: /
            pathType: Prefix

这是在我的 NextJS 应用程序中导入 JSON 文件的示例:

import rawConfig from '@/config/components/empty-screen.config.json'

interface ComponentConfig {
  [key: string]: any
  title?: string
  description?: string
  linkURL?: string
  linkLabel?: string
}

const { title, description, linkURL, linkLabel }: ComponentConfig = rawConfig

export const emptyScreenConfig = {
  title,
  description,
  linkURL,
  linkLabel
}

然后导出的

emptyScreenConfig
会导入到应用程序的其他部分。

node.js typescript kubernetes next.js webpack
1个回答
0
投票

我通过使用

next dev --turbo
解决了这个问题,它使用 Turbopack 而不是 Webpack。就我而言,我使用金丝雀版本的
next
和测试版
next-auth
,因为当前稳定版本不支持某些功能。

© www.soinside.com 2019 - 2024. All rights reserved.