Codebuildのローカルキャッシュでハマった話


実現したいこと

前回の記事 で構築したCIパイプラインの実行時間を短縮したい
具体的には,CodeBuildでDockerイメージを作成する際のgoモジュールを予めキャッシュしておき,ビルド毎に発生するダウンロード時間を短縮したい.

環境

  • Golang 1.13.5
  • Docker 18
  • AWS 東京リージョン

やったこと/ハマったこと

やったこと1

  • CodeBuildの設定変更
    CodeBuildのアーティファクト設定からキャッシュタイプを"ローカルキャッシュ"に変更
    オプションは"CustomCache"を選択

  • buildspec.yamlの編集

    前回作成したbuildspec.ymlに cache項目を追加


version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
    commands:
    - $(aws ecr get-login --no-include-email --region ap-northeast-1)

  pre_build:
    commands:
    - make test

  build:
    commands:
    - make build

  post_build:
    commands:
    - make push-image

#キャッシュ対象にするディレクトリを指定
cache:
  paths:
  # goモジュールの保存先
  - '/go/pkg/mod/**/*'

ハマったこと1

  • goモジュールが /go/pkg/mod/ に保存されていない
    go buildをDockerbuildの中で行っていたため ダウンロードしたモジュールは CodeBuild上で作成されたDockerコンテナの /go/pkg/mod/ に保存されていた

当然Dockerコンテナ自体をキャッシュすることは出来ないのでこの方法は破綻

go buildをCodeBuildのコンテナ上で行い,Docker build時にコピーすることに変更
これにより,goモジュールはCodeBuildコンテナの /go/pkg/mod/ に保存される

やったこと2

  • buildspec.ymlを編集
version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
      # goのランタイムが必要になったので追加
      golang: 1.13
    commands:
     - $(aws ecr get-login --no-include-email --region ap-northeast-1)

  pre_build:
    commands:
    - make test

  build:
    commands:
    # CodeBuildコンテナ上でbuildするため make buildから変更
    - CGO_ENABLED=0 go build -ldflags '-d -w -s' -o app
    - make build

  post_build:
    commands:
    - make push-image

cache:
  paths:
  - '/go/pkg/mod/**/*'

# go buildで必要になる環境変数の指定
env:
  variables:
    GOOS: linux
    GOARCH: amd64

  • DockerFileを編集
    元々はgo buildもdocker build内で行っていたので docker buildでは既に作成されたgoアプリの実行ファイルを使用してイメージを作成するようにDockerFileを編集

ハマったこと2

  • なぜかローカルキャッシュが機能していない

キャッシュの設定は上手くいっているようでログ上もローカルキャッシュを読み込んでいる(シンボリックリンクを作成している)
が,肝心のリンク先にキャッシュされているはずのファイルが存在しない.

AWSの仕様ページ を見るにローカルキャッシュが利用できない場合もあるとのことだが,今回の設定は該当していないように思える.

今回は原因調査まで行う余裕がなかったため 一旦ローカルキャッシュを諦め
S3にキャッシュさせることにした.

(課題は残るものの)完成

キャッシュ設定前後ではビルド時間が 3min43sec -> 3min09sec と多少なりキャッシュの恩恵を確認できた.
ただ,S3キャッシュはS3からキャッシュデータをダウンロードし,ビルド後にS3へアップロードするため,予めコンテナ内にデータを保持しておき,シンボリックリンクを作成するのみのローカルキャッシュと比べると時間がかかってしまう.
(今回はキャッシュデータが50MBを超えていたのでダウンロード/アップロードに時間がかかっているのが実感としてあった)