DEV Community

Cover image for How to Access ENV Variables in Google Cloud Run using Next.js
Cormac
Cormac

Posted on

How to Access ENV Variables in Google Cloud Run using Next.js

If you’re building a web application, Google Cloud Run is a great option for you to deploy microservices to the cloud. It’s built on top of Kubernetes and allows you to scale backend and monorepos with ease.

However, when our team at Ownchain was working to deploy our users’ based on a Docker image sitting in Google Cloud Build and Container Registry, our client-side code was unable to access our environment variables set in Cloud Run–they were showing up as undefined.

Here’s how we were able to deploy our Next.js monorepo application to Google Cloud using Docker and dynamic ENV variables:

I’m assuming you have already setup lerna and can run you’re application locally.

Initial Setup

This is the key to exposing your ENV variables to the client once you deploy your application to Cloud Run.

We ended up using @beam-australia/react-env to fetch ENV variables from the server and expose them to the client.

You can follow the NEXT.js example in their repo, or they also have instructions if you used Create React App.
Here’s an example of how it works:

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

Using the react-env package we can set a custom path for our .env file within our monorepo application.

`// app.tsx
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 (
<>



Ownchain


</>
);
}`

By adding the script t our

component we can read in our ENV variables using env("FIREBASE_USER_ID") format.

Some Devops Stuff

Once that’s all setup, you should have your Dockerfile in the root directory ready to go. Our’s looked something like this:

`# Stage 1: Compile and Build the app

Node version

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 root
EXPOSE 3000
CMD ["yarn", "start:prod"]`

**Make sure to add your USER as root otherwise @beam-australia/react-env won’t have enough access to your environment variables.

Sync Github with CloudBuild and set Cloud Run Automated Deployments

This is pretty easy to setup, Google has some great documentation for this: https://cloud.google.com/build/docs/automating-builds/build-repos-from-github

In addition, we can also utilize Cloud Functions to setup continuous delivery to Cloud Run with each new Cloud Build using Pub/Sub. Follow this article for specific instructions: https://medium.com/google-cloud/continuous-deployment-to-cloud-run-services-based-on-a-new-container-image-bccd776b7357

Showing it off

Now we can add ENV variables directly to Cloud Run:

Or you can add them as tags with API or CLI requests like so (see bottom):

"run",
"deploy",
${serviceName},
"--image",
"gcr.io/GOOGLE_CLOUD_PROJECT/store",
"--region",
"us-west2",
"--allow-unauthenticated",
"--platform",
"managed",
"--update-env-vars",
REACT_APP_FIREBASE_USER_ID=${userId},REACT_APP_STORE_LOGO=${logoUrl}``

Now when you visit your Cloud Run url your client will be able to access your env variables. 🥳

Discussion (0)