【问题标题】:Frontend Cannot Access Cloud Run ENV Variables in Production前端无法访问生产环境中的 Cloud Run ENV 变量
【发布时间】:2021-10-11 06:12:22
【问题描述】:

我正在使用 docker 通过 Google Cloud Build > Google Cloud Registry 构建映像。然后我设置了 Pub/Sub 触发器,以便在成功构建时使用新的 Docker 映像填充 Cloud Run 实例。

但是,我的前端代码无法访问我在仪表板中手动设置的 Cloud Run ENV 变量(它们返回 undefined)。我需要能够在没有定义 ENV 的情况下构建图像,因为我希望有许多基于同一图像的 Cloud Run 实例并稍后注入 ENV。

我正在使用 NEXT.js。

这是我的 next.config.js

module.exports = withPlugins(plugins, {
  assetPrefix,
  reactStrictMode: true,
  eslint: {
    ignoreDuringBuilds: true,
  },
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    config.plugins.push(new Dotenv({
      path: '../../../.env', 
    }))
    return config
  },
  serverRuntimeConfig: {
    NEXT_PUBLIC_FIREBASE_USER_ID: process.env.NEXT_PUBLIC_FIREBASE_USER_ID,
  },
  publicRuntimeConfig: {
    NEXT_PUBLIC_FIREBASE_USER_ID: process.env.NEXT_PUBLIC_FIREBASE_USER_ID,
  },
  env: {
    NEXT_PUBLIC_FIREBASE_USER_ID: process.env.NEXT_PUBLIC_FIREBASE_USER_ID,
  },
  async rewrites() {
    return [
      {
        source: '/:any*',
        destination: '/',
      },
    ];
  },
});

还有我的前端

const { serverRuntimeConfig, publicRuntimeConfig } = getConfig()
const { NEXT_PUBLIC_FIREBASE_USER_ID } = serverRuntimeConfig
const { NEXT_PUBLIC_FIREBASE_STORE_ID } = publicRuntimeConfig

function App(props) {
  useEffect(() => {
    console.log("NEXT_PUBLIC_FIREBASE_USER_ID: ", NEXT_PUBLIC_FIREBASE_USER_ID)
    console.log("NEXT_PUBLIC_FIREBASE_USER_ID: ", NEXT_PUBLIC_FIREBASE_USER_ID)
    console.log("NEXT_PUBLIC_FIREBASE_USER_ID: ", NEXT_PUBLIC_FIREBASE_USER_ID)
    console.log("uid: ", props.uid)
    console.log("process.env.NEXT_PUBLIC_FIREBASE_USER_ID: ", process.env.NEXT_PUBLIC_FIREBASE_USER_ID)
  }, [])
 
  return <Routes />;
}

export async function getServerSideProps() {
  return {
      props: {
        uid: process.env.NEXT_PUBLIC_FIREBASE_USER_ID,
      }
  }
}

在 Cloud Run 日志中,该变量将通过 next.config.js 文件准确记录在服务器端,但所有客户端变量在浏览器中返回 undefined

本地测试,我可以检索客户端变量就好了。

Dockerfile:

# Stage 1: Compile and Build the app

# Node veersion
FROM node:14.17.3-alpine as build

# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat git

# Set the working directory
WORKDIR /app

# Add the source code to app
COPY ./js /app

# Install all the dependencies
RUN yarn install
RUN yarn bootstrap

# Generate the build of the application
RUN yarn build

# Stage 2: Serve app with nginx server

# Production image, copy all the files and run next
FROM node:14.17.3-alpine AS runner
WORKDIR /app

ENV NODE_ENV production

RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

# Copy the build output to replace the default nginx contents.
COPY --from=build /app/packages/web/next.config.js ./
COPY --from=build /app/packages/web/public ./public
COPY --from=build --chown=nextjs:nodejs /app/packages/web/.next ./.next
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/packages/web/package.json ./package.json

USER nextjs

EXPOSE 3000

CMD ["yarn", "start:prod"]
enter code here

【问题讨论】:

  • 我建议您按照 Next.js (Environment Variables) 的建议设置环境变量。无需在next.config.js 中进行额外设置。
  • @juliomalves 我无法使用 NEXT_PUBLIC_ 因为我正在使用 dotenv 定义我的 .env 文件的自定义路径,并且 Next 在使用 dotenv 时禁用了他们的 ENV 功能我的项目是monorepo lerna 应用程序
  • @juliomalves 当我用dotenv-webpack 替换dotenv 时,客户端环境变量也可以在本地工作,但不能在云端运行:(
  • 你能分享你的 dockerfile 吗?
  • @guillaumeblaquiere 是的,将其添加到原始问题的底部

标签: reactjs typescript google-cloud-platform next.js google-cloud-run


【解决方案1】:

想通了!

Gyum Fox 拥有适合我的 original solution

我最终使用@beam-australia/react-env 从客户端获取我的 ENV。一旦我在 repo 中关注NEXT.js example,我的客户就能够读取在 Google Cloud Run 中设置的 ENV 变量

这是一个例子:

import React, { useEffect } from 'react';
import Head from 'next/head';
import env from "@beam-australia/react-env";

function App() {
 useEffect(() => {
   console.log("Firebase User: ",  env("FIREBASE_USER_ID"))
  }, [])

  return (
    <>
      <Head>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>Ownchain</title>
        <script src="/__ENV.js" />
      </Head>
    </>
  );
}

我的 package.json 看起来像这样:

{
  "name": "web",
  "version": "0.1.0",
  "dependencies": {
    "@beam-australia/react-env": "^3.1.1",
    "next": "^11.0.1",
    "next-compose-plugins": "^2.2.1",
    "next-with-less": "^1.0.0",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-env": "^0.0.0",
    "react-router-dom": "^5.2.0",
  },
  "scripts": {
    "start": "react-env --path ../../../.env -- next dev",
    "build": "next build",
    "export": "next export",
    "start:prod": "react-env --path ../../../.env -- next start",
    "test": "jest",
  },
}

然后我需要在我的 Dockerfile 中将我的 docker 用户更改为 root 以允许我写入 ENV 文件:

USER root

一旦我提交了另一个构建,我的 Cloud Run 实例客户端就可以访问 ENV!

【讨论】:

    猜你喜欢
    • 2020-12-28
    • 1970-01-01
    • 2020-11-12
    • 2018-03-01
    • 2019-12-30
    • 1970-01-01
    • 2019-05-13
    • 2019-04-14
    • 1970-01-01
    相关资源
    最近更新 更多