選定前提:Kaniko と buildx(決定マトリクス)
リモート Mac は Docker Desktop/Colima が典型で、Kaniko はLinux VM 内コンテナで executor を載せることが多いです。buildx はホスト Docker が BuildKit を直接駆動し、開発と同一 DSLで CI を閉じやすいです。
| 観点 | Kaniko | docker buildx | 越境での示唆 |
|---|---|---|---|
| デーモン | ホスト dockerd 不要(executor 内) | dockerd 必須 | Mac では Kaniko も Docker 経由が主 |
| キャッシュ | --cache-repo | --cache-to type=registry,mode=max | 読み書きレポを分離 |
| 並列 | 1 job は概ね直列に近い | マルチプラットフォームで並列増 | 同一ホスト同時 build 1〜2を先に絞る |
早引き:dockerd 禁止ポリシーなら Kaniko。buildx と同じ行を Mac で再現するなら buildx。
.dockerignoreと rsync exclude を一致。- BuildKit/Docker data-root を成果物ディスクから分離。
FROMは digest ピン。
rsync によるビルドコンテキスト予熱と並行上限
-aH --delete --numeric-ids で指紋を揃え、同一ディスク宛ての同時 rsync は 1〜2 本に抑えます。
コピペ:rsync 断片(SSH 生存つき)
# RSYNC_JOBS:同一受けディスクなら 1、別ボリュームなら 2 まで
export RSYNC_PARTIAL_DIR="${RSYNC_PARTIAL_DIR:-.rsync-partial-$CI_JOB_ID}"
mkdir -p "$RSYNC_PARTIAL_DIR"
rsync -aH --delete --numeric-ids \
--partial --partial-dir="$RSYNC_PARTIAL_DIR" \
--info=stats2,misc2 \
-e 'ssh -o ConnectTimeout=30 -o ServerAliveInterval=15 -o ServerAliveCountMax=3' \
"${RSYNC_SRC_PLACEHOLDER}/" "${RSYNC_DST_PLACEHOLDER}/"
# 帯域を他ジョブと分割したい越境では KB/s 上限(例:約 8MiB/s)
# rsync … --bwlimit=8000 …
| レバー | 推奨初期値 | 上げる条件 | 下げる条件 |
|---|---|---|---|
| 同一ディスクへの同時 rsync | 1 本(最大 2) | 受け先が別 APFS ボリュームで iostat に余裕 | await > 12ms が続く・diskutil apfs list で圧迫 |
--bwlimit(KB/s) | 越境 4000〜8000、同一リージョンは外して試験 | 429 がゼロ・RTT 安定 | 他ジョブの npm/git と帯域競合 |
| SSH 生存 | ServerAliveInterval=15 | 長距離でも切断ログなし | 中間装置が ICMP を落とす場合は TCPKeepAlive 併用を検討 |
ディスク水位:80/85/90% と空き 25→12→6 GB。詳細は OCI 取得決定表と揃えて運用してください。
Registry 認証・タイムアウト・Kaniko/buildx の再試行
DOCKER_CONFIG に config.json を置くか、直前の docker login で注入。Kaniko/buildx は同一資格情報を参照します。
環境変数・フラグ(コピペ目安)
export DOCKER_CONFIG="${DOCKER_CONFIG:-$HOME/.docker-ci/$CI_JOB_ID}"
mkdir -p "$DOCKER_CONFIG"
printf '%s' "${REGISTRY_TOKEN_PLACEHOLDER}" | docker login "${REGISTRY_HOST_PLACEHOLDER}" \
-u "${REGISTRY_USER_PLACEHOLDER}" --password-stdin
# Kaniko(Linux executor コンテナ内の例)
export GOMAXPROCS="${GOMAXPROCS:-4}"
exec /kaniko/executor \
--context=dir:///workspace \
--destination="${IMAGE_REF_PLACEHOLDER}" \
--cache=true \
--cache-repo="${CACHE_REPO_PLACEHOLDER}" \
--compressed-caching=true \
--push-retry="${KANIKO_PUSH_RETRY:-8}"
# buildx(キャッシュを Registry に吐き出す例)
# docker buildx build --push \
# --cache-from "type=registry,ref=${CACHE_REF_PLACEHOLDER}" \
# --cache-to "type=registry,ref=${CACHE_REF_PLACEHOLDER},mode=max" \
# -t "${IMAGE_REF_PLACEHOLDER}" .
| 項目 | キー/フラグ | 越境の目安 | メモ |
|---|---|---|---|
| Kaniko push 再試行 | --push-retry | 5〜12 | 2 回目以降の失敗では同時 build 本数を先に下げる |
| ビルドキット進捗 | BUILDKIT_PROGRESS=plain | CI ログ用に固定 | レイヤ境界の切り分けに効く |
| 429/5xx 退避(秒) | B1…B4 | 4 → 12 → 30 → 90 | 並列 build 1〜2 に制限 |
CI キャッシュキーと失敗退避(レイヤ命中のための素子)
キー素子は Dockerfile 群・ロックファイル・ベース digest に絞り、先頭に可変タイムスタンプだけを置かないでください。
digest ピンと退避ループ(シェル断片)
# ベース digest をキャッシュキーに混ぜる(crane 例)
BASE_DIGEST="$(crane digest "${BASE_IMAGE_PLACEHOLDER}")"
echo "base=${BASE_DIGEST}" >> "$CI_WORKSPACE/.ci/cache-key.txt"
# push 失敗の 4→12→30→90 秒退避(並列 build 本数も同時に下げる)
MAX_PARALLEL_BUILDS="${MAX_PARALLEL_BUILDS:-2}"
for i in 1 2 3 4 5; do
docker buildx build --push -t "${IMAGE_REF_PLACEHOLDER}" . && break
case "$i" in
1) sleep "${B1:-4}";;
2) sleep "${B2:-12}"; MAX_PARALLEL_BUILDS=$(( MAX_PARALLEL_BUILDS > 1 ? MAX_PARALLEL_BUILDS - 1 : 1 ));;
3) sleep "${B3:-30}";;
4) sleep "${B4:-90}";;
*) echo "push 打ち切り"; exit 1;;
esac
done
| 素子 | 含める/外す | 理由 |
|---|---|---|
Dockerfile* とビルドスクリプト | 含める | レイヤ命令が変わると下流が全無効化 |
package-lock.json 等のロック | 含める | 依存レイヤが毎回ぶれるのを防ぐ |
生成された *.pb.go 等 | 原則外す(生成を CI 内に閉じる) | mtime のみ変化でキャッシュが外れる典型 |
SOURCE_DATE_EPOCH | 再現ビルドなら固定 | スタンプ由来のレイヤ揺れを抑える |
FAQ
Q. Kaniko を Mac でバイナリ直実行できるか
A. Linux executor を Docker/Colima VMに載せるのが無難。buildx はホスト Docker で可。
Q. rsync 成功でもキャッシュが外れる
A. ignore ズレ・生成物・FROM 可変タグ。crane digest でピン留め。
Q. push が 502/524
A. --push-retry と 4→12→30→90、並列 build 1〜2。
まとめと次の一手(購入・資料)
越境ではrsync・選定・再試行・キャッシュキー・ディスク水位を同表で決め、リモート Macで await/429/push を実測してください。