I am trying to deploy my MERN project using GCP. I want to use values in the backend of my project that are stored in google secret manager. I have a yaml file and separate dockerfiles for frontend (doctorside) and backend. After deployment, when I console log process.env.REACT_APP_MONGO_PROD_CLUSTER_PASS in my frontend I can see the value in browser console, but when I try it in my server.js nodejs file, I see this in logs: MONGO_PROD_PASS_CLUSTER_PASS: '$MONGO_PROD_PASS_CLUSTER_PASS', etc.
cloudbuild.yaml:
steps:
# Build the backend
# Build the backend
- name: 'gcr.io/cloud-builders/docker'
entrypoint: 'bash'
args: [
'-c',
'docker build -t gcr.io/$PROJECT_ID/backend -f Dockerfile --build-arg MONGO_PROD_PASS_CLUSTER_PASS=$$MONGO_PROD_PASS_CLUSTER_PASS --build-arg MONGO_PROD_CLUSTER_PASS=$$MONGO_PROD_CLUSTER_PASS --build-arg MONGO_PROD_DETAILS=$$MONGO_PROD_DETAILS --build-arg MONGO_PROD_PASS_DETAILS=$$MONGO_PROD_PASS_DETAILS --build-arg MONGO_PROD_PASS_USR=$$MONGO_PROD_PASS_USR --build-arg MONGO_PROD_USR=$$MONGO_PROD_USR .'
]
dir: 'backend'
secretEnv: ['MONGO_PROD_PASS_CLUSTER_PASS', 'MONGO_PROD_CLUSTER_PASS', 'MONGO_PROD_DETAILS', 'MONGO_PROD_PASS_DETAILS', 'MONGO_PROD_PASS_USR', 'MONGO_PROD_USR']
# Build the DoctorSide
- name: 'gcr.io/cloud-builders/docker'
entrypoint: 'bash'
args: [
'-c',
'docker build -t gcr.io/$PROJECT_ID/doctorside -f Dockerfile --build-arg REACT_APP_MONGO_PROD_CLUSTER_PASS=$$MONGO_PROD_CLUSTER_PASS --build-arg REACT_APP_MONGO_PROD_USR=$$MONGO_PROD_USR .'
]
dir: 'doctorside'
secretEnv: ['MONGO_PROD_CLUSTER_PASS', 'MONGO_PROD_USR']
# Push images to GCR
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/backend']
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/doctorside']
# Deploy the backend
- name: 'gcr.io/cloud-builders/gcloud'
args: [
'run', 'deploy', 'backend-service',
'--image', 'gcr.io/$PROJECT_ID/backend',
'--platform', 'managed',
'--region', 'asia-south1',
'--allow-unauthenticated',
'--set-env-vars',
'MONGO_PROD_CLUSTER_PASS=$$MONGO_PROD_CLUSTER_PASS,MONGO_PROD_PASS_CLUSTER_PASS=$$MONGO_PROD_PASS_CLUSTER_PASS,MONGO_PROD_DETAILS=$$MONGO_PROD_DETAILS,MONGO_PROD_PASS_DETAILS=$$MONGO_PROD_PASS_DETAILS,MONGO_PROD_PASS_USR=$$MONGO_PROD_PASS_USR,MONGO_PROD_USR=$$MONGO_PROD_USR',
'--timeout', '600s'
]
secretEnv: ['MONGO_PROD_PASS_CLUSTER_PASS', 'MONGO_PROD_CLUSTER_PASS', 'MONGO_PROD_DETAILS', 'MONGO_PROD_PASS_DETAILS', 'MONGO_PROD_PASS_USR', 'MONGO_PROD_USR']
# Deploy the DoctorSide
- name: 'gcr.io/cloud-builders/gcloud'
args: [
'run', 'deploy', 'doctorside-service',
'--image', 'gcr.io/$PROJECT_ID/doctorside',
'--platform', 'managed',
'--region', 'asia-south1',
'--allow-unauthenticated',
'--set-env-vars', 'REACT_APP_MONGO_PROD_CLUSTER_PASS=$$MONGO_PROD_CLUSTER_PASS,REACT_APP_MONGO_PROD_USR=$$MONGO_PROD_USR',
'--timeout', '600s'
]
availableSecrets:
secretManager:
- versionName: projects/$PROJECT_ID/secrets/MONGO_PROD_PASS_CLUSTER_PASS/versions/latest
env: 'MONGO_PROD_PASS_CLUSTER_PASS'
- versionName: projects/$PROJECT_ID/secrets/MONGO_PROD_CLUSTER_PASS/versions/latest
env: 'MONGO_PROD_CLUSTER_PASS'
- versionName: projects/$PROJECT_ID/secrets/MONGO_PROD_DETAILS/versions/latest
env: 'MONGO_PROD_DETAILS'
- versionName: projects/$PROJECT_ID/secrets/MONGO_PROD_PASS_DETAILS/versions/latest
env: 'MONGO_PROD_PASS_DETAILS'
- versionName: projects/$PROJECT_ID/secrets/MONGO_PROD_PASS_USR/versions/latest
env: 'MONGO_PROD_PASS_USR'
- versionName: projects/$PROJECT_ID/secrets/MONGO_PROD_USR/versions/latest
env: 'MONGO_PROD_USR'
options:
logging: CLOUD_LOGGING_ONLY
backend dockerfile:
FROM node:16
# Create app directory
WORKDIR /app
# Declare build-time arguments (available only during build)
ARG MONGO_PROD_PASS_CLUSTER_PASS
ARG MONGO_PROD_CLUSTER_PASS
ARG MONGO_PROD_DETAILS
ARG MONGO_PROD_PASS_DETAILS
ARG MONGO_PROD_PASS_USR
ARG MONGO_PROD_USR
# Export arguments as runtime environment variables
ENV MONGO_PROD_PASS_CLUSTER_PASS=$MONGO_PROD_PASS_CLUSTER_PASS
ENV MONGO_PROD_CLUSTER_PASS=$MONGO_PROD_CLUSTER_PASS
ENV MONGO_PROD_DETAILS=$MONGO_PROD_DETAILS
ENV MONGO_PROD_PASS_DETAILS=$MONGO_PROD_PASS_DETAILS
ENV MONGO_PROD_PASS_USR=$MONGO_PROD_PASS_USR
ENV MONGO_PROD_USR=$MONGO_PROD_USR
# Copy only package files for better caching
COPY package*.json yarn.lock ./
# Install dependencies
RUN yarn install
# Copy the rest of your application code
COPY . .
# Expose the application port
EXPOSE 8080
# Start the application
CMD ["node", "server.js"]
frontend dockerfile:
FROM node:18-alpine AS build
WORKDIR /app
# Add build arguments for environment variables
ARG REACT_APP_MONGO_PROD_CLUSTER_PASS
ARG REACT_APP_MONGO_PROD_USR
# Set environment variables
ENV REACT_APP_MONGO_PROD_CLUSTER_PASS=$REACT_APP_MONGO_PROD_CLUSTER_PASS
ENV REACT_APP_MONGO_PROD_USR=$REACT_APP_MONGO_PROD_USR
COPY package.json yarn.lock ./
RUN yarn install
COPY . ./
RUN yarn build
# Production stage
FROM node:18-alpine
RUN yarn global add serve
WORKDIR /app
COPY --from=build /app/build ./build
ENV PORT=8080
EXPOSE 8080
CMD ["serve", "-s", "build", "-l", "8080"]
As per this official GCP document on Configure secrets for services :
Any configuration change leads to the creation of a new revision. Subsequent revisions will also automatically get this configuration setting unless you make explicit updates to change it.
You can make a secret accessible to your service using the Google Cloud console
Verify the secret version you're trying to access exists:
gcloud secrets versions list --secret="my-secret
For accessing secrets in your code as environment variables, refer to the tutorial on end user authentication, particularly the section Handling sensitive configuration with Secret Manager.
Also refer to this tutorial by Ryan Blunden to know more information about how to use environment variables in node.js for app configurations and services.