# Connect Cloud Run Services to VPC via Terraform

## Introduction

In this guide, we'll walk through setting up two Cloud Run services - a public frontend and a private backend - using Terraform. We'll use Google Artifact Registry to store our Docker images. This setup demonstrates how to create a secure, scalable microservices architecture on Google Cloud Platform.

## Prerequisites

* A Google Cloud Platform account
    
* `gcloud` CLI installed and configured
    
* Terraform installed
    
* Docker installed
    
* Git installed
    

## Getting Started

1. Clone my demo repository:
    
    ```yaml
    git clone git@github.com:finnng/demo-cloud-run-vpc.git
    cd demo-cloud-run-vpc
    ```
    
2. Set up your Google Cloud project:
    
    ```yaml
    export PROJECT_ID=your-project-id
    gcloud config set project $PROJECT_ID
    ```
    
3. Enable necessary APIs:
    
    ```yaml
    gcloud services enable run.googleapis.com artifactregistry.googleapis.com compute.googleapis.com
    ```
    
4. Create a Google Artifact Registry repository:
    
    ```yaml
    gcloud artifacts repositories create cloud-run-demo --repository-format=docker --location=us-central1
    ```
    

## Building and Pushing Docker Images

1. Build and push the backend image:
    
    ```yaml
    cd backend
    docker build --platform linux/amd64 -t us-central1-docker.pkg.dev/$PROJECT_ID/cloud-run-demo/backend:v1 .
    docker push us-central1-docker.pkg.dev/$PROJECT_ID/cloud-run-demo/backend:v1
    cd ..
    ```
    
2. Build and push the frontend image:
    
    ```yaml
    cd frontend
    docker build --platform linux/amd64 -t us-central1-docker.pkg.dev/$PROJECT_ID/cloud-run-demo/frontend:v1 .
    docker push us-central1-docker.pkg.dev/$PROJECT_ID/cloud-run-demo/frontend:v1
    cd ..
    ```
    

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Remember to choose the platform <code>--platform linux/amd64</code> Especially when you are using Mac M1 chip.</div>
</div>

## Configuring Terraform

1. Update `terraform.tfvars` with your project details:
    
    ```yaml
    project_id     = "your-project-id"
    region         = "us-central1"
    frontend_image = "us-central1-docker.pkg.dev/your-project-id/cloud-run-demo/frontend:v1"
    backend_image  = "us-central1-docker.pkg.dev/your-project-id/cloud-run-demo/backend:v1"
    ```
    
2. Initialize Terraform:
    
    ```yaml
    terraform init
    ```
    
3. Plan and apply the Terraform configuration:
    
    ```yaml
    terraform plan
    terraform apply
    ```
    

## Understanding the Configuration

Let's look at some key parts of our Terraform configuration:

### VPC and Connector Setup

```yaml
resource "google_compute_network" "vpc_network" {
  name                    = "cloud-run-network"
  auto_create_subnetworks = false
}

resource "google_vpc_access_connector" "connector" {
  name          = "vpc-con"
  ip_cidr_range = "10.8.0.0/28"
  network       = google_compute_network.vpc_network.name
  region        = var.region
}
```

This creates a VPC network and a connector, allowing our Cloud Run services to communicate securely.

### Backend Service

```yaml
resource "google_cloud_run_v2_service" "backend" {
  name     = "backend"
  location = var.region

  template {
    containers {
      image = var.backend_image
    }
    service_account = google_service_account.demo_backend_sa.email
    vpc_access {
      connector = google_vpc_access_connector.connector.id
      egress    = "PRIVATE_RANGES_ONLY"
    }
  }

  ingress = "INGRESS_TRAFFIC_INTERNAL_ONLY"
}
```

Note the `egress = "PRIVATE_RANGES_ONLY"` setting, which allows the backend to make external API calls while maintaining security.

### Frontend Service

```yaml
resource "google_cloud_run_v2_service" "frontend" {
  name     = "frontend"
  location = var.region

  template {
    containers {
      image = var.frontend_image
      env {
        name  = "BACKEND_URL"
        value = google_cloud_run_v2_service.backend.uri
      }
    }
    service_account = google_service_account.demo_frontend_sa.email
    vpc_access {
      connector = google_vpc_access_connector.connector.id
      egress    = "ALL_TRAFFIC"
    }
  }
}
```

The frontend service is configured to access the backend securely through the VPC connector.

## Testing the Setup

After applying the Terraform configuration, you can test your setup:

1. Get the URLs:
    
    ```yaml
    terraform output frontend_url
    terraform output backend_url
    ```
    
2. Open the URL in a web browser. You should see the frontend HTML, that means the frontend is publicly access.
    
3. To verify the backend is private, try accessing its URL directly (you can find it in the GCP Console). It should not be publicly accessible.
    
4. Now try to let call https://{frontend\_url}/request-backend. This request is call to backend and backend make an external call to https://example.com and return the html. You should see the website content of example.com
    

## Cleaning Up

To avoid incurring charges, remember to destroy the resources when you're done:

```yaml
terraform destroy
```

## Conclusion

This guide demonstrates how to set up a secure microservices architecture using Cloud Run and Terraform. By keeping the backend private and allowing the frontend to communicate with it through a VPC, we've created a scalable and secure setup.

Remember to always consider security best practices, especially in production environments. Regularly review and update your configurations to maintain cloud security standards.

Happy coding, and enjoy exploring Cloud Run and Terraform!
