I have built hundreds of side projects over the years and finding a place to manage and deploy them all has always been tricky. From the early days of a GoDaddy hosting package with random PHP files in folders, through having a persistentDigitalOceandroplet running, and event running a bare minimumKubernetescluster onGoogle Kubernetes Engine (GKE)– I’ve never been satisfied with the outcome.
I have a few requirements when it comes to down deploying random side projects:
- Fully-managed – I don’t want to have to worry about servers anymore – it’s (after all – and I want serverless all the things
- Cheap – These projects aren’t making me money so need to keep costs down
- Language agnostic – One day I maybe playing with something in Node, then next Python, the next Go.
- Scalable – in the unlikely something does takeoff, I don’t want to have to worry about it falling over
Thankfully, I’ve found a solution that I am happy with –Google Cloud Run.
Google is terrible at marketing…
Cloud Run is a fully managed compute platform that automatically scales your stateless containers. Cloud Run is serverless: it abstracts away all infrastructure management, so you can focus on what matters most — building great applications.
What is means is you can give it a docker container (technically any OCI compatible container) and it will deploy, run and scale it.
*******************
If we evaluate this by my requirements:
********
**************** (CloudSQL) or object storage (eg************************** Cloud Storage- then you are good to go. Do consider if any services you depend on can handle the traffic should this scenario occur though. (****************************************************Simple Node.js Example
Enough chat, let’s write some code.
If we take the most basic example of a Node.js Express app serving some JSON – this could be an API server for your statically deployed React frontend example.
(******************************************
The Application
You have your usual Node application code – something like:
(**************************************
************************** (‘express’) **********************************************) (********************************** const app=express(
const port=(process) **********************************************env.PORT||(************************************************** app .get
( '/'
,(req,res)=>(******************************** ({ res .json
(
{
message : 'Hello World' (********************************************** (********************************************** (********************************************** (********************************************** app .listen
( (port) ,((
)=>console.log(********************** () (********************************************** Example app listening on port (********************************************** ($ {) ********************************************* (port) **********************************************} (************************************************ (**********************************************! ****************************************** (************************************************))********************************************** (************************************************ ************************************************************************ (****************************************************************************************************************** (********************************************** (********************************************** (********************************************** (******************************************** (********************************************** (********************************************** (**********************************************This is the bare-minimum to run an HTTP server in Node - in this case when you hit the root path, it returns a JSON with a “Hello World” message. The only 'special' bit in this is line 3 where we grab the port number we tell express to listen to from the environment variable if it exists - this will be provided by the Cloud Run service at execution time.
Next we need aDockerfile to create our docker image from:
**************************************** (FROM) *********************************************** (node) **********************************************: ******************************************** 12 WORKDIR / usr / src / app COPY package * .json ./ RUN npm install COPY . . CMD
********************************** (************************************************ (********************************************** (********************************************** (********************************************** (************************************************ (********************************************** (************************************************ (************************************************ (********************************************** (************************************************ (********************************************** (************************************************
This is a barebonesDockerfile which uses the (node:) ************************************************************************************************************************************ base image, copies of our
****************** package.jsonfile in, installs our dependencies and then will run ourserver .jsfile upon running the container.
With that set now it is time to build & deploy.
Building & Pushing our Image
Google Cloud Runrequires our images to be in the Google Container Registryof our project for easiest access. As such, you will need to have this enabled on your Google Cloud Project - you can find out how to do this here. You will also need the (gcloud
) CLIinstalled on your machine and logged into your account - then rungcloud auth configure-docker (to setup) gcloudto work with docker.
Now to build, tag and push our image to the repository. Your container tag will need to be in the following format:
gcr.io/(***/[app-name]: latest
Where[gcp-project] is your Google Cloud Project name eg (my-project) and[app-name]is the name of your container egcloud-run-demo
You then build:
docker build -t gcr.io/[gcp-project] / [app-name]: latest.
and then push:
docker push gcr.io/(***/ [app-name]: latest
If everything worked without errors, you can now move onto deploying via Cloud Run.
You can do this via thegcloud CLI
gcloud beta run ...
commands or my preferred way, the Google Cloud Console.
Start by going to the Cloud Run section of your Google Cloud Console:
(********************************************************** (************************************************************ (************************************************************
Next press theCreate Service button at the top:
(********************************************************** (************************************************************ (************************************************************** (********************************
Here you need to select the container image that you just pushed - pressing theSelectlink in the box will open the picker which will show all the images in your Google Container Registry instance:
(********************************************************** (************************************************************ (************************************************************** (********************************
Once your image is selected a few other options to populate:
- Deployment Platform - for this example we want a fully managed offering so select (Cloud Run) ******************************* and your desired region. Go for the region closest to where your users will be.
- Service Name - Give your service a name so you can look it up later
-
- Authentication - Decide if you want your service to be authentication via Cloud IAM or not. For all my projects, I want people to access them so checkAllow Unauthenticated Invocations
-
There are some more advanced options to set things like custom environment variables, scaling limits and memory caps, but the default is fine for most thing.
HitCreate and your service will be deployed. If you get any errors at this point it usually means your application isn't listening on the (PORTenvironment variable. Double check this by running the container image locally and passing in the variable.
Behind the scenes
Cloud Run
is deploying your image and will given you an HTTP endpoint listed in the top of the page:
(********************************************************** (************************************************************ (**************************************************************** (************************************
All the
Cloud Run
URLs end in******************** (run.app) . Hitting this endpoint in your browser should return you the response from your server running in the container.
Your app is now fully deployed in a managed service. You can start throwing as much traffic at is as you wish, all without worrying about infrastructure, scaling, or maintenance and all for a very very small cost. The dream!
There are a number of advanced areas of Cloud Run which I make use of which maybe topics for future posts:
- Continuous Deployment from
- Cloud Build
-
-
- ************************************ Domain Mappingfor using my own domain names
- Connecting toCloudSQLfor database storage
- Authentication using Cloud IAM
(******************************************************************** (******************************
- Conclusion
Hopefully you've got a better idea of what
Cloud Runis, why it is so powerful and how it can help you with deploying all sorts of crazy side-projects for very little money and hassle.
Hit me much on Twitter @ alexolivierif you have any questions or want to talk more.
(****************************************************************************** (Read More) ***************************************************************************
PORT||(************************************************** app .( '/'get,(req,res)
{=>(******************************** ({ res .(jsonmessage : 'Hello World' (********************************************** (********************************************** (********************************************** (********************************************** app .listen( (port) ,(()
=>console.
log
(********************** () (********************************************** Example app listening on port (********************************************** ($ {) ********************************************* (port) **********************************************} (************************************************ (**********************************************! ****************************************** (************************************************))********************************************** (************************************************ ************************************************************************ (****************************************************************************************************************** (********************************************** (********************************************** (********************************************** (******************************************** (********************************************** (********************************************** (**********************************************This is the bare-minimum to run an HTTP server in Node - in this case when you hit the root path, it returns a JSON with a “Hello World” message. The only 'special' bit in this is line 3 where we grab the port number we tell express to listen to from the environment variable if it exists - this will be provided by the Cloud Run service at execution time.
Next we need aDockerfile to create our docker image from:
**************************************** (FROM) *********************************************** (node) **********************************************: ******************************************** 12 WORKDIR / usr / src / app COPY package * .json ./ RUN npm install COPY . . CMD********************************** (************************************************ (********************************************** (********************************************** (********************************************** (************************************************ (********************************************** (************************************************ (************************************************ (********************************************** (************************************************ (********************************************** (************************************************ This is a barebones
Dockerfile which uses the (node:) ************************************************************************************************************************************ base image, copies of our
****************** package.jsonfile in, installs our dependencies and then will run ourserver .jsfile upon running the container. With that set now it is time to build & deploy.
Building & Pushing our Image
Google Cloud Runrequires our images to be in the Google Container Registryof our project for easiest access. As such, you will need to have this enabled on your Google Cloud Project - you can find out how to do this here. You will also need the (gcloud
) CLIinstalled on your machine and logged into your account - then run gcloud auth configure-docker (to setup) gcloudto work with docker.
Now to build, tag and push our image to the repository. Your container tag will need to be in the following format:
gcr.io/(***/[app-name]: latest
Where[gcp-project] is your Google Cloud Project name eg (my-project) and[app-name]is the name of your container egcloud-run-demo
You then build:
docker build -t gcr.io/[gcp-project] / [app-name]: latest.
and then push:
docker push gcr.io/(***/ [app-name]: latest
If everything worked without errors, you can now move onto deploying via Cloud Run.
You can do this via the
gcloud CLI
gcloud beta run ...
commands or my preferred way, the Google Cloud Console.
Start by going to the Cloud Run section of your Google Cloud Console:
(********************************************************** (************************************************************ (************************************************************
Next press the
Create Service button at the top:
(********************************************************** (************************************************************ (************************************************************** (********************************Here you need to select the container image that you just pushed - pressing the
Selectlink in the box will open the picker which will show all the images in your Google Container Registry instance:
(********************************************************** (************************************************************ (************************************************************** (********************************Once your image is selected a few other options to populate:
- Deployment Platform - for this example we want a fully managed offering so select (Cloud Run) ******************************* and your desired region. Go for the region closest to where your users will be.
- Service Name - Give your service a name so you can look it up later
- Authentication - Decide if you want your service to be authentication via Cloud IAM or not. For all my projects, I want people to access them so checkAllow Unauthenticated Invocations
There are some more advanced options to set things like custom environment variables, scaling limits and memory caps, but the default is fine for most thing.
HitCreate and your service will be deployed. If you get any errors at this point it usually means your application isn't listening on the (PORTenvironment variable. Double check this by running the container image locally and passing in the variable.
Behind the scenes
Cloud Run
is deploying your image and will given you an HTTP endpoint listed in the top of the page:(********************************************************** (************************************************************ (**************************************************************** (************************************All the
Cloud Run
URLs end in******************** (run.app) . Hitting this endpoint in your browser should return you the response from your server running in the container.Your app is now fully deployed in a managed service. You can start throwing as much traffic at is as you wish, all without worrying about infrastructure, scaling, or maintenance and all for a very very small cost. The dream!
There are a number of advanced areas of Cloud Run which I make use of which maybe topics for future posts:
- Continuous Deployment from
- Cloud Build
- ************************************ Domain Mappingfor using my own domain names
- Connecting toCloudSQLfor database storage
- Authentication using Cloud IAM
(******************************************************************** (******************************
- Conclusion
Hopefully you've got a better idea of what
Cloud Runis, why it is so powerful and how it can help you with deploying all sorts of crazy side-projects for very little money and hassle.
Hit me much on Twitter @ alexolivierif you have any questions or want to talk more.
(****************************************************************************** (Read More) ***************************************************************************
GIPHY App Key not set. Please check settings