Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker: リリースビルド時にlatest(masterブランチ)のレイヤーキャッシュを使うようにしたい #674

Closed
aoirint opened this issue Apr 24, 2023 · 3 comments · Fixed by #707
Labels

Comments

@aoirint
Copy link
Member

aoirint commented Apr 24, 2023

内容

Docker (BuildKit)にはレイヤーキャッシュ機能があり、ビルド済みのレイヤーをレジストリから持ってくることができます。
VOICEVOX ENGINEでは、*-buildcacheというタグでDocker Hubにpushしています。

現在、latest(masterブランチ)のビルド時にはレイヤーキャッシュ(latest-buildcache)が使われていますが、リリースビルド時にはレイヤーキャッシュが使われていません(0.15.0-buildcacheのような、まだ存在しないタグを参照するため)。

リリースビルド時に、latestのレイヤーキャッシュ(latest-buildcache)を使うようにして、Dockerイメージのリリースビルドを高速化したいです。
実際には、releaseブランチ(release-*)ごとにbuildcacheを用意する方がよくなると思いますが、CIの実装が複雑になるデメリットがあるため、余裕があれば、くらいに思っています。

経緯としては、 #639 でarm64向けイメージが追加され、BuildKit/QEMUのCPUエミュレーションによるビルドをするようになったことで、Dockerイメージのビルド時間が伸びたため、短縮したいということがあります。

参考になるかも: https://docs.docker.com/build/cache/

Pros 良くなる点

  • Dockerイメージのリリースビルドが速くなる

Cons 悪くなる点

  • リリースビルド時に、厳密なバージョン管理をしていないUbuntuやaptパッケージが古いままになることがあるかも?(要調査)
    • 例えばubuntu:20.04として新しいイメージがpushされた後、レイヤーキャッシュが使われないようになっていれば大丈夫そうです
    • 仮にCIがこの仕様で動く場合、レイヤーキャッシュの寿命は新しいubuntu:20.04がpushされるまで、になります
    • 直近のubuntu:20.04(=ubuntu:focal)の更新は、focal-20230412, focal-20230308, focal-20230301, focal-20230126と不定期に見えます

実現方法

汎用的には、こういう実装にすればいいはずです。
実際には、OS・CPU/GPUごとにレイヤーキャッシュを参照することになるため、もう少し複雑になると思いますが、現在の実装をほぼ流用できると思います。

- name: Build and Deploy Docker image
  uses: docker/build-push-action@v3
  env:
    IMAGE_NAME_AND_TAG: ${{ format('{0}:{1}', env.IMAGE_NAME, env.IMAGE_TAG) }}
    IMAGE_CACHE_FROM: ${{ format('type=registry,ref={0}:latest-buildcache,mode=max', env.IMAGE_NAME) }}
    IMAGE_CACHE_TO: ${{ env.IMAGE_TAG == 'latest' && format('type=registry,ref={0}:latest-buildcache,mode=max', env.IMAGE_NAME) || '' }}
  with:
    context: .
    builder: ${{ steps.buildx.outputs.name }}
    file: ./Dockerfile
    push: true
    tags: ${{ env.IMAGE_NAME_AND_TAG }}
    cache-from: ${{ env.IMAGE_CACHE_FROM }}
    cache-to: ${{ env.IMAGE_CACHE_TO }} 

その他

@aoirint aoirint changed the title Docker: リリースビルド時にレイヤーキャッシュを使うようにしたい Docker: リリースビルド時にlatest(masterブランチ)のレイヤーキャッシュを使うようにしたい Apr 24, 2023
@Hiroshiba
Copy link
Member

issue作成ありがとうございます! 90分はたしかに長いですね…!

全部latestのキャッシュ見る形で良いかなと思いました!
不都合生じたらdockerhubのキャッシュ消す運用とかで。

@aoirint
Copy link
Member Author

aoirint commented Jun 13, 2023

Consで挙げていたaptパッケージ(例えばOpenSSL)が古いままになる懸念ですが、ローカルでのタグ上書きや、5月末のubuntu:22.04更新(別プロジェクト)での挙動を見る限り、

  • 例えばubuntu:20.04として新しいイメージがpushされた後、レイヤーキャッシュが使われないようになっていれば大丈夫そうです
  • 仮にCIがこの仕様で動く場合、レイヤーキャッシュの寿命は新しいubuntu:20.04がpushされるまで、になります

この通りの動きをするようです。

ubuntuイメージのリリースは、1~2か月に1度は行われているようなので、そのタイミングでaptパッケージが更新されますが、
nvidia/cudaイメージのリリースはそうではなく、1度きりの可能性があるので、CUDAバージョンを更新したり、レイヤーキャッシュを削除したりしない限り、古いバージョンのaptパッケージが使われ続けるのではないかと思います。

ここまで管理するのは大変なので、

不都合生じたらdockerhubのキャッシュ消す運用とかで。

で適宜対応でいいと思いました!

@Hiroshiba
Copy link
Member

確かにnvidia/cudaの更新は遅いからあまり考えられることは少ないかもしれませんね!
その方針がいいのかなと思います!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants