Jas*_*ane 6 environment-variables docker kubernetes next.js
这个问题之前已经被问过,在过去的两天里我尝试了很多例子来尝试和配置,但没有成功,所以我发布了我的环境以寻求帮助。
问题
Nextjs 使用 Terraform 部署到 kubernetes 后环境变量全部未定义
预期结果
staging: NEXT_PUBLIC_APIROOT=https://apis-staging.mywebsite.com
production: NEXT_PUBLIC_APIROOT=https://apis.mywebsite.com
Run Code Online (Sandbox Code Playgroud)
秘密存储在 github actions 中。我有一个 terraform 设置,可将我的应用程序部署到我的暂存和生产 klusters,下面是一个片段:
env:
ENV: staging
PROJECT_ID: ${{ secrets.GKE_PROJECT_STAG }}
GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS_STAG }}
GKE_SA_KEY: ${{ secrets.GKE_SA_KEY_STAG }}
NEXT_PUBLIC_APIROOT: ${{ secrets.NEXT_PUBLIC_APIROOT_STAGING }}
Run Code Online (Sandbox Code Playgroud)
我还有一个额外的步骤来手动创建 .env 文件
- name: env-file
run: |
touch .env.local
echo NEXT_PUBLIC_APIROOT: ${{ secrets.NEXT_PUBLIC_APIROOT_STAGING }} >> .env.local
Run Code Online (Sandbox Code Playgroud)
Dockerfile
FROM node:16-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json .npmrc ./
RUN npm ci
FROM node:16-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:16-alpine AS runner
WORKDIR /app
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# You only need to copy next.config.js if you are NOT using the default configuration
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
Run Code Online (Sandbox Code Playgroud)
next.config.js
module.exports = withBundleAnalyzer({
publicRuntimeConfig: {
NEXT_PUBLIC_APIROOT: process.env.NEXT_PUBLIC_APIROOT,
},
output: 'standalone',
webpack: (config, { dev, isServer }) => {
if (dev && isServer) {
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
config.plugins.push(
new ForkTsCheckerWebpackPlugin({
eslint: {
files: './src/**/*.{ts,tsx,js,jsx}',
},
})
)
}
return config
},
})
Run Code Online (Sandbox Code Playgroud)
有人对这个问题有经验吗?
首先我想说我绝不是 NextJS 的专家。因此,我尝试在以下假设下解决您的问题:
next.config.js机制自动加载环境变量.env.localus-central1-c:)我的第一步是创建一个具有单个 API 端点的虚拟 NextJS 应用程序,该应用程序仅打印我在将工作负载部署到 Kubernetes 时尝试设置的环境变量之一。当谈到 Dockerfile 时,我使用了与您提供的完全相同的图像。请在下面找到我的虚拟应用程序中的相关文件:
页面/api/test.js
export default function handler(req, res) {
res.status(200).json(process.env.NEXT_PUBLIC_APIROOT)
}
Run Code Online (Sandbox Code Playgroud)
next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: true,
});
module.exports = withBundleAnalyzer({
publicRuntimeConfig: {
NEXT_PUBLIC_APIROOT: process.env.NEXT_PUBLIC_APIROOT,
},
output: 'standalone'
})
Run Code Online (Sandbox Code Playgroud)
Dockerfile
FROM node:16-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM node:16-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:16-alpine AS runner
WORKDIR /app
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# You only need to copy next.config.js if you are NOT using the default configuration
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["npm", "start"]
Run Code Online (Sandbox Code Playgroud)
我在 Dockerfile 中做了一个更改,即更新 CMD 条目,以便应用程序通过命令启动npm start。
根据官方文档,NextJS 将尝试在应用程序根文件夹中查找.env.local并将这些环境变量加载到process.env.
因此,我使用 Kubernetes 资源创建了一个 YAML 文件,该文件将用于创建部署设置。
nextjs-app-setup.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nextjs-app-config
data:
.env.local: |-
NEXT_PUBLIC_APIROOT=hello_i_am_an_env_variable
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nextjs-app
labels:
app: nextjs-app
spec:
replicas: 1
selector:
matchLabels:
app: nextjs-app
template:
metadata:
labels:
app: nextjs-app
spec:
containers:
- name: nextjs-app
image: public.ecr.aws/u4x8r8g3/nextjs-app:latest
ports:
- containerPort: 3000
volumeMounts:
- name: nextjs-app-config
mountPath: "/app/.env.local"
subPath: ".env.local"
readOnly: true
volumes:
- name: nextjs-app-config
configMap:
name: nextjs-app-config
---
apiVersion: v1
kind: Service
metadata:
name: nextjs-service
spec:
selector:
app: nextjs-app
ports:
- protocol: TCP
port: 3000
targetPort: 3000
Run Code Online (Sandbox Code Playgroud)
上述配置中发生了多种情况:
.env.local将保存所有环境变量并将作为文件安装在应用程序 pod 中volumes和volumeMounts块。在这里,我正在挂载路径.env.local上定义的 ConfigMap 中的条目/app/.env.local通过 kubectl 连接到 GKE 集群后,我通过kubectl apply -f nextjs-app-setup.yaml.
为了从本地工作站连接到该服务,我执行了kubectl port-forward service/nextjs-service 3000:3000. 然后我在浏览器中导航localhost:3000/api/test并可以看到我在 ConfigMap 中设置为输出的值。
免责声明:我知道您的设置可能涉及一些额外的组件,特别是在 CI/CD 和基础设施即代码方面,但我在这里的回答至少应该为您提供一种访问容器化 NextJS 工作负载中的环境变量的方法。如果您仍然获得undefined值,我的假设是,它很可能与您在 CI/CD 管道中配置它们的方式有关,但这将是一个与 NextJS 或 Kubernetes 无关的不同问题。
| 归档时间: |
|
| 查看次数: |
1622 次 |
| 最近记录: |