dockerdを利用しているときに任意のリポジトリに対してパススルー・キャッシュを使う

Dockerが提供しているregistry:2のイメージを利用するとパススルーキャッシュを利用することができます。containerdを利用しているときには任意のリポジトリをパススルーキャッシュすることができますが、dockerdの場合はdocker.ioしか対応していないという問題があります。

It’s currently not possible to mirror another private registry. Only the central Hub can be mirrored.

ペパボでは、GitHub Actionsの環境にKubernertesを利用しており、Dockerについてはdind構成で提供しています。その場合に、なんか上手いこと任意のリポジトリをキャッシュできないか考えていたのですが、下記のようなラッパーをrunnerコンテナに差し込むことで対応できました。

#!/bin/bash

# 新しいイメージ名に変換する関数
translate_image_name() {
    local image_name="$1"
    local new_image_name="$image_name"

    if [[ $image_name ==ghcr.io/* ]]; then
        new_image_name="<your cache server>/${image_name#ghcr.io/}"
    fi

    echo "$new_image_name"
}

# Docker コマンドの引数を解析する
translated_args=()
is_pull_command=false
original_image_name=""
translated_image_name=""
for arg in "$@"; do
    if [[ $arg == "pull" ]]; then
        is_pull_command=true
    elif $is_pull_command && [[ $arg =~ ^ghcr.io/.* ]]; then
        original_image_name="$arg"
        translated_image_name="$(translate_image_name "$arg")"
        translated_args+=( "$translated_image_name" )
        continue
    fi
    translated_args+=( "$arg" )
done

# 変換後の引数で /usr/bin/docker を実行
/opt/docker "${translated_args[@]}"
result=$?

# pull コマンド後でイメージ名が置換されていたら、オリジナルのイメージ名でタグ付け
if [[ $result -eq 0 && $is_pull_command == true && $translated_image_name != "" && $original_image_name != "" ]]; then
    /opt/docker tag "$translated_image_name" "$original_image_name"
fi

exit $result

例としては、pullするときにイメージ名を ghcr.io/stns/stns:latest から <your cache>/ghcr.io/stns/stns:latest に書き換えることでパススルーキャッシュに捻じ曲げるようなイメージです。また透過的に動くようにその後タグも貼り直しています。

もっと早く思いつけばよかった。