うなすけとあれこれ

2021年05月17日

HTTP/3が喋れるcurlを定期的にbuildする

TL;DR

inductorさんが上のような記事を公開されています。ここで公開されているDockerfileによってbuildされたimageがあると嬉しいので、GitHub Actionsで定期的にbuildしたものをGitHub Container Registry上にホストすることにしました。

https://github.com/users/unasuke/packages/container/package/curl-http3

結論としてはこれだけなのですが、docker imageのtagについてちょっと手間取ったのでそれについて書こうと思います。

Docker imageのtagをある程度自由に書きたい

このimageをbuidするにあたり、 curl-http3 というimageに対して以下のtagを付けたいと思っていました。

GitHub ActionsでDocker buildを行いたいとなった場合には、以下のDocker公式が提供しているactionを使用するのが定石でしょう。

https://github.com/marketplace/actions/build-and-push-docker-images

そして、 docker/build-push-action@v2 を利用して動的なtagを付けようと、このようなYAMLを書きました。

- run: date +%Y-%m-%d
  id: date # 結果を参照できるようにidをつけておく
- run: foobar
- name: Build and push
  uses: docker/build-push-action@v2
  with:
    context: quiche
    push: true
    tags:
      - ghcr.io/unasuke/curl-http3:quiche-${{ steps.date.outputs.result }} # ここで dateの結果を利用したい
      - ghcr.io/unasuke/curl-http3:quiche-latest
    cache-from: type=local,src=/tmp/.buildx-cache
    cache-to: type=local,dest=/tmp/.buildx-cache-new

${{ steps.date.outputs }} というのは、 idがdateとなっているstepの出力を展開させるための記法です。

https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idoutputs

しかしここで文字列展開はできないらしく、以下のエラーによってActionを実行することができませんでした。

The workflow is not valid. .github/workflows/build.yml (Line: 32, Col: 13): A sequence was not expected .github/workflows/build.yml (Line: 70, Col: 13): A sequence was not expected

(どちらにせよ、上に書いたようなYAMLの内容では dateコマンドの結果を再利用することはできません、 ::set-output などの記法を適切に使用する必要があります)

どうすればいいでしょうか?

docker/metadata-action を使う

docker/metadata-action を使うと、ここで行いたいことができるようになります1

https://github.com/marketplace/actions/docker-metadata-action

もう一度、どのようなタグをつけたいかをおさらいします。

ここで、quiche版のみに注目して考えてみます。まず、quiche-latest については固定値なので docker/build-push-action@v2 だけでも実現できますが、今問題になっているのは、上でも述べたように quiche-2021-05-01 などのビルドした時点での日付が入っているものです。

これは、docker/metadata-action では type-schedule を指定することで実現できます。

https://github.com/marketplace/actions/docker-metadata-action#typeschedule

- uses: docker/metadata-action@v3
  id: meta
  with:
    images: ghcr.io/unasuke/curl-http3
    tags: |
      type=schedule,pattern={{date 'YYYY-MM-DD'}},prefix=quiche-
      type=raw,value=quiche-latest

- name: Build and push
  uses: docker/build-push-action@v2
  with:
    context: .
    push: true
    tags: ${{ steps.meta.outputs.tags }}

具体的には、上のような指定を書くことで quiche-2021-05-01 のようなtagを付けたimageをbuildすることができます。注意すべきは、この type=schedule で指定したtagが付与されるのはScheduled eventsの場合だけなので、pushしたタイミングで実行されるactionではtagが付きません。

他にもcommit hashを指定することもできます。

最終的に、 quiche-latestquiche-<YYYY-MM-DD>quiche-<commithash> の3種類のtagを付けるために、以下のようなYAMLを記述しました。

- uses: docker/metadata-action@v3
  id: meta
  with:
    images: ghcr.io/unasuke/curl-http3
    tags: |
      type=schedule,pattern={{date 'YYYY-MM-DD'}},prefix=quiche-
      type=raw,value=quiche-latest
      type=sha,prefix=quiche-

- name: Build and push
  uses: docker/build-push-action@v2
  with:
    context: quiche
    push: true
    tags: ${{ steps.meta.outputs.tags }}

実際に動いているWorkflowの定義は https://github.com/unasuke/curl-http3/blob/master/.github/workflows/build.yml にあります。

まとめ

HTTP/3が喋れるcurlを定期的にbuildして unasuke/curl-http3 に置いてあります。

また、GitHub Actionsにおいてdocker imageのtagをある程度柔軟に指定したい場合、 docker/metadata-action が解決策になるかもしれません。


  1. もともとは crazy-max/ghaction-docker-meta@v2 でしたが、この記事を書いている間にdocker org公式でメンテナンスされるようになっていました。すごい! https://github.com/docker/metadata-action/pull/78 

2021年05月17日