この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
Dockerイメージのビルドは構成次第で長い時間が掛かり、GitHub Actions上で行う場合に頻度が高くなると利用可能枠の圧迫につながります。Organization全体の限度枠をどのくらい占めているのか、及び残り利用枠が分かりにくいこともあり、先んじてキャッシュして備えることにしました。
効率のよいキャッシュを検討する
キャッシュを目的としたActionはいくつかありましたが、今回は使いません。BuildKitプロジェクト成果物のソースコード内での利用形跡が見つからなかったためです。
BuildKitについて
以下のスライドが参考になります。Dockerfile内で効率よくキャッシュするコツにも触れているので、読まれたことがない方には特におすすめします。
BuildKitを併用してキャッシュした場合の時間については、以下のブログ記事にまとまっています。
やってみる
同様の試みをまとめた記事があったため、それをベースにしてみます。
BuildKitを有効にした状態でビルドし、結果をECRのリポジトリへプッシュします。事前にECRへのログインが必要な点については注意してください。手軽に実行して確認するために workflow_dispatch を利用します。
on: [workflow_dispatch]
name: Build Image
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_DEV }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_DEV }}
AWS_DEFAULT_REGION: ap-northeast-1
jobs:
name: BuildAndPush
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: ap-northeast-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
DOCKER_BUILDKIT: 1
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: repository-name # TODO:実際のリポジトリ名に合わせる
IMAGE_TAG: ${{ github.sha }}
run: |
docker build \
--cache-from=$ECR_REGISTRY/$ECR_REPOSITORY:latest --build-arg BUILDKIT_INLINE_CACHE=1 \
-t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
元のテンプレートから変更した箇所は
ECR_REGISTRY
の指定をaws-actions/amazon-ecr-login
のoutput参照に切り替えた- Credential 用の環境変数を共通のものに変更した
on:push
では動作しなくなった
の3点です。必要に応じて変更してください。
キャッシュを効かせていないケースとの違いは、
- 環境変数に
DOCKER_BUILDKIT: 1
を指定 - docker buuldに
--cache-from=$ECR_REGISTRY/$ECR_REPOSITORY:latest --build-arg BUILDKIT_INLINE_CACHE=1
を指定
の2点。手軽ですね。
キャッシュ前後の結果
事前にlatestタグのついたイメージがなかったため、初回は通常ビルド、直後に再実行してキャッシュが効いたビルドにしました。
cache前 | cache後 |
---|---|
12m 8s | 5m 15s |
Dockerfileにもよりますが、今回ははっきりと違いのわかる結果となりました。
Cache前のログ一部
#4 importing cache manifest from ***.dkr.ecr.ap-northeast-1.amazon...
#4 ERROR: ***.dkr.ecr.ap-northeast-1.amazonaws.com/aws-cdk/assets:latest not found
#11 [internal] load build context
#11 transferring context: 238.06kB 0.0s done
#11 DONE 0.0s
#5 [1/14] FROM docker.io/library/amazonlinux:2@sha256:2c99363fc74d3a39f0236...
..
#5 DONE 3.7s
#6 [2/14] RUN yum -y install gcc python3-devel postgresql-devel libcurl-dev...
..
#6 DONE 39.1s
#7 [3/14] RUN pip3 install pipenv
..
#7 DONE 9.2s
#8 [4/14] RUN pip3 install --upgrade setuptools
#8 1.582 Collecting setuptools
#8 1.652 Downloading setuptools-50.0.3-py3-none-any.whl (784 kB)
#8 1.865 Installing collected packages: setuptools
#8 1.865 Attempting uninstall: setuptools
#8 1.865 Found existing installation: setuptools 38.4.0
#8 1.888 Uninstalling setuptools-38.4.0:
#8 2.055 Successfully uninstalled setuptools-38.4.0
#8 2.417 Successfully installed setuptools-50.0.3
#8 DONE 2.5s
Cache後のログ一部
#4 importing cache manifest from ***.dkr.ecr.ap-northeast-1.amazon...
#4 DONE 1.9s
#10 [internal] load build context
#10 transferring context: 238.06kB done
#10 DONE 0.0s
#7 [4/14] RUN pip3 install --upgrade setuptools
#7 CACHED
..
あとがき
Dockerfileの中間データキャッシュは、繰り返してビルドを行う回数が多いほど時間短縮の点で効果がでてきます。ビルド時間長期化で悩まれている場合は手をつけてみることをおすすめします。