Registry privat menuntaskan urusan image internal — tetapi masalah distribusi image publik jarang datang sendirian. Bayangkan kantor Budi yang tumbuh menjadi lima puluh developer: setiap pagi, puluhan docker pull nginx, docker pull postgres:18-alpine, dan docker pull node:22-alpine yang sama berulang keluar ke internet, masing-masing menempuh jarak jaringan yang sama, dan semuanya menggerus kuota 100 pull per 6 jam per alamat IP yang dibagi bersama. Docker menjawab dua masalah itu dengan satu mekanisme: registry mirror — pull-through cache yang berdiri di antara daemon kita dan Docker Hub. Chapter ini memasang mirror pada daemon.json, memverifikasi efeknya lewat docker info, lalu membangun mirror sendiri dari image registry:2 yang sudah kita kuasai.

Apa Itu Registry Mirror #

Registry mirror adalah pull-through cache: server yang menyimpan salinan image publik dari Docker Hub dan melayani permintaan pull berikutnya dari salinan tersebut. Alur kerjanya bersih:

  1. Daemon klien dikonfigurasi agar semua pull image docker.io ditujukan lebih dulu ke mirror.
  2. Bila image yang diminta belum ada di cache — cache miss — mirror menariknya dari Docker Hub, menyimpan salinannya, lalu meneruskannya kepada daemon klien.
  3. Permintaan pull berikutnya untuk image yang sama dijawab langsung dari cache — cache hit — dan Docker Hub tidak disentuh sama sekali.

Mari kita telaah diagram di atas: developer pertama yang menarik sebuah image membiayai cache miss — tarikannya sekilas lebih lambat karena mirror harus berbelanja ke hulu — tetapi setiap developer berikutnya menikmati cache hit dari LAN yang nyaris instan. Satu image populer cukup dibeli sekali dari internet untuk melayani satu kantor.

Memasang Mirror pada Daemon #

Konfigurasi mirror hidup di berkas daemon.json milik daemon klien — di Linux /etc/docker/daemon.json, atau panel Settings → Docker Engine pada Docker Desktop. Cerita kita berlanjut di workstation Budi 192.168.1.20: port 5000 sudah dipakai registry privat, jadi mirror menempati port 5555:

json
{
  "registry-mirrors": ["http://192.168.1.20:5555"],
  "insecure-registries": ["192.168.1.20:5555"]
}

Dua kunci bekerja bergandengan: registry-mirrors mendaftarkan alamat mirror untuk image docker.io, sedangkan insecure-registries menegaskan bahwa mirror ini berbicara HTTP polos di jaringan lab — perlakuan yang sama dengan registry privat HTTP pada Chapter Private Registry. Setelah berkas disimpan, daemon dimulai ulang dengan sudo systemctl restart docker di Linux atau Apply & Restart di Docker Desktop. Efeknya kita konfirmasi lewat docker info:

bash
$ docker info

Output yang Dihasilkan (dipotong):

text
Client:
 Context:    default
 Debug Mode: false
...
Server:
 Containers: 5
  Running: 2
...
 Insecure Registries:
  127.0.0.0/8
  192.168.1.20:5555
 Registry Mirrors:
  http://192.168.1.20:5555
...

Baris Registry Mirrors: adalah bukti konfigurasi terbaca. Sejak saat itu setiap docker pull nginx mengetuk 192.168.1.20:5555 lebih dulu, dan Docker Hub hanya dilibatkan bila mirror belum punya salinannya.

Apa yang Berubah Setelah Mirror Aktif #

Dari sisi pengguna, tidak ada yang berubah: perintah pull tetap ditulis seperti biasa, tanpa nama mirror di dalamnya. Yang berubah adalah dua hal yang tidak tampak. Pertama, hanya image docker.io yang melewati mirror — pull yang menyebut registry lain secara eksplisit, seperti ghcr.io/budi/katalog-web:v2 atau localhost:5000/katalog-web:2.0, tetap menuju alamat yang tertulis dan tidak pernah menyinggahi mirror. Kedua, kegagalan mirror tidak menjadi kegagalan pull: bila mirror mati, penuh, atau sedang galat, daemon beralih ke mirror berikutnya pada daftar, dan bila semuanya gagal, daemon mundur ke Docker Hub asli — pull tetap berhasil, hanya lebih lambat. Jadi saat mirror sedang tidak sehat dan image tiba-tiba “turun lambat seperti dulu”, itu bukan insiden; itu perilaku fallback yang bekerja semestinya.

Mirror Publik dan Mirror Self-Host #

Dari mana kita memperoleh mirror? Ada dua jalan. Jalan pertama adalah mirror publik: sebagian penyedia jaringan, ISP, penyedia cloud, dan komunitas kampus menyediakan mirror Docker yang bisa dipakai pelanggan atau publik — cek dokumentasi penyedia jaringan Anda untuk alamat resminya. Pertimbangkan faktor kepercayaan sebelum memakai mirror pihak ketiga: seluruh image yang kita tarik melewati tangan mereka, jadi gunakan mirror dari institusi yang Anda percayai.

Jalan kedua adalah mirror sendiri, dan di sinilah materi chapter sebelumnya terbayar lunas: image registry:2 yang sama yang menjalankan registry privat dapat berperan sebagai pull-through cache dengan satu environment variable tambahan:

bash
$ docker run -d -p 5555:5000 --restart always --name registry-mirror \
    -v mirror-data:/var/lib/registry \
    -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \
    registry:2

Mari kita telaah bagian yang membedakannya dari registry privat:

  1. REGISTRY_PROXY_REMOTEURL dengan nilai registry-1.docker.io — variabel ini mengaktifkan mode proxy: registry berubah menjadi cache yang menarik dari Docker Hub — alamat upstream resmi untuk tarikan programatik — alih-alih menyimpan image dari push.
  2. -p 5555:5000 — port host 5555 diteruskan ke port 5000 container karena port 5000 di host yang sama sudah melayani registry privat; dua layanan berdampingan di satu workstation.
  3. -v mirror-data:/var/lib/registry — named volume khusus menampung cache image publik, terpisah dari volume registry-data milik registry privat agar isi keduanya tidak tercampur.

Mirror sebagai Tameng Rate Limit #

Mari kita kembali ke angka yang sudah dihafal pada Chapter Docker Hub: pengguna tanpa login dibatasi 100 pull per 6 jam per alamat IPv4, akun Personal terautentikasi 200, dan satu kantor di balik satu NAT menghabiskannya bersama-sama hingga galat toomanyrequests 429 muncul di tengah hari kerja. Mirror memotong masalah ini dari dua arah: hanya cache miss yang benar-benar melakukan perjalanan ke Docker Hub — lima puluh developer yang menarik nginx menghabiskan satu kuota, bukan lima puluh — dan kecepatan pull LAN yang stabil menghapus kebiasaan mengulang pull yang gagal-gagal. Kombinasi login terautentikasi di tiap mesin ditambah mirror self-host adalah resep standar tim dengan banyak mesin.

Kombinasi Registry Privat dan Mirror #

Dua layanan di workstation 192.168.1.20 saling melengkapi, bukan saling menggantikan: registry privat melayani image internal lewat nama eksplisit, mirror melayani image publik docker.io secara transparan. Konfigurasi klien yang matang menggabungkan keduanya dalam satu berkas daemon.json yang sama:

json
{
  "registry-mirrors": ["http://192.168.1.20:5555"],
  "insecure-registries": ["192.168.1.20:5000", "192.168.1.20:5555"]
}

Dengan blok ini, docker pull nginx berjalan lewat mirror kantor, sementara docker pull 192.168.1.20:5000/katalog-web:2.0 langsung ke registry privat — masing-masing lalu lintas menempuh jalur yang paling cepat untuk kebutuhannya. Perlu diingat bahwa keduanya masih berbicara HTTP karena kita berada di jaringan lab; di produksi, registry privat tampil sebagai registry.example.com dengan TLS dari Chapter Private Registry, dan hanya mirror yang tetap diberi pengecualian sesuai kebijakan jaringan.

Perbedaan peran keduanya patut dirangkum sebelum melangkah:

AspekRegistry mirrorRegistry privat penuh
Isisalinan image publik docker.ioimage internal milik tim
Terisi lewattarikan otomatis dari upstreamdocker push dari tim dan CI
Melayani pulluntuk nama pendek docker.iountuk nama eksplisit host dan port
Melayani pushtidak pernahtugas utamanya
Masalah yang diselesaikanlatensi dan rate limit publikkerahasiaan dan kendali penuh

Referensi #

Dengan mirror, urusan ke mana image mengalir tertangani dari semua sisi: push dan pull ke registry publik, registry privat untuk image internal, dan cache untuk image publik yang sering dipakai. Satu pertanyaan terakhir menyusul sebelum section ini ditutup: nama apa yang sepatutnya diberikan kepada setiap rilis? Kesalahan kecil dalam strategi tag — seperti bergantung penuh pada latest — bisa meruntuhkan seluruh infrastruktur distribusi yang sudah kita bangun rapi. Strategi versioning image adalah topik chapter penutup section ini.