Continuous Deployment of a Spring Boot Application on Google Cloud Run with CircleCI

Migrating on-premises applications or deploying software products to the cloud can be a daunting process. The cloud brings scalability, flexibility, high availability, and security to your business, but it’s not always easy to choose the right cloud providers for the service offerings you need. Although Amazon Web Service (AWS) and Microsoft Azure are popular choices for integration with third-party services because of their accessibility and functionality, Google Cloud Platform (GCP) can be preferable due to its efficiency and simplicity, and because it works seamlessly with modern software development tools to implement continuous deployment.

This tutorial demonstrates how you can easily and efficiently create an entire continuous deployment pipeline for a Spring Boot application by using CircleCI and GCP Cloud Run (a fully managed serverless platform) by completing the following steps:

  • applying GCP security best practices; 
  • using the gcloud command-line tool to increase productivity and favour re-usability, but also using the Google Cloud console UI for alternatives;
  • using CircleCI to build a continuous deployment (CD) pipeline on your GitHub repo;
  • using Google Container Registry (GCR) to store an app docker image from the CircleCI CD pipeline; and
  • deploying an application to Cloud Run from the CircleCI CD pipeline.

What you need

GCP Continuous deployment pipeline using CircleCI

CircleCI is a modern continuous integration and continuous delivery (CI/CD) platform that provides simple integration solutions for a variety of cloud providers. Using CircleCI, you can implement and automate the flow, as depicted in the image below:



The steps consist of...
  1. implementing a Spring Boot application and creating its Dockerfile
  2. creating a CircleCI service account in GCP,
  3. granting access at GCR and Cloud Run to your CircleCI service account,
  4. generating and copying the service account key,
  5. setting up a CircleCI pipeline and adding environment variables,
  6. creating environment variables and secrets in CircleCI,
  7. building and pushing the docker image to GCR, and 
  8. deploying the docker image to Cloud Run.

1. IMPLEMENTING A SPRING BOOT APPLICATION AND CREATING ITS DOCKERFILE 

The Spring Boot application used in this tutorial is a simple mail handler service that exposes a single POST endpoint (submit) to process contact requests for various websites.




Dockerfile:


2. CREATING A CIRCLECI SERVICE ACCOUNT IN GCP

Next, you need to create a service account in GCP that will be used for integration and communication between CircleCI and GCP. The Cloud IAM service is used to create a new service through the UI or you can run the following command line (“circle-ci-serviceID” is the display name of the service that will be referenced throughout this tutorial):
gcloud iam service-accounts create circle-ci-serviceid \
--description="For circleCI to use when deploying application" \
--display-name="circle-ci-serviceID"


3. GRANTING ACCESS AT GCR AND CLOUD RUN TO YOUR CIRCLECI SERVICE ACCOUNT

You will need to grant a few permissions to the newly created service to allow it to store container images in GCR as well as deploying and running Cloud Run services. Therefore, you should add the following roles to your CircleCI service account (circle-ci-serviceID):
  • roles/run.admin allows the CircleCI service account to create and modify Cloud Run revisions.
  • roles/storage.admin allows the CircleCI service account to store container images in GCR.
This can be achieved by using the Cloud IAM service UI or the following commands (note: Where YOUR_PROJECT_ID is the actual project IDid in GCP):

gcloud projects add-iam-policy-binding ${YOUR_PROJECT_ID} \ --member=serviceAccount:circle-ci-serviceid@${YOUR_PROJECT_ID}.iam.gserviceaccount.com \ --role=roles/run.admin gcloud projects add-iam-policy-binding ${YOUR_PROJECT_ID} \ --member=serviceAccount:circle-ci-serviceid@${YOUR_PROJECT_ID}.iam.gserviceaccount.com \ --role=roles/storage.admin

4. GENERATING AND COPYING THE SERVICE ACCOUNT KEY

From the Cloud IAM service you will need to navigate to service accounts. When you locate the CircleCI service account, click the ellipsis button to generate a key and export the json file, treating it as secret, to add it to CircleCI as an environment variable (GCLOUD_SERVICE_KEY). This will be used for authentication and authorization within GCP.


5. SETTING UP A CIRCLECI PIPELINE AND ADDING ENVIRONMENT VARIABLES

In CircleCI, follow and click on the GitHub repo containing the Spring Boot application to start configuring your deployment pipeline.


Wait for the next page to load. Then, click on project settings at the top right.


Next, click on Environment Variables.

6. CREATING ENVIRONMENT VARAIBLES AND SECRETS IN CIRCLECI

For simplicity’s sake, this tutorial will use environment variables in CircleCI to store a few secrets and other variables for injection into the deployment pipeline script (a more secure and sophisticated approach is possible—such as Google Cloud Secret Manager, Key Vault, etc.—but that is outside the scope of this tutorial). These variables are made up of three mandatory environment variables for CircleCI and GCP integration:
  • GCLOUD_SERVICE_KEY: << add json data exported in the section above >>
  • GOOGLE_COMPUTE_ZONE: << chosen the project compute zone, e.g., us >>
  • GOOGLE_PROJECT_ID: << Google project ID visible in console >>
The other variables are application-specific and consist of the credentials used to send emails through the chosen email server:
  • EMAIL_SERVER_HOST: xxxxxxxxx
  • EMAIL_SERVER_USERNAME: xxxxxxxxx
  • EMAIL_SERVER_PASSWORD: xxxxxxxxx
  • EMAIL_SERVER_PORT: xxxxxxxxx
Lastly, you can add the following information as environment variables for pipeline script reusability and cleanliness:
  • DOCKER_IMAGE: mail-handler
  • CLOUD_RUN_SERVICE_NAME: mail-handler-svc


7. BUILDING AND PUSHING THE DOCKER IMAGE TO GCR

As defined in the overall architecture, from CircleCI your first step will be to build the application and docker image and then push the docker image. To do so, simply add a new file called config.yaml into the .config folder at the root of the Spring Boot repo.



CircleCI provides orbs which are reusable snippets of code that help automate repeated processes to speed up project setup and facilitate integration with third-party tools. In the CircleCI orbs registry, there is an orb named circleci/gcp-gcr@0.12.0 that enables you to achieve one major aspect of pushing your docker image into the GCR. Therefore, only one prior step is needed to build the Spring Boot application and create the docker image (see full pipeline below).
 
Alternatively, there is also an orb called circleci/gcp-cloud-run@1.0.2 that can deploy applications directly to Cloud Run; however, it doesn’t allow easy injection of environment variables into Cloud Run. Therefore, it is best to add another step with a direct command line to perform that operation.

8. DEPLOYING THE DOCKER IMAGE TO CLOUD RUN

By adding the following script into .circleci/config.yaml you can build and push the docker image of the Spring Boot application to GCR and then deploy to Cloud Run with all the required environment variables.

version: 2.1
  orbs:
    gcp-gcr: circleci/gcp-gcr@0.12.0
  jobs:
    build_push_deploy:
      docker:
       - image: cimg/base:stable
      steps:
       - checkout
       - setup_remote_docker:
           docker_layer_caching: false
       - run:
           name: Build app and Docker image
           command: |
             docker build -t us.gcr.io/$GOOGLE_PROJECT_ID/$IMAGE_NAME:latest .
       - gcp-gcr/gcr-auth
       - gcp-gcr/push-image:
           google-project-id: GOOGLE_PROJECT_ID
           registry-url: us.gcr.io
           image: $IMAGE_NAME
       - run:
           name: Deploy to Cloud Run
           command: |
             gcloud run deploy $SERVICE_NAME \
             --image us.gcr.io/$GOOGLE_PROJECT_ID/$IMAGE_NAME:latest \
             --region $GOOGLE_COMPUTE_ZONE \
             --allow-unauthenticated \
             --platform managed \
             --set-env-vars "email.host=$EMAIL_HOST, \
                             email.username=$EMAIL_USERNAME, \
                             email.password=$EMAIL_PASSWORD, \
                             email.port=$EMAIL_PORT"
             echo
             echo "Service is deploying"
             echo GET_GCP_DEPLOY_ENDPOINT=$(gcloud run services describe $SERVICE_NAME \
                    --platform managed \
                    --region $GOOGLE_COMPUTE_ZONE \
                    --format="value(status.address.url)")
             echo "export GCP_DEPLOY_ENDPOINT=$GET_GCP_DEPLOY_ENDPOINT" >> $BASH_ENV
             source $BASH_ENV
             echo $GCP_DEPLOY_ENDPOINT
             echo
             
    workflows:
       gcp_cloud_run_deploy:
         jobs:
           - build_push_deploy


In a nutshell, these steps specify a list of actions that you want CircleCI to perform in the GCP environment. You will need to define a first step of building the docker image of the Spring Boot application from the Dockerfile. The second step is to push the docker image to the container registry (GCR). The final step is to deploy the docker image to Cloud Run while injecting environment variables, such as email host, username, password and port. 

The following screenshot shows the representation of these steps in CircleCI and Google Cloud Platform.





Google Container Registry:


Google Cloud Run:


Click on the service name to see additonal details:



Click on EDIT & DEPLOY NEW REVISION to check environment variables added from CircleCI.



Easy access to logs and metrics with Cloud Run.



Click on the service URL highlighted in red to access the Spring Boot (e.g., Swagger UI).



Benefits of using GCP 

As cloud experts, we at Phlyt strongly recommend GCP cloud infrastructures as a solid solution for integrating other modern software development tools to continuously deploy your software products. The benefits of using the Google Cloud Platform include the following:
  • best-in-class set of  modular cloud-based services that provide building blocks you can use to develop everything from simple websites to sophisticated multitier web-based applications;
  • predefined roles or permissions that provide fine-grained access control to cloud resources;
  • first-class and fully serveless managed services such as Cloud Run;
  • seamless integration with well-established applications such as GitHub and CircleCI to implement, not only continuous deployment, but also continuous integration and continuous delivery; and
  • simplicity of use with a low learning curve for concepts and terminologies, despite offering a plethora of services when compared with competitors.

Contributing Authors:
Annel Ketcha (annel@phlyt.io)
Luke Shannon (luke@phlyt.io

Comments

Popular Posts