【问题标题】:Get Environment Variable Kubernetes on Next.js App在 Next.js 应用程序上获取环境变量 Kubernetes
【发布时间】:2020-11-30 16:47:55
【问题描述】:

我一直在阅读有关让 K8s 环境变量在 Next.js 应用程序中工作的其他问题,但到目前为止还没有被接受的答案。

我的应用在使用 .env.local 时运行良好,但在部署到 K8s 时出现错误(未定义)。

这是我的 next.config.js

module.exports = {
  env: {
    NEXT_PUBLIC_API_BASE_URL: process.env.NEXT_PUBLIC_API_BASE_URL,
  },
};

K8s 环境:

谁能帮我让那个环境变量在我的 next.js 应用程序上工作?

现在我做了一个简单的技巧,就是在dockerfile上添加ARG和ENV,然后在我构建docker镜像时注入它

Dockerfile:

ARG NEXT_PUBLIC_API_BASE_URL
ENV NEXT_PUBLIC_API_BASE_URL=${NEXT_PUBLIC_API_BASE_URL}

【问题讨论】:

  • 您在 Kubernetes 中看到的错误是什么?
  • @Rico 实际上不是错误,只是未定义的 NEXT_PUBLIC_API_BASE_URL
  • 收到该消息时,您的 pod 是崩溃了还是仍在运行?
  • @Rico 我的问题是如何从 next.js 应用程序读取在 kubernetes 上设置的环境变量,当尝试从客户端读取 process.env.NEXT_PUBLIC_API_BASE_URL 时我得到了未定义
  • 我想看看pod运行时是否可以调试

标签: docker kubernetes environment-variables next.js


【解决方案1】:

您应该将ENV_VARS 添加到.env.local 文件中。以configMap 的形式。 (https://nextjs.org/docs/basic-features/environment-variables)

在 Kubernetes 中,您可以像这样创建 configMap

apiVersion: v1
name: env-local
data:
  .env: |-
    NEXT_PUBLIC_API_URL=http:/your.domain.com/api
    API_URL=http://another.endpoint.com/serverSide
kind: ConfigMap

然后将configMap 作为文件挂载到部署中,然后在app/.env.local 上可用:


apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: your-app
  template:
    metadata:
      labels:
        app: your-app
    spec:
      containers:
      - image: your/image:latest
        imagePullPolicy: Always
        name: your-app
        ports:
        volumeMounts:
        - mountPath: /app/.env.local
          name: env-local
          readOnly: true
          subPath: .env.local
      volumes:
      - configMap:
          defaultMode: 420
          items:
          - key: .env
            path: .env.local
          name: env-local
        name: env-local


对于服务器端变量,同样有效的方法——至少对我而言——只是将它们作为常规环境变量添加到我的deployment:https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/#define-an-environment-variable-for-a-container

apiVersion: v1
kind: Pod
metadata:
  name: your-app
  labels:
    purpose: demonstrate-envars
spec:
  containers:
  - name: your-app-container
    image: gcr.io/google-samples/node-hello:1.0
    env:
    - name: DEMO_GREETING
      value: "Hello from the environment"
    - name: DEMO_FAREWELL
      value: "Such a sweet sorrow"

    const withSvgr = require('next-svgr');
    
    module.exports = {   
        // Will only be available on the server side
        serverRuntimeConfig: {
            API_URL: process.env.API_URL,
        },
        // Will be available on both server and client
        publicRuntimeConfig: {
            NEXT_PUBLIC_API_URL: process.env.API_URL,
        },
    };

【讨论】:

    【解决方案2】:

    我花了一整天的时间试验将我的 vars 放入下一个 js 应用程序的方法,而不是将它们暴露在 repo 中。上述线索都没有起到作用,与官方文档相同。我使用 GitLab CI/CD 构建阶段和 K8S 部署。最后让它像这样工作:

    1. 在 GitLab 中创建项目变量
    2. 在 .gitlab-ci.yml 中重建 .env.local(因为这是您获得 vars 的唯一点)
        - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
        - touch .env.local
        - echo "NEXT_PUBLIC_API_KEY='$NEXT_PUBLIC_API_KEY'" | cat >> .env.local
        ...
        - echo "NEXT_PUBLIC_MEASUREMENT_ID='$NEXT_PUBLIC_MEASUREMENT_ID'" | cat >> .env.local
        - docker build -t $IMAGE_TAG .
        - docker push $IMAGE_TAG
    

    【讨论】:

      【解决方案3】:

      TL;DR: next build && next start 来自容器内

      我还将 Next 与 Kubernetes 一起使用。但是,recent Next versions(我正在运行版本 11)environment variablesbuild time 中得到解决。我猜这是一个静态优化功能。

      为了利用 ConfigMap (几乎)即时更新应用程序的值,我最终在容器内的 next start 之前添加了一个 next build

      我的package.json 包含以下内容:

      {
        "scripts": {
          "start:docker": "next build && next start"
        }
      }
      

      缺点是应用程序容器需​​要更长的时间才能启动,但老实说,在 Next 为这个工作流程提供内置修复程序之前,我会坚持下去。

      请注意,因为您的容器需要更长的时间才能启动,请不要忘记配置您的 k8s readinessProbe

      编辑: 我意识到这种方法还有两个更大的缺点,因此我不推荐。

      1. 在构建期间资源使用会显着增加。在 k8s 上,超出内存限制会导致您的 pod 被杀死。
      2. pod 将具有不同的 JS 捆绑输出,例如/_next/static/chunks/pages/_app-.js 如果页面加载在一个 pod 中,而静态页面加载到另一个 pod 中,则会导致 404。

      【讨论】:

        【解决方案4】:

        我和你有同样的问题。您必须使用 NextJs 运行时配置: https://nextjs.org/docs/api-reference/next.config.js/runtime-configuration

        为了在本地运行,我使用了 dotenv。变量在本地时设置在 .env 中。在服务端,使用configMap中定义的环境变量。

        例子:

        publicRuntimeConfig: {
          NEXT_PUBLIC_API_BASE_URL: process.env.NEXT_PUBLIC_API_BASE_URL,
        },
        

        【讨论】:

        • 对我不起作用
        • 在本地开发环境中工作,但不能通过 kubernetes
        猜你喜欢
        • 2020-03-23
        • 1970-01-01
        • 2020-03-30
        • 2022-12-05
        • 2021-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-15
        相关资源
        最近更新 更多