🐳
Github Actionsでのdocker buildでキャッシュを有効にする
以下を実現するGithub Actionsを作る方法を紹介する。
- Dockerイメージのビルドには BuildKit を使う
- Github Actionsのもつキャッシュの仕組みを有効にする
- Dockerイメージのタグには
YYYYMM-(コミットハッシュの頭7桁)
のように、コミットごとにユニークになる値を使う - mainブランチをビルドする際には、latestタグも付与する
このBuildKitとGithub Actionsのキャッシュを組み合わせる方法は、Dockerの公式ドキュメントに、Optimizing the workflow
として掲載されている。
これに自分のアレンジを加えた方法として紹介する。
まず、BuildKitを有効にするには、以下のdocker/setup-buildx-action@v1
を先に組み込む。
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
次にactions/cache@v2
をBuildKitのキャッシュとして使うファイルを引数に組み込む。${{ github.ref }}
にはブランチ名が入るため、これをresore-keysにいれておくと、ブランチ内でキャッシュが効くようになる。さらに、mainブランチも指定しておくことで、mainブランチ以外のfeature/xxxブランチであったとしても、mainブランチのキャッシュを使えるようになる。
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ github.ref }}-${{ github.sha }}
${{ github.ref }}
refs/head/main
タグは別途シェルスクリプトのステップで作成する。ステップ間の値渡しには環境変数を使う。この例では、YYYYMM-HASH先頭7文字
をタグにし、さらにmainブランチの場合にはカンマ区切りでlatestタグも追加している。
env:
IMAGE: 74th/githjub-actions-docker-build-with-cache
jobs:
build:
...
steps:
...
- name: create tag
run: |
SHA=${{ github.sha }}
TAG=${IMAGE}:$(TZ=UTC-9 date '+%Y%m')-${SHA:0:7}
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
LATEST=${IMAGE}:latest
echo "TAGS=$TAG,$LATEST" >> $GITHUB_ENV
else
echo "TAGS=$TAG" >> $GITHUB_ENV
fi
echo TAG $TAG
docker/build-push-action@v2
を組み込んでdocker buildを行う。ここで、先のステップのキャッシュのパスと、作成したタグを組み込む。tagsにはカンマ区切りで複数与えることができる。
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: ./
file: ./Dockerfile
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: ${{ env.TAGS }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
以上を組み合わせると、以下のYAMLができあがる。
name: build-docker
on: push
env:
IMAGE: 74th/githjub-actions-docker-build-with-cache
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: checkout
uses: actions/checkout@v1
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ github.ref }}-${{ github.sha }}
${{ github.ref }}
refs/head/main
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
- name: create tag
run: |
SHA=${{ github.sha }}
TAG=${IMAGE}:$(TZ=UTC-9 date '+%Y%m')-${SHA:0:7}
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
LATEST=${IMAGE}:latest
echo "TAGS=$TAG,$LATEST" >> $GITHUB_ENV
else
echo "TAGS=$TAG" >> $GITHUB_ENV
fi
echo TAG $TAG
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: ./
file: ./Dockerfile
builder: ${{ steps.buildx.outputs.name }}
push: false
tags: ${{ env.TAGS }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
キャッシュが効いている場合には、以下のようにログにCACHEDと書かれて、そのビルドステップは省略され、高速にビルドすることができる。
...
#12 [1/6] FROM docker.io/library/python:3.9@sha256:168fd55b03929f88cd3e1e05b9ebe8f9cc1c095af8b53a8c0cd50da04a8c3a40
#12 sha256:d23acac7e68ba122c4a36d2f678784fa44485e2b1b3ce45b3f4e162de16f7e33
#12 resolve docker.io/library/python:3.9@sha256:168fd55b03929f88cd3e1e05b9ebe8f9cc1c095af8b53a8c0cd50da04a8c3a40 done
#12 DONE 0.0s
#7 [internal] load build context
#7 sha256:d8baf4b681cfd956bd41e7dcd88e0885036e445ad5d58210350906952e0d5393
#7 transferring context: 8.29kB done
#7 DONE 0.0s
#5 [2/6] WORKDIR /app
#5 sha256:cc5bf3907fccf389eeddea6b0481756956d5d7f28d724aaa3a40ea7ee3832ba5
#5 CACHED
#6 [3/6] RUN pip install poetry
#6 sha256:28fee1bc4b7c051e0d5cabc28ba60d91893046d47339c2202ac83d7454322d16
#6 CACHED
#9 [5/6] RUN poetry install
#9 sha256:5eee4e56fd80670a93603c955cf19a8015609f7c776fd9fdbe4e029b3bb23d60
#9 CACHED
#8 [4/6] COPY pyproject.toml poetry.lock ./
#8 sha256:7ecf0a9ab931cf67405e0a6a1ff5f6fd64bb29608c49e544267d2f416ccc15f6
#8 CACHED
...
Discussion