🛠️

GitHub Actions で キャッシュを効かせてDockerビルドをしてECRにデプロイする with Terraform

2024/02/07に公開

はじめに

こんにちは。
株式会社ソーシャルPLUSでインフラエンジニアをやっている、isです。
主にAWS、CICD、IaC周りのことを書いていこうと思っています。

概要

  • DockerfileをビルドをしてECRにデプロイするCICDをGitHubActionsで作成します

  • 記事を書こうと思ったきっかけ

    • GitHubActionsでのキャッシュの効かせ方が近年変わったため備忘録用
    • OIDC, Docker Layer Cache, Terraform, GitHubActionsの組み合わせた記事があまりなかったため
    • CICDでキャッシュを効かせることでビルド時間が10min -> 3minになったのでキャッシュが大事だということを共有したい
  • この記事でのポイント

    • ECRなどAWSの構成をTerraformで管理する
    • GitHubActionsとAWSの認証はOpenID Connectを使って認証することでセキュリティを高める
    • GitHubActionsでのDockerビルド時にキャッシュを効かせることでCICDの高速化を行う

動作環境

  • デプロイするDockerfileはとてもシンプルな物を使用します
FROM python:bullseye

Terraform で ECR + OIDC を作成

main.tf
provider "aws" {
  region = "us-east-1"
}

data "aws_caller_identity" "current" {}
data "aws_region" "current" {}

locals {
  account_id = data.aws_caller_identity.current.account_id
  region     = data.aws_region.current.id
}

# ECRリポジトリを作成
resource "aws_ecr_repository" "ECRRepository" {
  name = "python-test"
}

# GitHubActionsからECRにPushするための権限を付与
resource "aws_iam_policy" "ecr_push_policy" {
  name = "ci-cd-ecr-push"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        "Effect" : "Allow",
        "Action" : [
          "ecr:GetDownloadUrlForLayer",
          "ecr:BatchGetImage",
          "ecr:BatchCheckLayerAvailability",
          "ecr:PutImage",
          "ecr:InitiateLayerUpload",
          "ecr:UploadLayerPart",
          "ecr:CompleteLayerUpload"
        ],
        "Resource" : ["arn:aws:ecr:${local.region}:${local.account_id}:repository/${aws_ecr_repository.ECRRepository.name}"]
      }
    ]
  })
}

# GitHubActionsで使用するOIDCプロバイダを作成
module "oidc_github" {
  source  = "unfunco/oidc-github/aws"
  version = "1.7.1"

  github_repositories = [
    "${var.github_organization}/${var.github_repository}"
  ]
  # 作成したECR Push用の権限を付与
  iam_role_policy_arns = [
    aws_iam_policy.ecr_push_policy.arn
  ]
}
  • 環境変数からGitHubのOrganization名とリポジトリ名を取得するための変数を定義します
variables.tf
variable "github_organization" {
  type        = string
  description = "GithubのOrganization名. or Organizationに所属していない場合Githubのユーザ名"
  default     = "i-s-23"
}

variable "github_repository" {
  type        = string
  description = "Githubのリポジトリ名"
  default     = "github-actions-docker-push-terraform"
}

GitHubActions で Dockerビルド + ECRへPushする

  • ActionsでDockerのLayer Cacheを使う方法

    • GithubActionsでCacheを使う方法は複数あってややこしいですが今回は docker/build-push-action の機能を使います
    • ActionsのCacheの設定が上手くいっていればActionsの実行画面で確認が可能です
      • GithubActionsは追加料金なしでPrivateリポジトリでもリポジトリ毎に10GBまでのキャッシュが利用できる(10GBを超えた分から勝手に消える)のでたいていのCICDで困ることなく使えます
  • AWSの認証情報で使用するregionとIAM Role ArnはそれぞれGithubActionsのSecretとVariablesに登録する必要があります

.github/workflows/docker-push.yml
name: Docker Build and Push

on:
  push:
    # mainブランチにPushされた時のみ実行
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    # OIDCで使用するTokenの権限
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - name: Configure AWS credentials # AWSの認証をOIDCで行う設定
        uses: aws-actions/configure-aws-credentials@v4.0.1
        with:
          role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }}
          aws-region: ${{ vars.AWS_REGION }}
      - uses: aws-actions/amazon-ecr-login@v2.0.1 # ECRへのログイン
        id: login-ecr
      - name: Set up buildx
        uses: docker/setup-buildx-action@v3.0.0 # Docker Buildxを使いビルドの高速化を行う
      - run: echo "REPOSITORY_NAME=${GITHUB_REPOSITORY#${GITHUB_REPOSITORY_OWNER}/}" >> $GITHUB_ENV
      - name: Set up meta data # Dockerイメージにタグを付与
        id: meta
        uses: docker/metadata-action@v5.3.0
        with:
          images: |
            ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}
          tags: |
            value=latest
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} # AWSのECRのレジストリ名を取得
          ECR_REPOSITORY: python-test
      - name: docker build and push ECR
        uses: docker/build-push-action@v5.1.0
        with:
          context: .
          platforms: linux/amd64 # アーキテクチャを指定
          file: ./Dockerfile
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha # GithubActionsのCacheを使うという設定
          cache-to: type=gha,mode=max
          provenance: false

  • mainブランチにPushされるとCICDが実行されてECRにイメージがPushされます
    • このようにECRでLatestのタグが付与された状態になっていれば成功です

参考資料

SocialPLUS Tech Blog

Discussion