Bangun dan Rilis Container Image dari GitHub ke DockerHub via AWS CodeBuild

tl;dr Provision build server di AWS CodeBuild menggunakan Terraform. Kemudian bangun dan rilis container image dari GitHub ke Dockerhub via AWS CodeBuild

Proses membangun dan merilis sebuah container image umumnya memerlukan sebuah build server atau CI/CD engine.

Amazon Web Services (AWS) menyediakan sebuah layanan/service bernama AWS CodeBuild yang dapat bertindak sebagai build server. CodeBuild merupakan solusi serverless sehingga kita tidak perlu mengelola infrastruktur dari build server yang kita gunakan. CodeBuild juga dapat diintegrasikan dengan banyak sumber git repository baik itu native AWS seperti CodeCommit ataupun penyedia layanan git lain yang umum seperti GitHub. Selengkapnya terkait AWS CodeBuild dapat dilihat di dokumentasi berikut.

Pada blogpost kali ini, saya akan mendiskusikan cara membangun dan merilis container image melalui AWS CodeBuild dengan sumber dari GitHub dan dengan tujuan DockerHub. Konfigurasi atau provision AWS resource menggunakan Terraform dengan backend remote (Terraform Cloud).

Skenario dan Topologi

Skenario dan topologi yang digunakan pada blog ini sebagai berikut:

topology

  • Application code disimpan di GitHub
  • Infrastructure code akan dijalankan oleh Terraform Cloud
  • AWS CodeBuild akan bertindak sebagai build server
  • Container image akan dirilis dan disimpan ke DockerHub dengan tag version dan latest

Konfigurasi pembuatan application code tidak dijelaskan secara lebih detail di blogpost ini. Blogpost ini lebih menitikberatkan konfigurasi alur pembuatan dan rilis container image via AWS CodeBuild.

Prasyarat

Sebelum melakukan konfigurasi terkait build server di AWS CodeBuild, pastikan beberapa hal ini sudah tersedia atau terkonfigurasi:

  • IAM service role dengan permission policy yang cukup. Sebagai referensi service role seminimal mungkin memiliki privilege seperti pada policy codebuildbasepolicy dan codebuildmanagedsecretpolicy
  • Dockerfile yang dijadikan acuan untuk pembuatan container image
  • Buildspec.yml yang nantinya akan menjadi acuan CodeBuild dalam pembuatan container image. Sebagai contoh bisa dapat melihat file ini

Konfigurasi

Pada artikel ini, struktur file yang digunakan oleh terraform code sebagai berikut:

devtools/
├─ devtools-apse1/
│  ├─ codebuild.tf
│  ├─ main.tf
│  ├─ parameter.tf
│  ├─ variable.tf
modules/
├─ devtools/
│  ├─ codebuild-github-dockerhub/
│  │  ├─ project.tf
│  │  ├─ variable.tf

Resource build project CodeBuild dibuat berdasarkan self managed module yang saya buat dimana di dalamnya dikonfigurasi beberapa parameter yang dijadikan template untuk membuat build project CodeBuild dengan sumber repository GitHub dan beberapa environment variable yang digunakan untuk rilis ke DockerHub. Environment variable yang digunakan beberapa diantaranya disimpan di AWS SSM Parameter Store. Referensi terrraform code berdasarkan dokumentasi terraform aws_codebuild_project dan aws_ssm_parameter.

Langkah Konfigurasi

  1. Konfigurasi saya mulai dengan membuat self managed module yang ada di directory modules/devtools/codebuild-github-dockerhub. File pertama yang saya diskusikan adalah modules/devtools/codebuild-github-dockerhub/variable.tf. Pada file ini saya definisikan variable-variable yang digunakan dalam module. Di antara variable-variable tersebut, beberapa saya definisikan default value untuk variable.

module-variable

variable "project_name" {
  type        = string
  description = "CodeBuild project name"
  default     = ""
}

variable "project_tags" {
  type        = map(string)
  description = "Set key value tags for CodeBuild project"
  default     = {}
}

variable "github_repository_url" {
  type        = string
  description = "URL of GitHub repository"
  default     = ""
}

variable "source_version" {
  type        = string
  description = "Enter a pull request, branch, commit ID, tag, or reference and a commit ID"
  default     = ""
}

variable "build_image" {
  type        = string
  description = "Container image used by build project"
  default     = ""
}

variable "environment_type" {
  type        = string
  description = "Build environment type"
  default     = "LINUX_CONTAINER"
}

variable "compute_type" {
  type        = string
  description = "Compute resource type used by build project"
  default     = "BUILD_GENERAL1_SMALL"
}

variable "priveleged" {
  type        = bool
  description = "Set to true if need to run docker daemon inside docker container"
  default     = true
}

variable "dockerhub_username_value" {
  type        = string
  description = "Value of environment variable DOCKERHUB_USERNAME"
}

variable "dockerhub_password_value" {
  type        = string
  description = "Value of environment variable DOCKERHUB_PASSWORD"
}

variable "aws_default_region_value" {
  type        = string
  description = "Value of environment variable AWS_DEFAULT_REGION"
}

variable "aws_account_id_value" {
  type        = string
  description = "Value of environment variable AWS_ACCOUNT_ID"
}

variable "image_tag_version_value" {
  type        = string
  description = "Value of environment variable IMAGE_TAG_VERSION"
}

variable "image_repo_name_value" {
  type        = string
  description = "Value of environment variable IMAGE_REPO_NAME"
}

variable "codebuild_service_role_arn" {
  type        = string
  description = "ARN of CodeBuild service role"
  default     = "arn:aws:iam::12digitsawsid:role/service-role/codebuild-apse1-service-role"
}

variable "artifact_type" {
  type        = string
  description = "Type of artifact"
  default     = "NO_ARTIFACTS"
}
  1. Berikutnya file yang akan didiskusikan adalah modules/devtools/codebuild-github-dockerhub/project.tf. Pada file ini, saya mendeklarasikan template konfigurasi build project CodeBuild dengan source repository GitHub dan disesuaikan dengan environment yang diperlukan untuk rilis container image ke DockerHub. Terraform Argument didefinisikan dengan acuan variable yang sudah didefinisikan di file modules/devtools/codebuild-github-dockerhub/variable.tf

module-project

/*
Create codebuild project with GitHub repository as source
Environment intended to use with Dockerhub as build destination
*/
resource "aws_codebuild_project" "github_project" {
  name = var.project_name
  tags = var.project_tags

  source {
    type     = "GITHUB"
    location = var.github_repository_url
  }

  source_version = var.source_version

  environment {
    image           = var.build_image
    type            = var.environment_type
    compute_type    = var.compute_type
    privileged_mode = var.priveleged

    environment_variable {
      name  = "DOCKERHUB_USERNAME"
      type  = "PARAMETER_STORE"
      value = var.dockerhub_username_value
    }

    environment_variable {
      name  = "DOCKERHUB_PASSWORD"
      type  = "PARAMETER_STORE"
      value = var.dockerhub_password_value
    }

    environment_variable {
      name  = "AWS_DEFAULT_REGION"
      type  = "PARAMETER_STORE"
      value = var.aws_default_region_value
    }

    environment_variable {
      name  = "AWS_ACCOUNT_ID"
      type  = "PARAMETER_STORE"
      value = var.aws_account_id_value
    }

    environment_variable {
      name  = "IMAGE_TAG_VERSION"
      type  = "PLAINTEXT"
      value = var.image_tag_version_value
    }

    environment_variable {
      name  = "IMAGE_REPO_NAME"
      type  = "PLAINTEXT"
      value = var.image_repo_name_value
    }
  }

  service_role = var.codebuild_service_role_arn

  artifacts {
    type = var.artifact_type
  }
}
  1. Setelah child module untuk template build project CodeBuild dengan source GitHub dan tujuan DockerHub selesai dibuat, selanjutnya adalah konfigurasi CodeBuild root module. Saya mulai dengan menjelaskan file devtools/devtools-apse1/main.tf. Di file ini saya mendeklarasikan konfigurasi terraform yang akan mengacu ke terraform cloud (app.terraform.io) sebagai backend. Dan mereferensikan nama organisasi dan workspace yang digunakan. Kemudian saya juga deklarasikan terraform provider yang digunakan yaitu hashisorp/aws dengan versi terkait. Di akhir saya deklarasikan region aws yang digunakan, mengacu ke variable aws_region yang ada di file devtools/devtools-apse1/variable.tf yang berikutnya akan saya jelaskan.

root-main

# Setup terraform cloud and workspace
terraform {
  backend "remote" {
    hostname     = "app.terraform.io"
    organization = "lanandra"

    workspaces {
      name = "devtools-ap-southeast-1"
    }
  }
}

# Setup terraform providers
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.30.0"
    }
  }

  required_version = ">= 1.2.9"
}

# Setup AWS provider
provider "aws" {
  region = var.aws_region
}
  1. Selanjutnya adalah mendefinisikan variable yang digunakan oleh CodeBuild root module di file devtools/devtools-apse1/variable.tf.

root-variable

variable "aws_region" {
  type        = string
  description = "AWS Region"
  default     = "ap-southeast-1"
}
  1. Berikutnya di file devtools/devtools-apse1/parameter.tf, saya membuat resource ssm parameter yang akan digunakan oleh build project. Parameter-parameter ini disimpan di SSM Parameter Store. Parameter tersebut nantinya akan digunakan sebagai environment variable di build project CodeBuild. Untuk value saya berikan dummy initial value di terraform code yang harapannya nanti akan diisi manual di web console setelah resource terbentuk. Hal ini untuk menghindari hardcoded value di code. Selain itu di terraform code juga dikonfigurasi lifecycle untuk mengabaikan segala bentuk perubahan value di parameter.

root-parameter

# Create parameters related to DevTools and stored in SSM parameter store
resource "aws_ssm_parameter" "codebuild_lanandra_dockerhub_username" {
  name  = "/CodeBuild/lanandra/DOCKERHUB_USERNAME"
  type  = "String"
  value = "change_me"

  lifecycle {
    ignore_changes = [
      value
    ]
  }
}

resource "aws_ssm_parameter" "codebuild_lanandra_dockerhub_password" {
  name  = "/CodeBuild/lanandra/DOCKERHUB_PASSWORD"
  type  = "SecureString"
  value = "change_me"

  lifecycle {
    ignore_changes = [
      value
    ]
  }
}

resource "aws_ssm_parameter" "codebuild_aws_region_apse1" {
  name  = "/CodeBuild/aws/REGION_APSE1"
  type  = "String"
  value = "change_me"

  lifecycle {
    ignore_changes = [
      value
    ]
  }
}

resource "aws_ssm_parameter" "codebuild_lanandra_aws_account_id" {
  name  = "/CodeBuild/lanandra/AWS_ACCOUNT_ID"
  type  = "String"
  value = "change_me"

  lifecycle {
    ignore_changes = [
      value
    ]
  }
}
  1. Berikutnya di file devtools/devtools-apse1/codebuild.tf, saya membuat build project CodeBuild dengan referensi dari child module /devtools/codebuild-github-dockerhub yang sudah saya buat sebelumnya. Di dalam konfigurasi CodeBuild root module ini saya deklarasikan nama CodeBuild project, GitHub repository url, nama git branch yang digunakan, build image CodeBuild. Kemudian value dari environment variable yang digunakan oleh build project. Beberapa di antaranya mengacu ke nama parameter yang ada di SSM Parameter Store, kecuali image tag version dan image repo name yang merupakan plain text value yang diinput secara langsung. Terakhir saya deklarasikan juga key value tags yang digunakan oleh build project.

root-codebuild

# Create CodeBuild project from module
module "steampipe_container_agent" {
  source = "../../modules/devtools/codebuild-github-dockerhub/"

  project_name          = "steampipe-container-agent"
  github_repository_url = "https://github.com/lanandra/steampipe-container-agent.git"
  source_version        = "main"
  build_image           = "aws/codebuild/standard:6.0"

  dockerhub_username_value = "/CodeBuild/lanandra/DOCKERHUB_USERNAME"
  dockerhub_password_value = "/CodeBuild/lanandra/DOCKERHUB_PASSWORD"
  aws_default_region_value = "/CodeBuild/aws/REGION_APSE1"
  aws_account_id_value     = "/CodeBuild/lanandra/AWS_ACCOUNT_ID"
  image_tag_version_value  = "v0.1.0"
  image_repo_name_value    = "lanandra/steampipe-container-agent"

  project_tags = {
    Name        = "steampipe-container-agent"
    Environment = "Production"
    Owner       = "Luthfi"
  }
}
  1. Berikutnya adalah melakukan commit dan push terraform code ke repository. Dan lakukan terraform plan dan terraform apply di Terraform Cloud workspace agar infrastructure dapat dibuat/provisioned. Untuk bagian ini hanya saya tampilkan simulasinya saja. Jika ingin melihat lebih detail bagaimana proses provisioning resource AWS via Terraform Cloud, silahkan lihat blogpost saya berikut ini.

tfcloud-plan-apply

  1. Setelah provisioning resource via Terraform Cloud sudah selesai. Langkah selanjutnya adalah memastikan resource-resource berhasil terbentuk. Kita dapat menggunakan AWS web console untuk memastikannya. Resource pertama yang akan kita verifikasi adalah parameter di SSM Parameter Store. Masuk ke halaman service Parameter Store, pastikan parameter yang didefinisikan di terraform code sudah berhasil terbentuk.

verify-ssm-parameter

  1. Ubah atau update nilai atau value dari tiap parameter yang sudah didefinisikan sesuai dengan kebutuhan. Sebagai contoh saya ubah nilai parameter /CodeBuild/aws/REGION_APSE1 menjadi nama region yang saya gunakan yaitu "ap-southeast-1"

update-parameter-example

  1. Selanjutnya memastikan build project CodeBuild sudah berhasil terbentuk. Masuk ke halaman service CodeBuild, kemudian pilih menu Build projects. Pastikan build project yang didefinisikan di terraform code sudah berhasil terbentuk.

list-codebuild-project

  1. Selanjutnya masuk ke halaman detail dari build project dengan meng-klik nama project di poin sebelumnya. Kemudian masuk ke bagian Build details untuk memastikan setiap konfigurasi yang didefinisikan di terraform code sudah sesuai.

verify-codebuild-project-1

verify-codebuild-project-2

verify-codebuild-project-3

verify-codebuild-project-4

verify-codebuild-project-5

  1. Setelah itu lakukan proses build container image dengan meng-klik tombol Start build

start-build

  1. Tunggu hingga proses build selesai dan pastikan status nya Succeeded.

build-succeeded

  1. Pastikan container image sudah berhasil terkirim ke DockerHub.

verify-dockerhub

Kesimpulan

Akhirnya kita sampai di penghujung artikel ini. Ada beberapa kesimpulan atau key takeaways yang ingin saya sampaikan:

  • AWS CodeBuild merupakan service yang menyediakan layanan build server yang serverless atau kita harus mengelola infrastruktur di dalamnya.
  • AWS CodeBuild dapat diintegrasikan dengan beberapa pilihan sumber git repository yang umum, salah satunya GitHub
  • Konfigurasi build project AWS CodeBuild dapat dilakukan dengan pendekatan IaC. Sehingga kita memiliki state file dari infrastruktur yang sudah kita buat.

Silahkan kunjungi GitHub repo saya untuk melihat source code konfigurasi yang digunakan dalam artikel ini. Child module untuk template konfigurasi CodeBuild dengan sumber repository GitHub dan tujuan DockerHub dapat dilihat di directory codebuild-github-dockerhub module.

Konfigurasi root module untuk CodeBuild dapat dilihat di directory CodeBuild root module.

Sekian artikel kali ini. Jika ada saran, kritik, atau masukan silahkan tinggalkan di kolom komentar.

Iklan

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout /  Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout /  Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout /  Ubah )

Connecting to %s

Situs yang Didukung WordPress.com.

Atas ↑

%d blogger menyukai ini: