Fix Beneran Buildx CI yang Flaky, Bukan Cuma Retry
Curl retry sama plugin cache cuma nutupin gejalanya. Ini kenapa registry based build cache adalah fix beneran buat pipeline Docker Buildx yang sering timeout.

Bulan lalu pipeline GitLab gue tiba-tiba mulai gagal di titik yang aneh banget. Bukan pas proses build Docker-nya. Bukan pas testing juga. Yang gagal itu step setup, bagian yang cuma download dan install plugin Buildx sebelum kerjaan sebenarnya dimulai.
Awalnya errornya keliatan sepele. Curl timeout di sini, runner_system_failure di sana. Tapi kejadiannya berulang di dua project frontend yang beda, dan tiap kali gagal, deploy yang sebenarnya kodenya aman ikut kena block. Selama seminggu gue benerin ini dengan cara paling gampang, yaitu retry. Terus gue sadar, retry itu cuma nutupin gejala, bukan nyembuhin penyakitnya.
Key Takeaways
Setup Docker Buildx bisa gagal di CI walau kode lo aman-aman aja, soalnya pipeline download ulang binary Buildx dan rebuild layer image dari nol tiap kali run. Curl retry flags, cache plugin per project, sama install lewat package manager memang ngurangin seberapa sering download-nya gagal, tapi tetep nggak ngilangin ketergantungan ke network yang stabil. Fix yang beneran struktural itu registry based build cache pakai docker buildx build --cache-from dan --cache-to, yang reuse setup Buildx sekaligus layer image lama, bukan fetch ulang semuanya tiap run. Retry tetep dipake sebagai lapisan pengaman, bukan strategi utama.
Kenapa Docker Buildx Gagal Pas Setup CI, Bukan Pas Build?
Buildx nggak selalu udah preinstalled di GitLab runner, apalagi yang berbasis Alpine dan ringan. Kebanyakan tim install manual di step before_script, biasanya dengan curl langsung dari GitHub, chmod plus x, terus didaftarin sebagai plugin Docker CLI.
Download itu kejadian tiap kali pipeline run, cold, lewat jalur network apapun yang runner punya hari itu. Kalau runner-nya kena network blip sebentar, atau GitHub throttle request-nya, atau runner-nya sendiri kena runner_system_failure dari sisi GitLab, job-nya langsung gagal sebelum satu baris pun dari Dockerfile lo diproses. Kode lo nggak salah apa-apa. Infrastrukturnya aja lagi apes lima detik.
Juga Baca: Kenapa Docker Buildx Mengubah CI/CD Gue Selamanya
Cukup Nggak Sih Tambah curl Retry Flags Buat Fix Timeout Buildx?
Enggak, curl retry flags ngurangin angka kegagalan tapi nggak ngilangin akar masalahnya. Nambahin --retry 3 --retry-delay 5 --connect-timeout 10 ke command download buildx itu fix tercepat yang bisa lo ship, dan emang worth it. Ini ngubah network blip sesaat dari yang tadinya bikin pipeline gagal total jadi retry diam-diam aja.
Nih contohnya di before_script GitLab CI.
before_script:
- |
ARCH=${CI_RUNNER_EXECUTABLE_ARCH#*/}
BUILDX_URL="https://github.com/docker/buildx/releases/latest/download/buildx-linux-$ARCH"
mkdir -vp ~/.docker/cli-plugins/
curl --retry 3 --retry-delay 5 --connect-timeout 10 \
--silent -L --output ~/.docker/cli-plugins/docker-buildx "$BUILDX_URL"
chmod a+x ~/.docker/cli-plugins/docker-buildxIni bikin lo lebih tahan banting terhadap blip sesaat. Tapi nggak ngaruh apa-apa kalau network-nya lemot berkepanjangan, GitHub lagi rate limit, atau runner-nya emang lagi nggak bisa akses internet sama sekali selama semenit. Ini cuma patch di gejala, dipasang tepat di momen pipeline lo paling rentan, cold, tanpa cache, tanpa fallback.
Sebaiknya Cache Binary Buildx atau Install Lewat Package Manager?
Dua-duanya, dan install lewat package manager sebaiknya jadi prioritas kalau ada opsinya. Cache binary hasil download antar run pipeline, pakai cache key GitLab CI, bikin lo nggak perlu fetch ulang byte yang sama dari GitHub tiap kali. Ini aja udah motong sebagian besar exposure ke network, soalnya binary-nya jarang berubah antar run.
Kalau opsinya ada, install docker-buildx lewat package manager OS malah lebih bagus lagi, soalnya step download-nya ilang total. Di runner berbasis Alpine, ini simpel banget:
before_script:
- apk add --no-cache docker-buildxSatu baris, nggak ada curl, nggak ada chmod, nggak gantung ke GitHub pas build time. Kalau image runner lo support ini, jadiin ini default lo, dengan pendekatan curl plus cache sebagai fallback buat image yang package-nya belum tersedia.
Apa Itu Registry Based Build Cache dan Kenapa Bisa Nyelesain Akar Masalahnya?
Registry based build cache itu fitur Docker Buildx yang nyimpen metadata dan blob layer build di container registry, jadi build berikutnya bisa reuse itu daripada rebuild dari nol. Ini bagian yang beneran nyerang akar masalah, bukan cuma gejalanya.
Curl retry flags sama cache plugin cuma ngurusin step setup, beberapa detik sebelum build lo bahkan mulai. Dua-duanya nggak ngaruh ke proses build itu sendiri, padahal di situ justru kebanyakan waktu pipeline CI abis, buat pull base image, install ulang dependency, sama recompile layer yang sebenarnya nggak berubah dari run sebelumnya.
Registry cache ngubah apa yang perlu di-fetch pipeline dari awal. Daripada rebuild tiap layer tiap run, Buildx cek registry buat cari cache entry yang cocok terus reuse itu. Kerjaan lebih dikit berarti exposure ke network yang flaky juga lebih dikit, soalnya yang perlu di-download dan di-rebuild emang lebih sedikit.
Gimana Cara Setup docker buildx build dengan Registry Cache di GitLab CI?
Tambahin flag --cache-from dan --cache-to yang ngarah ke tag cache khusus di registry lo, bareng flag build dan push yang biasa. Nih before dan after lengkapnya.
Before, step build biasa tanpa strategi layer cache apapun:
build_job:
stage: build
script:
- docker buildx build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --push .After, udah ditambahin registry based cache:
build_job:
stage: build
script:
- docker buildx build
--cache-from type=registry,ref=$CI_REGISTRY_IMAGE:cache
--cache-to type=registry,ref=$CI_REGISTRY_IMAGE:cache,mode=max
-t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
--push .Setting mode=max bilang ke Buildx buat export semua layer ke cache, bukan cuma stage terakhir aja, dan ini penting banget kalau Dockerfile lo multi stage. Kalau registry lo belum support format cache manifest yang baru, versi inline cache yang lebih simpel bisa jadi fallback.
- docker buildx build --cache-from type=registry,ref=$CI_REGISTRY_IMAGE:latest
--build-arg BUILDKIT_INLINE_CACHE=1
-t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --push .Juga Baca: Ngatasin Next.js Docker Build OOM Kill di CI
Masih Perlu Retry Flags Nggak Kalau Udah Pakai Registry Cache?
Masih, tetep pertahanin. Registry cache ngurangin seberapa gede ketergantungan pipeline lo ke network yang stabil, tapi nggak ngilangin step setup Buildx dari pipeline sepenuhnya, dan nggak bikin registry-nya sendiri kebal dari blip. Anggap curl retry flags, cache plugin per project, sama install via package manager sebagai lapisan pengaman di bawah fix struktural ini, bukan pengganti.
Satu hal yang perlu ditegasin. Jangan cache selamanya. Rebuild tanpa cache secara terjadwal, mingguan atau dua mingguan tergantung seberapa sering base image lo dapet security patch, biar image lo tetep dapet update level OS, bukannya diam-diam reuse layer basi terus-terusan.
Pertanyaan yang Sering Diajukan
Kenapa pipeline GitLab CI gue gagal sebelum proses build Docker mulai? Biasanya ini berarti step install plugin Buildx yang gagal, bukan build-nya. Curl timeout pas download binary Buildx atau runner_system_failure dari infrastruktur GitLab bisa bikin job mati sebelum Dockerfile lo diproses sama sekali.
Apa maksudnya mode=max di docker buildx build —cache-to? Itu ngasih tau Buildx buat export data cache dari tiap stage di build multi stage, bukan cuma image final aja. Tanpa itu, stage build perantara nggak ke-cache, jadi ngebatasin seberapa banyak waktu yang beneran lo hemat pas rebuild.
Inline cache sama registry cache itu sama nggak sih? Inline cache itu bentuk lebih simpel dari registry cache yang nempelin metadata cache langsung di image yang di-push, pakai build argument BUILDKIT_INLINE_CACHE. Ini jalan di registry manapun tapi opsi export cache-nya lebih terbatas dibanding backend type=registry yang dedicated.
Perlu nggak sih pindah dari curl install ke apk add docker-buildx? Perlu, kalau image runner CI lo berbasis Alpine dan package-nya tersedia. Ini ngilangin step download yang rawan gagal sepenuhnya, dan lebih reliable dibanding tuning curl retry sebanyak apapun.
Seberapa sering sebaiknya rebuild image Docker tanpa cache? Praktik umumnya mingguan atau dua mingguan, atau disesuain sama siklus security patch base image lo. Ini nyegah lo reuse layer yang kehilangan update security level OS terus-terusan tanpa sadar.
CI yang flaky emang nyebelin banget, sampe godaan buat retry-in aja terus tuh gede. Retry sih oke sebagai jaring pengaman. Tapi kalau step setup Buildx lo masih aja gagal, atau build lo makin lama dari yang seharusnya, fix yang beneran awet itu registry based cache, bukan nambah satu flag retry lagi.


