Learn how to create, Dockerize, and deploy your containerized Angular application using Google Cloud Run.
TL;DR: working example Github repo.
Prerequisites:
- Node
- Angular CLI
- Docker
- Google Cloud SDK
- An activated Google Cloud Platform account
Skip step 1. if you already have a working Angular app.
1. Create an Angular App
To get started, use the Angular CLI to generate a new Angular app:
ng new
You will be prompted to name your app and add some configuration choices.
Once the CLI has generated all the necessary files for your Angular app, you can test it out by executing these two commands.
cd <app-name>
ng serve
In your favorite browser, navigate to http://localhost:4200. With Angular 9, you will get a similar welcome screen to the one below.
2. Create a Google Cloud Project
Login to your GCP account, then create a new project. You are not required to use an organization, as long as you have billing enabled on your account.
After you see the GCP welcome dashboard for your freshly created project, click on the hamburger menu, and navigate to Cloud Run. Proceed by clicking the “start using Cloud Run” button. You should now see your Cloud Run dashboard. Click on the create service button.
In service settings, enter a service name, and the container image URL should autofill. Select the region of your choice, then click create.
Your new service is now created, and ready to have an image pushed to it.
3. Dockerize, and Serve your Angular App Using ExpressJS
Cloud Run only works with containerized images. In order to containerize our Angular app, we use Docker. You can do so by creating a Dockerfile in your project directory with the config below.
FROM node:12-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install -g @angular/cli
RUN npm install
COPY . ./
RUN npm run build
EXPOSE 8080
CMD [ "node", "server.js" ]
This Dockerfile permits us to install the Angular CLI, along with all our project’s dependencies in a node-based docker container. It also builds and generates the necessary static files to serve our Angular app. Note that we expose port 8080, even though our Angular app’s default server port is 4200. Port 8080 is Google Cloud Run’s default port. This is a great transition to the last missing piece of the puzzle: Using ExpressJS.
In order to get our app on the web, we need to serve the static files contained in our dist folder using a service. ExpressJS is a NodeJS library that allows us to do so, in a few lines of code. Create a server.js file and copy the below snippet to it, replacing PROJECT-NAME with the name of your Angular app.
var express = require('express');
var app = express();
app.use(express.static('dist/PROJECT-NAME'));
app.get('/', function (req, res,next) {
res.redirect('/');
});
app.listen(8080)
After adding the two files, feel free to test your container by building an image and running it using the two commands below (replacing *app-tag *with the tag you wish to use).
docker build -t app-tag .
docker run -p 8080:8080 app-tag
Navigate to http://localhost:8080 to see your Angular app served via ExpressJS from inside your container (hence the “CMD [ “node”, “server.js” ]” at the bottom of your Dockerfile).
4. Deploy your Angular App (Source)
All that is left to do, is to use the Google Cloud SDK to build and deploy your containerized web app.
This is actually as simple as it sounds. Two commands, one to build, another to deploy. You will need your Project ID (Can be found in your
Google project dashboard), and your Cloud Run service name. Execute the two below commands substituting PROJECT-ID and SERVICE-NAME with your values.
gcloud builds submit --tag gcr.io/PROJECT-ID/SERVICE-NAME
gcloud run deploy --image gcr.io/PROJECT-ID/PROJECT-NAME --platform managed
Once your revision (image) is deployed, you will get a link to your live Angular app. If you go back to your cloud console, you will see a green arrow next to your service in the Cloud Run dashboard. Scaling and provisioning will automatically be taken care of.
Congratulations! You just deployed your container using Cloud Run! 🎉
Here is the demo link for the example used in this article along with the Github repo.
5. Extras
Performance:
You can make your deployment process faster, by adding a .dockerignore file like the one below.
Dockerfile
README.md
node_modules
npm-debug.log
This will tell the docker daemon not to copy those specific files to your new container. This will save some time, considering node_modules are particularly heavy.
Cleanup (Source):
While Cloud Run does not charge when the service is not in use, you might still be charged for storing the container image in Container Registry. You can delete your image or delete your Cloud project to avoid incurring charges. Deleting your Cloud project stops billing for all the resources used within that project.
Original Source: https://medium.com/@marwan.helali01/deploying-an-angular-app-using-google-cloud-run-7a4d59048edd
Top comments (4)
Thanks for the tutorial. There is a problem with the order of the steps. (Perhaps this is because of changes to GCP)
At the top, you say to create a service in Cloud Run. But Cloud Run does not let you create a service without selecting the container image URL. It doesn't let you proceed to the next step.
Therefore I first ran: gcloud builds submit --tag gcr.io/PROJECT-ID/SERVICE-NAME
After running this, the container image URL was now available to be selected. I was able then to finish the rest of the steps of "Create Service".
After finishing creating the service, I did not need to run: gcloud run deploy --image gcr.io/PROJECT-ID/PROJECT-NAME --platform managed
The image was already deployed, and I was able to see in the browser that the Angular app was being served by Cloud Run.
Hi!, I have done everything, but my docker file doesn't run when I type "docker run -p 8080:8080 app-tag", it freezes. Maybe it's my docker installation. I have one question, where the server.js file should be? btw where is the dist folder located?
I thought mine was hung also. But when I ran "docker ps -a", I could see that the container was running. I went to "localhost:8080" and, sure enough, it was running! I don't know why the "docker run" command does not return. But hitting "ctrl-c" to get back to the prompt and running "docker ps -a" again showed it was still running.
using cloud build how can we change this?