Login sudah beres dan repository budi/katalog-web sudah menunggu di Docker Hub — tetapi image hasil Section Docker dalam Pengembangan masih memakai nama pendek katalog-web:2.0, nama yang tidak menyebut registry tujuan maupun pemilik repository. Sebelum docker push bisa bekerja, image memerlukan nama lengkap yang sesuai dengan alamatnya di registry. Chapter ini membedah docker tag sampai ke mekanismenya: mengapa tag hanyalah alias, bagaimana satu image boleh memikul banyak nama sekaligus, ke mana nama tanpa namespace sebenarnya diarahkan, dan bagaimana latest bekerja tanpa sihir apa pun.
Tag Adalah Alias, Bukan Salinan #
Kita mulai dari fakta paling mendasar: image di penyimpanan lokal diidentifikasi lewat ID-nya, bukan lewat nama. Nama repository dan tag hanyalah referensi — alias yang menunjuk satu image tertentu. Perintah docker tag tidak menyalin data apa pun; perintah ini hanya memasang alias baru pada image yang sudah ada:
$ docker tag katalog-web:2.0 budi/katalog-web:2.0Perintah ini sukses tanpa mencetak satu baris pun — docker tag adalah salah satu perintah paling sunyi di CLI Docker. Tidak ada pesan berarti tidak ada kesalahan, dan alias baru pun terpasang. Mari kita buktikan hasilnya di tabel image lokal:
$ docker imagesOutput yang Dihasilkan:
REPOSITORY TAG IMAGE ID CREATED SIZE
budi/katalog-web 2.0 4d8b2e7f1a6c 2 days ago 142MB
katalog-web 2.0 4d8b2e7f1a6c 2 days ago 142MB
katalog-web dev 8f3a2c9e5b1d 3 days ago 189MB
...Baris image lain seperti nginx dan postgres dipotong agar fokus. Mari kita telaah tiga baris yang tersisa:
- Kolom
REPOSITORYdanTAG— kini ada dua baris untuk rilis yang sama:katalog-web:2.0(nama lama, polos) danbudi/katalog-web:2.0(nama lengkap baru). - Kolom
IMAGE ID— kedua baris menunjuk ID yang sama,4d8b2e7f1a6c; ini bukti bahwa keduanya adalah image yang persis sama, bukan dua salinan. - Kolom
SIZE— 142MB tidak berlipat ganda karena tidak ada satu byte pun yang disalin; disk tetap menyimpan satu set layer. Bariskatalog-web:devyang gemuk tetap berdiri sendiri sebagai image development dari Chapter Development dan Production Image.
Nama Tanpa Namespace Akan Tersesat ke library #
Mengapa nama pendek katalog-web:2.0 tidak cukup untuk push? Karena Docker melengkapi nama yang tidak ditulis penuh dengan bagian bawaannya: registry docker.io dan namespace library. Nama katalog-web:2.0 sebenarnya dibaca sebagai docker.io/library/katalog-web:2.0 — baris naming to docker.io/library/katalog-web:2.0 pada output build di Section Docker dalam Pengembangan sepanjang waktu sudah memberi tahu kita hal itu.
Masalahnya, namespace library adalah wilayah khusus official images — akun biasa tidak punya hak push ke sana. Bila Budi lupa menempelkan namespace dan langsung menjalankan docker push katalog-web:2.0, registry menolak dengan galat akses karena hak (scope) akun Budi tidak mencakup namespace tersebut:
The push refers to repository [docker.io/library/katalog-web]
denied: requested access to the resource is deniedMenempelkan username sebagai namespace — budi/katalog-web — adalah cara memberi tahu Docker Hub bahwa image ini milik akun Budi, persis alamat repository yang kita buat pada Chapter Membuat Repository.
Menunjuk Registry Lain Lewat Hostname #
Bentuk nama yang sama bekerja untuk registry selain Docker Hub: cukup awali dengan hostname registry tujuan. Contoh berikut menyiapkan image yang sama untuk GitHub Container Registry:
$ docker tag katalog-web:2.0 ghcr.io/budi/katalog-web:v2Bagian ghcr.io/ mengubah nasib push: alias ini akan dikirim ke GHCR, sedangkan budi/katalog-web:2.0 tetap ditujukan ke Docker Hub. Satu image lokal, dua alamat distribusi berbeda — berguna ketika kita ingin menyebarkan image yang sama ke beberapa registry sekaligus tanpa build ulang. Aturan deteksinya sendiri sudah kita kenal dari Chapter Memahami Image Tag: segmen pertama yang mengandung titik atau titik dua dibaca sebagai hostname registry.
Menempel Semua Nama Sejak Build #
Kita tidak harus menunggu build selesai untuk mengetik docker tag satu per satu. Perintah docker build menerima flag -t beberapa kali dalam satu kali jalan — dan karena layer-layernya sudah tersedia dari build sebelumnya, BuildKit melayani semuanya dari cache:
$ docker build -t katalog-web:2.0 -t budi/katalog-web:2.0 -t budi/katalog-web:latest .Output yang Dihasilkan (dipotong):
[+] Building 2.1s (15/15) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> [internal] load metadata for docker.io/library/node:22-alpine 0.4s
...
=> CACHED [9/15] RUN npm test 0.0s
...
=> exporting to image 0.1s
=> => exporting layers 0.0s
=> => writing image sha256:4d8b2e7f1a6c9e3b5d7f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b 0.1s
=> => naming to docker.io/library/katalog-web:2.0 0.0s
=> => naming to docker.io/budi/katalog-web:2.0 0.0s
=> => naming to docker.io/budi/katalog-web:latest 0.0sMari kita telaah ekor output tersebut:
writing image sha256:4d8b2e7f...— hanya satu image yang diekspor; seluruh langkah dilayaniCACHED, sehingga identitasnya persis dengan hasil build rilis kemarin.- Tiga baris
naming to— satu baris untuk setiap flag-t; ketiga nama menunjuk IMAGE ID yang sama persis. naming to docker.io/library/katalog-web:2.0— flag pertama yang polos kini tampak jelas arah sebenarnya: namespacelibrary. Pola multi-tag inilah fondasi strategi versioning yang kita susun tuntas pada Chapter Strategi Versioning Image — menempel nomor versi, penanda commit, danlatestsekaligus pada rilis yang sama.
Tabel image lokal kini memuat empat nama untuk satu IMAGE ID:
REPOSITORY TAG IMAGE ID CREATED SIZE
budi/katalog-web 2.0 4d8b2e7f1a6c 2 days ago 142MB
budi/katalog-web latest 4d8b2e7f1a6c 2 days ago 142MB
katalog-web 2.0 4d8b2e7f1a6c 2 days ago 142MB
katalog-web dev 8f3a2c9e5b1d 3 days ago 189MB
...Mencabut Alias dengan docker rmi #
Karena tag hanyalah alias, menghapusnya tidak serta-merta menghapus image. Perintah docker rmi pada satu nama hanya mencabut referensi tersebut — di sini kita pakai alias GHCR yang barusan dibuat dan memang tidak akan kita terbitkan:
$ docker rmi ghcr.io/budi/katalog-web:v2Output yang Dihasilkan:
Untagged: ghcr.io/budi/katalog-web:v2Kata Untagged — bukan Deleted — menandakan bahwa hanya alias yang dicabut; image tetap hidup karena tiga nama lain masih menunjuk kepadanya, dan tidak satu layer pun lepas dari disk. Baru ketika alias terakhir juga dicabut, image beserta layer-layernya benar-benar dihapus dari penyimpanan lokal — perilaku yang sudah kita bahas tuntas pada Chapter Menghapus Image. Perilaku ini membuat kita bisa bermain dengan banyak nama tanpa takut merusak image aslinya.
latest Hanyalah Tag Biasa #
Banyak pemula mengira latest punya perilaku khusus: otomatis menunjuk versi terbaru, otomatis diperbarui, atau otomatis dipilih saat pull. Kenyataannya tidak ada satu pun keajaiban seperti itu. latest hanyalah string tag biasa yang kebetulan menjadi nilai bawaan: bila kita pull tanpa menulis tag, daemon melengkapinya dengan latest; bila kita build tanpa -t bertag, nama hasil build diberi tag latest.
Konsekuensinya penting dipahami dua arah, sebagaimana sudah kita bedah pada Chapter Memahami Image Tag. Image budi/katalog-web:latest tidak akan pernah bergeser sendiri ke versi baru — nilai pada nama itu hanya berubah bila kita secara eksplisit membangun atau menandai ulang dengan tag latest, seperti yang baru saja kita lakukan pada build multi-tag di atas. Sebaliknya, docker run budi/katalog-web pada image yang sudah tersimpan lokal tidak mengecek registry sama sekali — latest milik sebuah mesin bisa saja berarti versi paling lawas di ruangan. Nilai bawaan yang sama bekerja di Compose: image: budi/katalog-web:${IMAGE_TAG:-latest} pada compose.prod.yaml kita sejak Chapter Compose Override dan Environment memakai latest hanya karena variabel IMAGE_TAG tidak diset — bukan karena tag tersebut punya perilaku khusus.
Pola Nama per Tujuan #
Menutup chapter ini, tabel berikut merangkum pola nama yang layak menjadi kebiasaan, lengkap dengan tujuan masing-masing:
| Pola nama | Contoh | Tujuan |
|---|---|---|
| Nama pendek | katalog-web:2.0 | latihan lokal; untuk push akan tersesat ke namespace library |
| Namespace pemilik | budi/katalog-web:2.0 | push dan pull pada repository milik akun di Docker Hub |
| Registry eksplisit | ghcr.io/budi/katalog-web:v2 | menyebarkan image yang sama ke registry kedua tanpa build ulang |
| Tag mengapung | budi/katalog-web:2 | penunjuk rilis minor terbaru — hanya untuk lingkungan development |
latest | budi/katalog-web:latest | penunjuk rilis stabil terbaru — kenyamanan, bukan identitas |
Referensi #
- docker image tag — CLI Reference — aturan penamaan referensi saat memasang alias baru.
- docker build — CLI Reference
— flag
-tberulang dan perilakunaming topada BuildKit. - docker image rm — CLI Reference
— semantik
UntaggeddanDeletedsaat mencabut referensi.
Image katalog-web kini memikul nama lengkap budi/katalog-web:2.0 — paspor yang dibutuhkan untuk menyeberang ke Docker Hub. Langkah berikutnya adalah perjalanan itu sendiri: mengunggah manifest dan layer ke repository, menyaksikan penghematan saat push rilis kedua, lalu menarik semuanya kembali dari mesin Siti. Seluruh mekanisme docker push dan docker pull itulah yang kita praktikkan pada chapter berikutnya.