English 中文(简体)
Frontend Cannot Access Cloud Run ENV Variables in Production
原标题:

I am using docker to build an image via Google Cloud Build > Google Cloud Registry. Then I have Pub/Sub triggers setup to populate Cloud Run instances with new Docker images on a successful build.

However my frontend code is unable to access the Cloud Run ENV variables I manually set in the dashboard (they return undefined). I need to be able to build images without the ENVs already defined since I wish to have many Cloud Run instances based on the same image and inject ENVs later on.

I am using NEXT.js.

This is my 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:  / ,
      },
    ];
  },
});

And my frontend

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,
      }
  }
}

In Cloud Run logs, the variable will log accurately on the server side via the next.config.js file but all of the client side variables return undefined in the browser.

Locally testing, I can retrieve client side variables just fine.

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
问题回答

Figured it out!

Gyum Fox had the original solution that worked for me.

I ended up using @beam-australia/react-env to fetch my ENV from the client side. Once I followed the NEXT.js example in the repo, my client was able to read ENV variables set in Google Cloud Run

Here s an example:

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>
    </>
  );
}

My package.json looked like this:

{
  "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",
  },
}

Then I needed to change my docker user to root in my Dockerfile for Google Cloud Build to allow my to write to the ENV file:

USER root

Once I submitted another build, my Cloud Run instance client accessed the ENV like a charm!





相关问题
How to use one react app into another react app?

I have two react apps, parent app and child app. and child app have an hash router. I have build the child app using npm run build, It creates build folder. That build folder moved into inside the ...

how to get selected value in Ant Design

I want to print the selected value, and below is my option list: const vesselName = [ { value: 0 , label: ALBIDDA , }, { value: 1 , label: ALRUMEILA , }, { value: 2 ,...

How to add a <br> tag in reactjs between two strings?

I am using react. I want to add a line break <br> between strings No results and Please try another search term. . I have tried No results.<br>Please try another search term. but ...

热门标签