Introduction
In this article I will walk through the steps required to setup continuous integration environment and create build pipeline and automate deployment of a sample Angular App on Google Cloud Run. I will be using GCP stack end-end. Cloud Source Repositories for Git repository for version control, Cloud Build for creating docker containers which will be stored on Container Registry and then deploying the image on Cloud Run - serverless runtime environment. Finally, I will outline steps for configuring automated integration/deployment that will trigger builds and deployment of new version of application for any merge.
Key Concepts and Services
Cloud Source Repositories - Fully managed free git repository from Google Cloud to storing and version control of source code. Tightly integrated with Cloud Build for triggering build for continuous integration.
Docker - software that is most popularly used to build containers. Docker would combining the application code and set of instructions called DockerFile and produce a container that contains code all the required dependencies (listed as part of instructions in the docker file) to run the code.
Containers - a self contained environment that can be run on many platforms
Cloud Build - provide service similar to Docker and integrated with Cloud Source Repositories and can be triggered to produce container images and provides Continuous development and Continuous deployment. Cloud build can be configured to push the images to container registry and deployed to Cloud Run
Container Registry - Google Cloud Repository that can be used for hosting container images produced by Cloud Build
Cloud Run is fully managed serverless compute platform to deploy and running containerized application. Managed Serverless environment allows you to focus on your application and not worry about the underlying infrastructure or setting up and managing runtime environments.
Steps
- Build a sample angular application
- Create Git Repository
- Containerize the application
- Build Container Image
- Verify Image in Container Registry
- Deploy Image to Cloud Run
- Configure continuous integration / deployment (CI/CD)
Pre-requisites
- GCP account
- GCloud sdk installed on development machine
- Nodejs/Angular CLI (for angular project)
- Enable APIs on GCP - Cloud Run API, Container Registry, Cloud build
Build Sample angular application
ng new my-app
cd my-app
ng serve --open
Create Git Repository
Log on to GCP console and Create a project
From hamburger menu on left go to Source Repositories. Create a new project my-app and click Add repository button (on top right) and select Create New Repository option.
Provide name, say my-app select project id and click Create
There are multiple options to upload your code:
Option 1 - Using Google Cloud SDK
Initialize GCloud
gcloud init && git config --global credential.https://source.developers.google.com.helper gcloud.sh
Make sure to select the correct account and project created above
Add Cloud Repository as repository
git remote add google https://source.developers.google.com/p/cloud-run-blog/r/my-app
Push code from local git repository
git push --all google
Refresh browser - you should see your code
Option 2 - using SSH Authentication
Note: instructions below are for mac
Create and register key
cd ~/.ssh && ssh-keygen
Copy the file in memory
cat ~/.ssh/id_rsa.pub | pbcopy
Register SSH key on Google Cloud
Click on options on top right and click Manage SSH Keys
Clone this repository to a local Git repository:
git clone ssh://mbhasin@gmail.com@source.developers.google.com:2022/p/cloud-run-blog/r/my-app
Push the code
cd my-app2
git push -u origin master
Configure web server
Containerize your application
Before we define the Docker file we need to do one more step. By default, angular app runs on port 4200. To expose the web app we will use nginx server. Create a folder nginx under root and create file default.conf under it and add following contents.
server {
listen 80;
sendfile on;
default_type application/octet-stream;
gzip on;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.";
gzip_min_length 1100;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_comp_level 9;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ /index.html =404;
}
}
Create a DockerFile under application root and populate with following:
FROM node as builder
COPY package.json package-lock.json ./
RUN npm ci && mkdir /ng-app && mv ./node_modules ./ng-app
WORKDIR /ng-app
COPY . .
RUN npm run ng build -- --prod --output-path=dist
FROM nginx
COPY nginx/default.conf /etc/nginx/conf.d/
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /ng-app/dist /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
Checkin the code
git add .
git commit -m "containerizing the app"
git push --all google
Build Container Image
From Cloud Source Repositories page select my-app and then click on the button Edit Code (top right)
On the console window below give command to build the image
gcloud builds submit --tag gcr.io/cloud-run-blog/my-app-image
This command will use get docker image and start executing the instructions on the Dockerfile configured and included in the source code earlier
mbhasin@cloudshell:~/cloudshell_open/my-app (cloud-run-blog)$ cloud builds submit --tag gcr.io/cloud-run-blog/my-app-imageCreating temporary tarball archive of 33 file(s) totalling 558.4 KiB before compression.Some files were not included in the source upload.Check the gcloud log [/tmp/tmp.6uBFOBZmOk/logs/2020.08.17/00.02.18.534654.log] to see which files and the contents of thedefault gcloudignore file used (see `$ gcloud topic gcloudignore` to learnmore).Uploading tarball of [.] to [gs://cloud-run-blog_cloudbuild/source/1597622538.788477-eb6c8ebe5ab04462b08e8878b090e231.tgz]Created [https://cloudbuild.googleapis.com/v1/projects/cloud-run-blog/builds/97ddb164-fae6-4057-8d52-b006c13312e0].Logs are available at [https://console.cloud.google.com/cloud-build/builds/97ddb164-fae6-4057-8d52-b006c13312e0?project=268340482308].------------------------------------------------------------------------------------ REMOTE BUILD OUTPUT ------------------------------------------------------------------------------------starting build "97ddb164-fae6-4057-8d52-b006c13312e0"FETCHSOURCEFetching storage object: gs://cloud-run-blog_cloudbuild/source/1597622538.788477-eb6c8ebe5ab04462b08e8878b090e231.tgz#1597622539464344Copying gs://cloud-run-blog_cloudbuild/source/1597622538.788477-eb6c8ebe5ab04462b08e8878b090e231.tgz#1597622539464344.../ [1 files][142.8 KiB/142.8 KiB]Operation completed over 1 objects/142.8 KiB.
After successful completion you should see something like following
DONE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ID CREATE_TIME DURATION SOURCE IMAGES STATUS97ddb164-fae6-4057-8d52-b006c13312e0 2020-08-17T00:02:19+00:00 3M4S gs://cloud-run-blog_cloudbuild/source/1597622538.788477-eb6c8ebe5ab04462b08e8878b090e231.tgz gcr.io/cloud-run-blog/my-app-image (+1 more) SUCCESSm
Verify image in Container Registry
Deploy Image to Cloud Run
From Console:
Click on three vertical dots on the right end and select the option Deploy to Cloud Run
This will take you to Cloud Run page and launch the wizard to give you opportunity to configure the deployment - select Region, authentication and click Create
This will open the Cloud Run page and start the deployment. After about 1 min you will see the deployment complete.
Go to Cloud Build. You can create a separate build config file (using YAML or JSON syntax) but in our case we are using Dockerfile created earlier.
Go to Details tab and click on URL to launch the application in browser
Deploying from cloudshell CLI:
gcloud run deploy --image gcr.io/cloud-run-blog/my-app-image --platform managed
Configure CI/CD
Finally, you can automate deployment such that whenever new code is merged it will trigger cloud build and after successful build the new version of the app will be deployed.
While on Cloud Run page click on the service name my-app-image and then click Setup Continuous Deployment button on the top right corner (refer last screenshot above)
Select Cloud Source Repository and my-app for the Repository
While on Click on Settings button (gear shaped - top right of the page) and click Next. Provide Build Configuration and select Build Type as Dockerfile
You will see message - Setting up continuous deployment
Verify build trigger
If you go back to Cloud Build page and then Triggers section you will now see a trigger for my-app
Click on the name to see configuration file. It also allows you to define variables whose value can be substituted at build time. For example, project id, build id etc.
Another navigation path to configure triggers from Cloud Source Repository page. Click on link Cloud Build Triggers and it will take you to Cloud Build's Triggers section.
Then click on Create Trigger button on and list all the repositories configured in this project
Conclusion
In this blog we walked though the steps to configure development environment on GCP. From configuring Git repository to setting up automated builds for continuous integration/deployment on serverless managed environment Cloud Run.
No comments:
Post a Comment