Setup react app build folder onto Google Kubernetes - reactjs

Currently, I have a repo that contains both a Node.js Express backend and React frontend. The repo's image is in Google Container Registry and is used on a Google Kubernetes cluster. There is an url provided by a load balancer, where it is the backend url that is serving the static build server. In the future, I want to separate the backend/frontend into two different repos (one for backend and one for frontend).
I believe making changes for the backend in the cluster won't be difficult, but I am having trouble figuring out how to add the React frontend to this since the build folder will be in a different repo than the backend. I read online that to serve a React app on GCP, you would upload the build folder onto a bucket and have that bucket served on App Engine, which will provide a url to access it on the web.
I'm wondering if this is how it would be done on a Kubernetes cluster or if there is a different approach since it is not using App Engine, rather Google Kubernetes.
I hope this makes sense (I am still fairly new to Google Cloud) and any feedback/tips will be appreciated!
Thanks!

There are different approaches to this.
Approach 1: Serve your frontend via Google Cloud Storage.
There is a guide in the GCP documentation: Hosting a static website to set this up. After the build copy all the files to the cloud storage and you are done.
Approach 2: Add your fronted to your backend while building the Docker image
Build your frontend and pack it into a Docker image with something like this:
FROM node AS build
WORKDIR /app
COPY . .
RUN npm ci && npm run build
FROM scratch
COPY --from=build /app/dist /app
Build your backend and copy the frontend:
FROM myapp/frontend as frontend
FROM node
// build backend
COPY --from=frontend /app /path/where/frontend/belongs
This decouples both builds but you will always have to deploy the backend for a frontend change.
Approach 3: Serve your frontend with nginx (or another web server)
FROM node AS build
WORKDIR /app
COPY . .
RUN npm ci && npm run build
FROM nginx
COPY --from=build /app/dist /usr/share/nginx/html
You might also adapt the nginx.conf to enable routing without hash paths. See this article by codecentric for more information on that.

Related

How to deploy app with Docker Compose + React + Django + Nginx?

I'm building an app using Docker Compose, React, Django and Nginx. After struggling for a few days I managed to set up a docker-compose file that successfully connected all these services, from collecting the React static files and having Nginx serve them, to having Nginx point to the Django static files instead of Django serving them, to adding other services like Celery to the Docker Compose config.
However, it seems like there's no easy place to publish + deploy this container (the Docker registry doesn't accept containers I think?). All I could find was Azure and AWS integrations, which are definitely a step up from the Heroku deployment I was doing before. My Heroku no longer works as it needs the React + Django to all be at the same depth level of folders, or it doesn't let me use the 'heroku/nodejs' buildpack. Is there a deployment option that lets me maintain the separate folder structure + ease of development of Docker Compose, without being as complex as Azure and AWS? Thanks in advance!
You can upload your container to heroku container registry
https://devcenter.heroku.com/categories/deploying-with-docker
add a heroku.yml file
build:
docker:
web: Dockerfile
run:
web: bundle exec puma -C config/puma.rb
then with the heroku-cli
heroku create
heroku container:push web

How to use Google Cloud Secrets in Cloud Run using react?

I'm developing a react website that uses some sensitive API keys.
I'm hosting the application on Google Cloud Run, via a container.
I would like to access API keys through Google Cloud Secret Manager, but I am not able to. When I try to access them, the return is "undefined".
Here is my code snippet:
console.log(process.env.REACT_APP_API_KEY)
And the Dockerfile:
FROM node:14-alpine AS builder
WORKDIR /app
COPY package.json ./
COPY yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
RUN yarn build
FROM nginx:1.19-alpine AS server
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder ./app/build /usr/share/nginx/html
I'm deploying the application using the gcloud command:
gcloud run deploy test-gcr-react \
--image gcr.io/test-gcr-react-app/test-gcr-react \
--region=southamerica-east1 \
--set-secrets=REACT_APP_API_KEY=REACT_APP_API_KEY:latest \
--allow-unauthenticated
PS: I have already given the proper access permissions to the service account "Default compute service account" to be a "Secret Manager Secret Acessor" of the secret REACT_APP_API_KEY.
It's a common issue. Think about the role and the behavior of each layer:
NGINX serve directly the react JS
The react JS is ran directly on the user browser.
therefore, NEVER, the env var (your secret) is read. NGINX doesn't care of it, the user browser can't access Cloud Run env var.
The trick here is to set the API KEY in a conf file of your react APP at build time (in your dockerfile). The secret must be in the JS before the runtime. NGINX only serve JS, not update/change it
I guess you mean Secret Manager Secret Accessor role.
In order to do so you can do this:
gcloud secrets add-iam-policy-binding secret-id \
--member="serviceAccount:<project-number>-compute#developer.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
But, make sure your cloud run is really using that service account, if not change the member field in the command up above to correct it to the appropriate service account instead.

GIT CD "Laravel + React" application

I have an application that uses Laravel as backend and React as frontend
The two applications are stored in separate repositories.
In the local environment, I serve the Laravel application with "php artisan:serve" and the React application with "npm run start".
The two applications communicate with each other through POST/GET APIs.
Now I want to create a "deploy" repository.
The deploy repository should have two folders:
backend (containing Laravel application)
frontend (containing React application)
I want that every time a merge is made on the main branch of one of the two repos (backend or frontend) the changes are pushed to the deploy repository too.
The deploy repo will take care of building the app and eventually build a docker image.
Is this possible?
There are better ways/patterns to achieve what I want?

Is is possible to deploy different monorepos packages to different domains

I'm trying to deploy a monorepo of 2 react packages (repos) where each package is deployed to different aws s3 bucket , is it possible ?
package A to be deployed to api.mywebsite.com
package B to be deployed to www.mywebsite.com
Welcome to Stackoverflow!
I suggest you do the following
In your build step create two artifacts (e.g. api, web). For example, if your npm build creates a ./build directory, do cp -r build api for the api project and similar for the web project
In your deployment step do something like aws s3 cp api s3://api.mywebsite.com --recursive or aws s3 sync api s3://api.mywebsite.com and same for the web artifact

How to push existing docker image to google app-engine

I am currently using the app engine maven plugin, which seems to trigger a Google cloud build to build a docker image and then push to app engine.
Is it possible for me to just push an exiting docker image from docker hub or google container registry?
You can deploy to App Engine using a specific Docker image hosted on Google Container Registry by using the --image-url flag like this:
gcloud app deploy --image-url=[HOSTNAME]/[PROJECT-ID]/[IMAGE]
See doc here for more info on the hostname options.
It is also possible to do this through the Dockerfile in your app directory.
I noticed this while searching for ways to customize Google's own NGINX container in the App Engine instance (this is what is used to serve your app).
The first line of the Nginx Dockerfile is FROM nginx. This is referencing the 'nginx' image in the default image repository. As such this could be any image in the default registry as referenced by name. The default registry seems to be the Docker-hub registry (did not investigate if Google is mirroring or similar).
In this way, your app directory only need contain 2 files: app.yaml and Dockerfile.

Resources