Deploy React and Nginx to Google Cloud Run
I was very excited to know that now we can deploy containerized apps to Google Cloud platform and have most of the benefits of serverless services. Meaning that we only have to pay for the resources we use while being able to greatly modify the underlying OS and runtime.
That service is Google Cloud run.

What is serverless?
A serverless service is that in which you don’t have to babysit the underlying server your app is running on. Google does most of that job (updates, maintenance). There’s usually one more benefit, you pay only for the resources you use, but there’s a tradeoff, you have limitations when it comes to being able to modify the runtime.
What’s new about cloud run
In Cloud run you can modify the runtime of your application by tweaking a dockerfile and sending it along with your source code to Google Cloud platform.
In this tutorial, we are going to put a Create React App (CRA) application online, served with an Nginx server, this server is going to be waiting for the environment variable PORT that contains the port the app is going to listen on. By doing that we meet one of the requirements of Google Cloud run, the second one is serving a stateless application. Since this web app never writes to permanent storage we automatically comply with that second requirement.
I’m going to assume you already have a Google account and a project in Google Cloud platform if that’s not the case have a look at this article.
You’ll also need the Google Cloud SDK installed and configured with your GCP project, learn how to set that up here.
Let’s get started
In the google cloud console, Select the project that you’re going to be working with and over to the navigation menu located in the top left part of the screen. Select APIs & services > Library

Using the search bar find the following APIs enable them.
- Cloud Run API
- Container Registry API
- Cloud build API
Now lets get the CRA code
The Repo
This repository contains the code with the CRA, the Nginx config file and the dockerfile that puts it all together.
If you npm install and npm run the create-react-app you should see something like this. Just a home page and 3 routes.

Nginx config
If you open nginx.conf that is located in the root of the project you’ll see the following config.
server {
listen $PORT;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /error.html {
root /usr/share/nginx/html;
}
}
Line 2 specifies the port where the server is going to be listening.
But wait, there’s an environmental variable ($PORT)where the port number was supposed to be! — And nginx files don’t support env variables! Right!?
That’s totally right. But something is going on in the dockerfile that’s going to take care of that.
Parenthesis, an ephemeral container where the react app is going to be built.
FROM node:8-alpine as react-build
WORKDIR /app
COPY . ./
RUN yarn
RUN yarn build
Back to the Nginx stuff
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/configfile.template
ENV PORT 8080
ENV HOST 0.0.0.0
To Nginx alpine, the file nginx.conf is being copied as configfile.template and the PORT and HOST environment variables are being declared.
RUN sh -c "envsubst '\$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf"
COPY --from=react-build /app/build /usr/share/nginx/html
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
Then, the envsubst command is being applied over configfile.template in order to substitute the environment variables present in the file with their respective values, the result is being saved as default.conf.
This will result in line 2 from Nginx.conf going from “listen $PORT” to “listen 8080” (or whatever you the PORT variable to be).
Finally, we are copying the built CRA and starting up the Nginx server. This will leave behind the source code and dependencies, significantly reducing the size of the final bundle and eliminating potential vulnerabilities included in that code.
Go ahead and run the following command to see the containerized react app running on your local machine.
docker build -t test . && docker run -p 4444:8080 test
The production build of React should now be running on localhost:4444, more importantly, running off a docker container.
Deploying to Cloud Run
In the Google Cloud SDK command line type
gcloud builds submit — — tag gcr.io/NAME-OF-YOUR-PROJECT/IMAGE_NAME
NAME_OF_YOUR_PROJECT being the name of your project in GCP

you are free to choose a value for IMAGE_NAME
This will send to dockerfile and source code to Google cloud builds to follow the steps in the dockerfile and ultimately build the Nginx container.
When the process finishes and the image is fully created. Head over to the google cloud console, on the navigation menu, scroll down and select Container registry.

There you should be able to see the newly added image, click on its image name.
For the image with the “latest” tag (usually the first row) click on the 3 vertical dots and select Deploy to Cloud Run

The Deployment platform form will come up. Give a name to this deployment, select “allow unauthenticated invocations” and click Create.
Once the deployment finishes you’ll be able to see the deployment details usually found in serverless apps, but now, regarding your containerized react app.
Congratulations you’ve now deployed your first serverless container in Google Cloud Run