Deploy applications using CircleCI, Docker, HashiCorp Terraform, and Google Cloud
Tags: devops, tutorial, cloud, circleci
Published: 2018-12-21 18:47:17

---
title: Deploy applications using CircleCI, Docker, HashiCorp Terraform, and Google Cloud
published: true
tags: devops, tutorial, cloud, circleci
canonical_url: https://circleci.com/blog/deploying-using-terraform-gcp/
---

I regularly speak at conferences and tech meetups, and lately I’ve been fielding a lot of questions regarding the continuous delivery of applications to cloud platforms, such as [Google Cloud](https://cloud.google.com), using [HashiCorp Terraform](https://www.terraform.io/). In this post, I will demonstrate how to deploy an application using CI/CD pipelines, Docker, and Terraform into a Google Cloud instance. In this example, you will create a new Google Cloud instance using a [Google Container-Optimized OS](https://cloud.google.com/container-optimized-os/docs/) host image. Google’s Container-Optimized OS is an operating system image for Compute Engine VMs that is optimized for running Docker containers. With Container-Optimized OS, you can bring your Docker containers up on Google Cloud Platform quickly, efficiently, and securely.

This tutorial also demonstrates how to use Terraform to create a new Google Cloud instance and deploy the application using this [CI/CD tutorial Docker image](https://github.com/datapunkz/python-cicd-workshop/blob/master/tutorial/cicd_101_guide.md). The image will be pulled from Docker Hub and run on the instance created from Terraform.

## Prerequisites

Before you get started you'll need to have the following:

- A [GitHub account](https://github.com/join)
- A [CircleCI account](https://circleci.com/signup/)
- A [Docker Hub account](https://hub.docker.com)
- A [Google Cloud account](https://cloud.google.com/free)

You'll also need to:
- Fork or clone the [cicd-101-workshop repo](https://github.com/datapunkz/python-cicd-workshop) locally.
- Complete the [hands on with CircleCI section in this tutorial](https://github.com/datapunkz/python-cicd-workshop/blob/rivera-demo/tutorial/cicd_101_guide.md#hands-on-with-circleci), specifically the [setting your Docker Hub credential environment variables section](https://github.com/datapunkz/python-cicd-workshop/blob/rivera-demo/tutorial/cicd_101_guide.md#set-project-level-environment-variables), which is required for the build to push the Docker image to Docker Hub.
- Ensure that a your application's [Docker image](https://circleci.com/docs/2.0/circleci-images/) exists in your Docker Hub account. A green build on CircleCI should get you there.

After you have all the prerequisites, you're ready to proceed to the next section.

## Infrastructure as code

Infrastructure as code (IaC) is the process of managing and provisioning cloud and IT resources via machine readable definition files. IaC enables organizations to provision, manage, and destroy compute resources using modern DevOps tools such as [Terraform](https://www.terraform.io/).

You'll be using IaC principles and Terraform in this post to deploy your application to Google Cloud.

## Create a Google Cloud Platform project

Use these instructions to [create a new Google Cloud project](https://github.com/GoogleCloudPlatform/community/blob/master/tutorials/getting-started-on-gcp-with-terraform/index.md#create-a-google-cloud-platform-project).

### Create and get Google Cloud Project credentials

You will need to create [Google Cloud credentials](https://github.com/GoogleCloudPlatform/community/blob/master/tutorials/getting-started-on-gcp-with-terraform/index.md#getting-project-credentials) in order to perform administrative actions using Terraform. Go to the [Create Service Account Key page](https://console.cloud.google.com/apis/credentials/serviceaccountkey). Select the default service account or create a new one, select JSON as the key type, and click **Create**. Save this JSON file in the root of `terraform/google_cloud/`.

<i>**Important security note:** Rename the file to `cicd_demo_gcp_creds.json` in order to protect your Google Cloud credentials from being published and exposed in a public GitHub repository. You can also protect the credential's JSON file from being released by simply adding the credential's JSON filename in this project's `.gitignore` file. You must be very cautious with the data in this JSON file because, if exposed, anyone with this information can hack into your Google Cloud account, create resources, and run up charges.</i>

## Install Terraform locally

First, [install Terraform locally](https://www.terraform.io/intro/getting-started/install.html).

## Set up Terraform

In a terminal, run:

```bash 
cd terraform/google_cloud/
terraform init # this installs the Google Terraform plugins
```

Next, you'll have to change some values in the `main.tf` file. You'll change the values of the Terraform variables to match your information. Change the variable `project_name`'s `default` tag to the project name you created earlier:

```HCL
variable "project_name" {
  type = "string"
  default = "cicd-workshops"
}
```
Change the variable `docker_declaration`'s `default` tag's `image` value of: `image: 'ariv3ra/python-cicd-workshop'` to the Docker image that you built and pushed to Docker Hub in the CI/CD tutorial:

```HCL
variable "docker_declaration" {
  type = "string"
  # Change the image: string to match the Docker image you want to use
  default = "spec:\n  containers:\n    - name: test-docker\n      image: 'ariv3ra/python-cicd-workshop'\n      stdin: false\n      tty: false\n  restartPolicy: Always\n"
}
```

## Terraform plan

The [`terraform plan` command](https://www.terraform.io/docs/commands/plan.html) is used to create an execution plan. Terraform performs a refresh, unless explicitly disabled, and then determines what actions are necessary to achieve the desired state specified in the configuration files. This command is a convenient way to check whether the execution plan for a set of changes matches your expectations without making any changes to real resources or to the state.

In a terminal, run:

```bash
terraform plan -out=plan.txt
```

This will show you a nice graph that lists which items Terraform will create or change.

## Terraform apply

The [`terraform apply` command](https://www.terraform.io/docs/commands/apply.html) is used to apply the changes required to reach the desired state of the configuration, or the pre-determined set of actions generated by a Terraform execution plan.

In a terminal, run:

```bash
terraform apply plan.txt
```

This executes the Terraform plan and attempts to build out a new Google Compute instance based on the plan and the Docker image defined.

## Google Compute instance IP address

When Terraform completes building the Google assets, you should see the instance's Public IP Address and it should look similar to the output below:

```bash
Public IP Address = 104.196.11.156
```

Copy the IP Address or DNS listed and paste it into a web browser with port 5000 appended to the end. The complete address should look like this:

```
https://35.237.090.42:5000
```

The new application should render a welcome message and an image. The application is a Docker container spawned from the CI/CD intro tutorial Docker image you built and pushed to CircleCI.

## Terraform destroy

Now that you have proof that your Google Compute instance and your Docker container work, you  should run the [`terraform destroy` command](https://www.terraform.io/docs/commands/destroy.html) to destroy the assets that you created in this tutorial. You can leave it up and running, but be aware that there is a cost associated with any assets running in the Google Cloud Platform and you could be liable for those costs. Google gives a generous $300 credit for its free trial sign-up, but you could easily eat through that if you leave assets running. It's up to you, but running `terraform destroy` will close out any running assets.

## Summary

In this post, you deployed the example application to a live Google Cloud instance from Docker Hub using Terraform. This example demonstrates how to manually deploy your applications using Terraform after the application's CI/CD pipeline builds green on CircleCI. With some additional tweaking of the project's CircleCI `config.yml` file, you can configure the CI/CD pipeline to automatically deploy using Terraform within the pipeline. Configuring automatic Terraform deployments are a bit more complicated and require a bit more engineering but it's definitely possible. It might be a topic for a future blog pos, so stay tuned!

If you want to learn more about CircleCI check out the [documentation](https://circleci.com/docs/2.0/) site. If you get stuck, you can reach out to the CircleCI community via the [community](https://discuss.circleci.com/) forum.

[1]: https://github.com/datapunkz/python-cicd-workshop/blob/master/tutorial/cicd_101_guide.md