A Cloud Engineers Blog

Posted by : at

Category : terraform

As you may know from reading my previous blog posts that I’ve been learning Terraform and what I can do with it, and recently I’ve been trying to find a better way to deploy Terraform rather than doing it locally, I then found Google Cloud Build.

What Cloud Build allows me to do is create my Terraform builds straight from my GitHub, if you want to read about how it actually works you can go here.

Also, just a side note, I only just started learning CloudBuild this week, so I’m no expert.

So how does CloudBuild launch my Terraform builds?

The way CloudBuild works is it allows you to build your code via a config file or a Docker image, I went with creating it via a config file as it allowed me to define how I wanted my Terraform to build. I guess if you had some custom code that needed to be run in a specific way then you would have your own custom docker image and use that.

My CloudBuild Lab

So I have a few Terraform configs and modules but I wanted to see how I could go about using my Minecraft config and how much quicker it would be via CloudBuild, also if you haven’t read / watched my Minecraft Terraform build you can find it here.

So below is my Terraform config that will launch my Minecraft environment, as you can see I don’t have a credentials file since this is been run directly in Google Cloud I can use the CloudBuild service account.

provider "google" {
  project     = "${var.project_name}"
  region      = "${var.region_name}"
  zone        = "${var.zone_name}"

//Aditional HDD
resource "google_compute_disk" "default" {
  name = "minecraft-disk"
  type = "pd-ssd"
  zone = "${var.zone_name}"
  physical_block_size_bytes = "16384"

//Static IP
resource "google_compute_address" "static-ip-address" {
  name = "mcs-ip"
//Create VM
resource "google_compute_instance" "default" {
  name = "${var.instance_name}"
  machine_type = "${var.machine_type}"

  boot_disk {
      initialize_params {
          image = "${var.instance_image}"
  attached_disk {
      source = "${google_compute_disk.default.self_link}"
  network_interface {
      network = "${}"
      subnetwork = "${var.subnetwork}"
      access_config {
          nat_ip = "${google_compute_address.static-ip-address.address}"

  metadata = {
      startup-script = <<SCRIPT
      mkdir -p /home/minecraft
      mkfs.ext4 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/disk/by-id/google-minecraft-disk
      mount -o discard,defaults /dev/disk/by-id/google-minecraft-disk /home/minecraft
      apt-get update
      apt-get install -y default-jre-headless
      cd /home/minecraft
      java -Xms1G -Xmx3G -d64 -jar server.jar nogui
      sed -i 's/false/true/g' eula.txt
      java -Xms1G -Xmx3G -d64 -jar server.jar nogui

//Network creation
resource "google_compute_network" "vpc-network" {
    name = "${var.instance_network}"
//firewall rules
resource "google_compute_firewall" "default" {
    name = "allow-mcs"
    network= "${}"
    allow {
        protocol = "tcp"
        ports    = ["25565"]
    source_ranges = [""]

resource "google_compute_firewall" "defaultssh" {
    name = "allow-ssh"
    network= "${}"
    allow {
        protocol = "tcp"
        ports    = ["22"]
    source_ranges = [""]

resource "google_storage_bucket" "default" {
    name     = "nlwilkingminecraftstoragebucket2019"

So for me to run this via CloudBuild I needed to tell CloudBuild how to handle it, and that is done via a cloudbuild.yaml file.

# 1. Fetch the source code
- name:
  id: build-repo
  args: ['clone', '']

# 2a. Set up GCS & BQ etc. using public terraform Docker image
- name: hashicorp/terraform
  id: terraform-init
  args: ['init']
  dir: '.'

# 2b. Create the GCS bucket using Terraform
- name: hashicorp/terraform
  id: terraform-plan
  args: ['plan']
  dir: '.'

# 2b. Create the GCS bucket using Terraform
- name: hashicorp/terraform
  id: terraform-apply
  args: ['apply', '-auto-approve']
  dir: '.'

So from what you can see above, a number of things are going to happen.

  1. It grabs the source code from my Repo
  2. It builds a Docker instance running Terraform
  3. It runs a Terraform init
  4. It Runs a Terraform plan
  5. It runs a Terraform apply with the auto approve flag.

CloudBuild lists the steps that are run and will give you some good feedback if something breaks. Cloud Build

What’s so good about using CloudBuild?

CloudBuild makes it easy to manage your build, and you don’t need to worry about having to pull your code from your repo to run it, as well as managing .JSON credentials as it’s all run under a service account, another cool thing I’ve done is made a backend which stores my state file in Google Cloud Storage so that my state is always protected, which was always a concern when running things local.


You are not limited to just GitHub either as it supports Googles source repos and Bit bucket.

I’m going to make a video about to later on to really show it off, but until then here’s a good video to watch.


Hi, my name is Nicholas Wilkinson. I am a Cloud Engineer, Google Cloud Professional Cloud Architect and Linux Nerd.