仕事で m3 mac 使ってて、 Lima を使ってコンテナを利用している。 Artifact Registry への認証の仕組みを整備しているので、備忘のためメモ。
前提は direnv 使ってディレクトリごとに認証情報とか設定を環境変数で切り替えてる。 Google 認証情報も Application Default Credentials (ADC)主体。
環境
- macOS Sequoia
- Lima 2.0.3
方針
- ホスト側で ADC を管理する
- Lima VM へ環境変数を伝搬する
- VM 内では docker-credential-gcr を利用する
- Artifact Registry 認証は docker-credential-gcr に委譲する
つまり認証情報はホスト側へ集約。lima vmは参照のみ。
構成は以下:
Host +- ADC +- wrapper script +- Lima Lima VM +- docker-credential-gcr +- nerdctl + containerd / docker + dockerd
Lima VM の準備
VM 内へ docker-credential-gcr を導入する。これは Lima VM のスタートアップスクリプトを仕込む。 またホスト側のホームディレクトリはマウントしておく。 ADC の application_default_credentials.json はホーム以下に存在する前提。 docker-credential-gcr は latest を取得しているため、再現性を重視する場合は取得するリリースを固定する。
# lima.yaml provision: - mode: system script: | #!/bin/bash set -e -u -o pipefail # Global variable for secure temporary directory (for exit trap scope) __temp_dir="" # Check if a list of required commands are installed and available check-required-commands() { local cmd for cmd in "$@"; do if ! command -v "${cmd}" >/dev/null 2>&1; then printf "ERROR: '%s' is required but not installed.\n" "${cmd}" >&2 return 1 fi done } # Fetch the latest release asset URL for the target repository get-latest-asset-url() { local api_url='https://api.github.com/repos/GoogleCloudPlatform/docker-credential-gcr/releases/latest' local url url="$(curl -sSf "${api_url}" | jq -r '.assets[] | select(.name | contains("linux_arm64")) | .browser_download_url')" if [[ -z "${url}" || "${url}" == "null" ]]; then return 1 fi printf "%s\n" "${url}" } main() { # 1. Verify required commands are available if ! check-required-commands jq curl tar; then return 1 fi # 2. Fetch the latest release asset URL via helper function printf "Fetching latest release metadata from GitHub API...\n" local download_url if ! download_url="$(get-latest-asset-url)"; then printf "ERROR: Failed to find asset in the latest release.\n" >&2 return 1 fi printf "Found asset URL: %s\n" "${download_url}" # 3. Create a secure temporary directory and assign to global variable __temp_dir=$(mktemp -d -t docker-credential-gcr-bootstrap-XXXXXX) # Ensure cleanup of the temp directory on exit or error (runs in global scope) trap '[[ -n "${__temp_dir}" ]] && rm -rf "${__temp_dir}"' EXIT # 4. Extract archive name from the URL and download/extract it inside the temporary directory local archive_name archive_name=$(basename "${download_url}") printf "Downloading asset '%s' to temporary directory: %s\n" "${archive_name}" "${__temp_dir}" curl -sSfL -o "${__temp_dir}/${archive_name}" "${download_url}" printf "Extracting archive...\n" tar -xzf "${__temp_dir}/${archive_name}" -C "${__temp_dir}" # 5. Move the binary to /usr/local/bin directly (mv fails strictly if file is missing) local binary_name="docker-credential-gcr" local dest_dir="/usr/local/bin" printf "Moving binary to %s ...\n" "${dest_dir}" mv "${__temp_dir}/${binary_name}" "${dest_dir}/" chmod +x "${dest_dir}/${binary_name}" printf "Successfully installed docker-credential-gcr to %s/%s!\n" "${dest_dir}" "${binary_name}" } main "$@"
Lima VM を起動して、 ~/.docker/config.json に以下の認証ヘルパが登録されていたらOK:
{ "credHelpers": { "asia-northeast2-docker.pkg.dev": "gcr" } }
環境変数の伝搬
ホスト側でラッパースクリプトを用意し、パスを通しておく。 これで単にホストからラッパースクリプトを叩くだけで、透過的に扱える。 以下の例では、 lima コマンドに渡すコマンド exec に対して、変数をコマンドスコープで指定している。
#!/bin/bash # lima whichなど、limaコマンドを指定コマンド実行前に実行すると、STDINが消費されてしまう # 明示的に退避が必須 __command='nerdctl' if lima which docker </dev/null >/dev/null 2>&1; then __command='docker' fi __env=() if [[ -n "${GOOGLE_APPLICATION_CREDENTIALS:-}" ]]; then __env+=("GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS}") fi exec lima "${__env[@]}" exec "${__command}" "$@"
動作確認
ホスト側で以下のように、Artifact Registry から pull & push を実行する。
docker pull asia-northeast2-docker.pkg.dev/PROJECT/REPOSITORY/IMAGE:TAG docker push asia-northeast2-docker.pkg.dev/PROJECT/REPOSITORY/IMAGE:TAG
メモ
Lima VM 内へ Google Cloud SDK を導入する構成も考えられるが、以下の理由で筋悪いなと思って採用してない。
- VM ごとに gcloud を管理したくない
- VM ごとに認証状態を持たせたくない
- 認証情報の管理箇所を増やしたくない
また、ADC ファイルを VM 側へコピーする構成も論外。認証情報を複製したくなかったため、ホスト側で管理する前提とした。
まとめ
- ADC はホスト側で管理
- Lima VM へ環境変数を伝搬
- docker-credential-gcr を利用
- Artifact Registry 認証は helper に委譲
これでホスト側の認証情報を管理するだけで、Lima VM 側に透過的に認証状態を参照させることが可能。 Lima VM はたまに再作成するので、気軽に消せるようになって大変よろしい。