Registry #
Docker Registry adalah jantung distribusi dalam ekosistem Docker. Tanpa registry, image yang kamu build di laptop tidak akan pernah sampai ke server production, CI pipeline tidak akan punya artifact yang konsisten, dan kolaborasi tim akan terhenti di “tolong kirim file Docker-mu lewat email”. Registry menjawab satu pertanyaan sederhana: di mana image disimpan, dan bagaimana image itu didistribusikan ke semua host yang membutuhkannya?
Artikel ini membahas Docker Registry dari dalam ke luar. Kita akan bedah anatominya (repository, tag, manifest, layer), bandingkan registry publik dan privat, lihat workflow push-pull secara detail, dan terakhir bahas aspek keamanan yang sering diabaikan: image scanning, supply chain attack, dan strategi tag yang aman. Setelah membaca artikel ini, kamu akan bisa memilih registry yang tepat untuk organisasimu dan merancang pipeline distribusi image yang aman.
Peran Registry dalam Ekosistem Docker #
Registry adalah lapisan ketiga dalam arsitektur Docker — tempat image disimpan dan didistribusikan. Tanpa registry, satu-satunya cara berbagi image adalah dengan docker save (export ke file) lalu copy file itu ke host lain. Itu tidak skalabel, tidak auditable, dan tidak aman.
flowchart LR
DEV[Developer]
CI[CI/CD Pipeline]
subgraph REG["Registry"]
R1[Repository: api]
R2[Repository: web]
R3[Repository: worker]
end
STAGING[Staging Server]
PROD_K8S["K8s Cluster<br/>(production)"]
DEV2[Developer 2]
DEV -->|"docker push<br/>api:v1.0"| R1
CI -->|"docker push<br/>api:abc123"| R1
R1 -->|"docker pull"| STAGING
R1 -->|"docker pull"| PROD_K8S
R1 -->|"docker pull<br/>(debug)"| DEV2
Registry adalah single source of truth untuk semua image di organisasi. Image yang sudah di-push ke registry bisa diambil (pull) oleh siapa pun yang punya akses — dari laptop developer sampai node Kubernetes di tiga region berbeda. Inilah yang membuat deployment bisa reproducible dan scalable.
Kenapa Registry Penting #
TANPA registry:
✗ Image hanya ada di lokal satu mesin.
✗ Deployment butuh copy file antar host (manual, error-prone).
✗ Tidak ada version control untuk image.
✗ Tidak ada cara aman share image antar tim.
✗ Tidak ada audit trail (siapa push apa, kapan).
DENGAN registry:
✓ Image tersimpan terpusat, di-backup, di-replicate.
✓ Deployment cukup pull by tag.
✓ Version control image lewat tag dan digest.
✓ Access control per repository, per user, per tim.
✓ Audit log lengkap (siapa push/pull apa, kapan).
✓ Image scanning untuk CVE.
✓ CDN-like distribution (image di-cache di edge).
Cara mengingat: bayangkan registry sebagai “GitHub untuk Docker image”. Sama seperti GitHub menyimpan kode, registry menyimpan image. Sama seperti kamu git clone kode, kamu docker pull image. Sama seperti GitHub punya repo publik dan privat, registry juga punya konsep yang sama.
Anatomi Registry: Repository, Tag, Manifest, Layer #
Registry bukan sekadar file server untuk image. Ia adalah layanan yang mengelola empat konsep inti: repository, tag, manifest, dan layer. Keempatnya saling terkait dan membentuk hierarki yang rapi.
flowchart TB
REG["Docker Registry"]
REG --> REPO_A["Repository: myapp"]
REG --> REPO_B["Repository: nginx"]
REG --> REPO_C["Repository: postgres"]
REPO_A --> TAG_A1["Tag: latest<br/>(mutable)"]
REPO_A --> TAG_A2["Tag: v1.0.0<br/>(immutable)"]
REPO_A --> TAG_A3["Tag: v1.1.0<br/>(immutable)"]
TAG_A2 --> MANIFEST["Image Manifest<br/>(sha256:aaa...)"]
MANIFEST --> CONFIG["Image Config<br/>(CMD, ENV, dll)"]
MANIFEST --> L1["Layer 1<br/>(sha256:111)"]
MANIFEST --> L2["Layer 2<br/>(sha256:222)"]
MANIFEST --> L3["Layer 3<br/>(sha256:333)"]
Repository #
Repository adalah kumpulan image yang terkait. Biasanya satu repository = satu aplikasi atau satu layanan.
Format nama repository:
[NAMESPACE/]REPOSITORY
Contoh:
library/nginx # official image, namespace "library" implicit
unisbadri/myapi # user "unisbadri", repo "myapi"
myorg/frontend/web # org "myorg", sub-namespace "frontend", repo "web"
Repository adalah unit kontrol akses. Kamu bisa memberikan izin push ke repository tertentu untuk satu user atau satu tim, tanpa memberikan akses ke repository lain.
Tag #
Tag adalah identifier di dalam repository. Tag menunjuk ke digest tertentu dari image manifest.
Format lengkap reference:
[REGISTRY[:PORT]/][NAMESPACE/]REPOSITORY[:TAG][@DIGEST]
Contoh:
docker.io/library/nginx:1.25.3
ghcr.io/unisbadri/myapi:v2.1.0
123456789.dkr.ecr.us-east-1.amazonaws.com/prod-api:2026-02-07
myregistry.local:5000/internal/worker@sha256:b5b2b2c5...
Tag mutable, digest immutable. Tag adalah pointer yang bisa dipindahkan ke manifest lain (misalnya saat re-push). Digest adalah konten-addressable identifier yang tidak pernah berubah untuk image yang sama.
# Tag mutable: push kedua menimpa pointer
docker push myapp:v1.0 # digest A
docker push myapp:v1.0 # digest B (sekarang v1.0 menunjuk ke B)
# Digest immutable: pull by digest selalu dapat image yang sama
docker pull myapp@sha256:aaa... # selalu digest A
Anti-pattern: menggunakan taglatestdi production. Taglatestadalah default tag yang otomatis di-resolve ke digest TERBARU. Jika kamu re-push image dengan taglatest, container yang sedang jalan (atau deployment script yang pakailatest) akan menarik image BARU yang belum kamu test. Selalu gunakan tag eksplisit (semver, tanggal, commit SHA) atau digest untuk deployment.
Manifest #
Manifest adalah JSON yang mendeskripsikan image — daftar layer, konfigurasi, dan arsitektur. Manifest disimpan di registry dengan content-addressable digest.
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"digest": "sha256:b5b2b2c507a0944348e0303112d8d08cba2bd51a7f..."
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:e692418e4d3c4f7d3e4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"size": 77956920
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:3e3b1767b39736f5c0e3b4d5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5",
"size": 12345678
}
]
}
Field penting:
config.digest— pointer ke JSON konfigurasi image.layers[]— daftar layer, masing-masing dengan digest dan size.- Content-addressable — digest adalah
sha256dari konten, jadi registry bisa verifikasi integritas.
Layer #
Layer adalah unit filesystem yang immutable. Setiap instruksi Dockerfile menghasilkan satu layer. Layer-layer ini disimpan di registry dan di-cache di host yang melakukan pull.
flowchart LR
BASE["Base image<br/>ubuntu:22.04<br/>77 MB"]
PKG["apt install nginx<br/>12 MB"]
CONF["COPY config<br/>0.1 MB"]
BASE --> PKG --> CONF
CACHE[Host Local Cache]
BASE -.-> CACHE
PKG -.-> CACHE
CONF -.-> CACHE
Keuntungan layer sharing:
- Pull inkremental — kalau kamu sudah punya
ubuntu:22.04di host, pull image baru yang pakai base yang sama tidak akan download layer base lagi. - Storage efisien — registry menyimpan satu copy layer yang dipakai banyak image.
- Build cache — saat build image baru, layer yang sama dipakai ulang.
Detail menarik: layer sharing terjadi antar repository, antar tag, dan antar image. Misalnya, image python:3.12-slim dan node:20-alpine mungkin tidak berbagi layer (beda base), tapi myapp:v1.0 dan myapp:v2.0 kemungkinan besar berbagi banyak layer (base image, dependencies). Inilah kenapa upgrade dari v1 ke v2 tidak selalu “download ulang semua”.
Jenis-Jenis Docker Registry #
Registry terbagi dalam tiga kategori besar: public registry (siapa pun bisa akses), private cloud registry (dikelola provider cloud), dan self-hosted registry (kamu yang jalankan sendiri). Masing-masing punya karakteristik, kelebihan, dan trade-off yang berbeda.
Public Registry #
| Registry | Provider | Use Case |
|---|---|---|
| Docker Hub | Docker Inc. | Default, image official, komunitas |
| GitHub Container Registry (GHCR) | GitHub | Integrasi GitHub Actions |
| Quay.io | Red Hat | Image security, Clair scanning |
| AWS Public ECR Gallery | AWS | Public image dari AWS services |
Docker Hub adalah registry publik terbesar dengan 100+ miliar pull per tahun. Image “official” (nginx, redis, postgres, dll) disimpan di namespace library/ dan diaudit oleh Docker. Image komunitas bisa di-pull siapa pun tanpa autentikasi.
Kelebihan:
- Mudah digunakan, default di
dockerCLI. - Image official dijamin kualitasnya (audit berkala, security update).
- Gratis untuk repo publik.
Kekurangan:
- Rate limit untuk anonymous pull (100 pull / 6 jam per IP) dan authenticated pull (200 pull / 6 jam per user).
- Risiko supply chain: image tidak resmi bisa saja malicious atau backdoored.
- Tidak ada SLA untuk availability (biasanya tinggi, tapi bukan jaminan).
Private Cloud Registry #
| Provider | Service | Karakteristik |
|---|---|---|
| AWS | Elastic Container Registry (ECR) | Integrasi IAM, auto scan, KMS encryption |
| Google Cloud | Artifact Registry | Multi-format (Docker, Maven, npm, Python) |
| Azure | Container Registry (ACR) | Integrasi AKS, geo-replication |
| DigitalOcean | Container Registry | Sederhana, harga jelas |
Private cloud registry adalah registry yang kamu kontrol (kamu yang punya akses), tapi dikelola oleh provider cloud. Keuntungan utamanya:
- Integrasi IAM — kontrol akses lewat role AWS/GCP/Azure, tanpa manage user terpisah.
- Network proximity — registry berada di region yang sama dengan cluster, pull lebih cepat.
- Compliance — sertifikasi compliance provider cloud (SOC2, HIPAA, dll) berlaku.
- Zero operational overhead — tidak perlu install, patch, backup, scale registry sendiri.
Trade-off:
- Vendor lock-in — meski Docker Registry Protocol standar, fitur-fitur proprietary (misalnya IAM integration) tidak portable.
- Biaya — pull dari region berbeda atau ke internet biasanya ada biaya egress.
- Quota — beberapa provider membatasi jumlah repo atau ukuran total.
Self-Hosted Registry #
Registry self-hosted cocok untuk:
- Kebutuhan compliance yang sangat ketat (data center on-premise, tidak boleh keluar).
- Isolasi penuh dari internet.
- Latensi sangat rendah antar data center lokal.
- Biaya jangka panjang yang lebih rendah pada volume tinggi.
| Tool | Karakteristik |
|---|---|
| Docker Registry (official) | Image registry:2, minimal, ringan |
| Harbor | Enterprise-grade, UI, scanning, replication, RBAC |
| JFrog Artifactory | Universal artifact repo (bukan hanya container) |
| Sonatype Nexus | Universal artifact repo, support banyak format |
| GitLab Container Registry | Terintegrasi dengan GitLab CI/CD |
flowchart TB
subgraph DOCKER["Docker Registry (official)"]
A1[Minimal]
A2[REST API only]
A3[No UI]
end
subgraph HARBOR["Harbor"]
B1[Web UI]
B2[RBAC]
B3[Vulnerability scan]
B4[Replication]
B5[Image signing]
end
subgraph ARTIFACTORY["JFrog Artifactory"]
C1[Universal artifact]
C2[Build info]
C3[Enterprise features]
end
Docker Registry (registry:2) adalah implementasi minimal — hanya REST API, tidak ada UI, tidak ada scanning. Cocok untuk setup kecil atau sebagai building block untuk solusi yang lebih besar. Harbor adalah pilihan enterprise yang paling populer: UI lengkap, RBAC granular, image scanning (Trivy/Clair), replication antar instance, dan image signing (Cosign/Notary).
Rekomendasi: untuk sebagian besar tim, mulai dengan registry cloud provider (ECR, GAR, ACR) yang paling dekat dengan infrastrukturnya. Pindah ke self-hosted (Harbor) hanya ketika ada kebutuhan spesifik yang tidak bisa dipenuhi cloud registry: on-premise mandate, compliance khusus, atau volume yang membuat cloud registry mahal.
Workflow Push dan Pull #
Mari kita lihat secara detail apa yang terjadi ketika kamu docker push dan docker pull. Pemahaman ini membantu debug masalah push/pull yang sering muncul di production.
Workflow Push #
sequenceDiagram
participant CLI as docker CLI
participant D as dockerd
participant REG as Registry
CLI->>D: docker push myapp:v1.0
D->>D: Resolve image ID & layer digests
D->>REG: HEAD /v2/myapp/manifests/v1.0
REG-->>D: 404 (manifest doesn't exist)
D->>REG: POST /v2/myapp/blobs/uploads/ (start upload)
REG-->>D: 202 Accepted (upload UUID)
D->>REG: PATCH /v2/myapp/blobs/uploads/<uuid> (layer 1)
REG-->>D: 200 OK
D->>REG: PATCH /v2/myapp/blobs/uploads/<uuid> (layer 2)
REG-->>D: 200 OK
D->>REG: PUT /v2/myapp/blobs/uploads/<uuid>?digest=sha256:... (finalize)
REG-->>D: 201 Created
D->>REG: PUT /v2/myapp/manifests/v1.0 (push manifest)
REG-->>D: 201 Created
D-->>CLI: push complete
Langkah-langkah kunci:
- Resolve image & layer — daemon membaca image ID, lalu daftar layer yang membentuknya.
- Cek manifest existing —
HEADke registry untuk tahu apakah manifest sudah ada. Mounting trick: untuk layer yang sudah ada, daemon bisaPOST .../?mount=<digest>untuk “mount” layer dari blob lain tanpa upload ulang. - Upload layer satu per satu — layer yang tidak ada di registry di-upload via chunked upload (PATCH untuk tiap chunk).
- Push manifest — setelah semua layer ada, manifest di-push dan menunjuk ke layer-layer tersebut.
Workflow Pull #
sequenceDiagram
participant CLI as docker CLI
participant D as dockerd
participant REG as Registry
CLI->>D: docker pull myapp:v1.0
D->>REG: GET /v2/myapp/manifests/v1.0
REG-->>D: manifest (config + layers)
D->>D: Compare with local cache
D->>REG: HEAD /v2/myapp/blobs/<layer1-digest>
REG-->>D: 200 OK (exists)
D->>REG: GET /v2/myapp/blobs/<layer1-digest>
REG-->>D: layer 1 data
D->>REG: HEAD /v2/myapp/blobs/<layer2-digest>
REG-->>D: 200 OK
D->>REG: GET /v2/myapp/blobs/<layer2-digest>
REG-->>D: layer 2 data
D->>D: Apply layers (extract, snapshot)
D-->>CLI: pull complete
Optimasi yang Sering Terjadi #
Layer deduplication dan mounting: saat push, jika layer dengan digest yang sama sudah ada di registry (misalnya dari image lain), daemon tidak upload ulang — ia hanya “mount” referensi ke blob yang sudah ada. Ini yang membuat push image kedua dengan base yang sama jauh lebih cepat dari push pertama.
Parallel download: pull modern (Docker 18.09+) mendownload multiple layer secara paralel. Image dengan banyak layer kecil akan lebih cepat dari image dengan satu layer besar (relevan untuk image design).
Resume upload: chunked upload (PATCH) bisa di-resume jika koneksi putus. Ini sangat membantu untuk push image besar lewat jaringan tidak stabil.
Cache di host: setelah pull pertama, layer di-cache di /var/lib/docker/overlay2/. Pull berikutnya untuk image yang berbagi layer tidak akan download ulang.
Masalah umum di production: rate limit Docker Hub. Saat CI/CD menarik banyak image berbeda dalam waktu singkat, anonymous CI bisa kena rate limit 100 pull/6 jam. Solusinya: mirror image yang sering dipakai ke registry internal, atau gunakan Docker Hub authenticated pull dengan akun organisasi (200 pull/6 jam per user).
Authentication dan Authorization #
Registry modern mendukung beberapa mekanisme autentikasi, dari yang paling sederhana sampai yang paling sophisticated.
Tipe Autentikasi #
| Tipe | Cara Kerja | Use Case |
|---|---|---|
| Anonymous | Tidak perlu kredensial, registry publik | Docker Hub public images |
| Basic Auth | Username + password (HTTP Basic) | Registry sederhana, self-hosted |
| Bearer Token | Token JWT yang di-issue setelah login | Docker Hub, GHCR, cloud registry |
| OAuth 2.0 | Flow OAuth standar, integration dengan IdP | Enterprise, GitHub Apps |
| IAM-based | Cloud IAM (AWS IAM, GCP Service Account) | ECR, GAR, ACR |
| mTLS | Mutual TLS dengan client certificate | Zero-trust network |
Login ke Registry #
# Login ke Docker Hub
docker login
# Username: your-username
# Password: ************
# Login ke custom registry
docker login registry.example.com
# Login dengan IAM (AWS ECR)
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin 123.dkr.ecr.us-east-1.amazonaws.com
# Logout
docker logout registry.example.com
Kredensial disimpan di ~/.docker/config.json. Untuk environment CI/CD, lebih aman menggunakan short-lived token atau secret manager daripada hardcode password.
Authorization — Kontrol Akses #
Authorization adalah siapa boleh melakukan apa — biasanya lebih kompleks dari authentication.
| Aksi | Contoh |
|---|---|
| Pull | Siapa boleh pull image dari repo X? |
| Push | Siapa boleh push image ke repo Y? |
| Delete | Siapa boleh hapus image atau tag? |
| List | Siapa boleh lihat daftar image di registry? |
Implementasi authorization berbeda per registry:
- Docker Hub: role sederhana (admin, contributor, reader) per repo.
- AWS ECR: policy IAM dengan
Action: ecr:GetDownloadUrlForLayerdll. - Harbor: role granular (project admin, developer, guest) per project.
- GHCR: package visibility (public, private, internal) + GitHub team permission.
Prinsip least privilege: untuk CI/CD, buat service account khusus yang hanya punya izin push ke registry, dan token-nya di-rotate berkala. Jangan gunakan akun developer pribadi untuk push dari CI — jika token bocor, blast radius lebih kecil untuk service account yang scoped ke repo tertentu.
Image Scanning dan Supply Chain Security #
Registry bukan hanya tempat menyimpan image — ia juga titik kontrol penting untuk keamanan. Image yang dipush bisa mengandung vulnerability (CVE di package) atau bahkan malicious code (backdoor, crypto miner). Image scanning mendeteksi ini sebelum image sampai ke production.
Anatomi Image Scanning #
flowchart LR
A[Image di-push] --> B[Scanner]
B --> C{Scan type}
C -- Vulnerability --> D[Trivy, Snyk, Clair]
C -- Compliance --> E[Config scan, CIS benchmark]
C -- Secret --> F[GitLeaks, TruffleHog]
D --> G[Report CVE]
E --> H[Report config issue]
F --> I[Report leaked secret]
G --> J{Gate}
H --> J
I --> J
J -- Critical --> K[Block deploy]
J -- High --> L[Manual review]
J -- Medium/Low --> M[Deploy with monitoring]
Tool Scanning Populer #
| Tool | Tipe | Lisensi | Integrasi |
|---|---|---|---|
| Trivy | Vulnerability, misconfig, secret | Open source (Apache 2.0) | CI/CD, registry, runtime |
| Snyk | Vulnerability, license | Komersial + free tier | GitHub, GitLab, registry |
| Clair | Vulnerability (static analysis) | Open source (Apache 2.0) | Quay, Harbor |
| Docker Scout | Vulnerability, rekomendasi | Komersial (Docker subscription) | Docker Hub, Docker Desktop |
| AWS ECR Scan | Vulnerability | Included with ECR | AWS ecosystem |
| GCP Container Analysis | Vulnerability | Included with GAR | GCP ecosystem |
| Anchore | Vulnerability, policy | Open source + komersial | Jenkins, K8s |
Supply Chain Attack — Risiko Nyata #
Supply chain attack adalah serangan di mana attacker menyusup ke dependency atau tool yang kamu gunakan, sehingga malicious code sampai ke image yang kamu build. Beberapa contoh nyata:
- SolarWinds (2020) — malicious code di-update software yang dipakai banyak perusahaan.
- CodeCov (2021) — credential bocor dari tool CI, attacker memodifikasi script yang di-pull.
- event-stream npm (2018) — maintainer asli menyerahkan package ke attacker, malicious code masuk ke ribuan proyek.
- XZ Utils backdoor (2024) — malicious code di compression library, hampir masuk ke banyak distribusi Linux.
Pertahanan berlapis untuk supply chain security:
flowchart TB
A[Base image] --> B{Pin to digest?}
B -- Ya --> C[Verifikasi integrity]
B -- Tidak --> D[Auto-update bisa break]
C --> E[Build image]
E --> F{Scan?}
F -- Ya --> G[Detect CVE]
F -- Tidak --> H[Blind deploy]
G --> I{Sign image?}
I -- Ya --> J[Verifikasi signature]
I -- Tidak --> K[Anyone can replace]
J --> L[Deploy]
- Pin base image ke digest —
FROM ubuntu@sha256:abc...bukanFROM ubuntu:22.04. Ini mencegah tag mutable. - Verifikasi image signature — gunakan Cosign (bagian dari Sigstore) atau Docker Content Trust (DCT) untuk sign image.
- Scan di setiap tahap — jangan cuma scan image final, scan juga base image dan intermediate layer.
- Gunakan trusted base image —
docker.io/library/*(official) atau image dari vendor terpercaya. - Allowlist — di K8s, gunakan admission controller (OPA, Kyverno) yang hanya izinkan image dari registry yang diizinkan.
Anti-pattern: pull base image tanpa verifikasi. Jika attacker compromise Docker Hub dan menukar image library/nginx dengan image backdoored, semua build yang tidak pin ke digest akan otomatis ter-compromise. Selalu pin base image ke digest SHA256 dan verifikasi signature-nya.
Self-Hosted Docker Registry — Setup Praktis #
Untuk setup sederhana, Docker Registry official (registry:2) sudah cukup. Berikut contoh docker-compose.yml untuk registry self-hosted dengan TLS dan basic auth.
# docker-compose.yml
version: "3.9"
services:
registry:
image: registry:2
restart: always
ports:
- "5000:5000"
environment:
REGISTRY_HTTP_SECRET: a-very-long-random-string
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
volumes:
- ./auth:/auth
- registry-data:/var/lib/registry
deploy:
resources:
limits:
memory: 512M
volumes:
registry-data:
# Buat user admin
mkdir -p auth
docker run --rm \
--entrypoint htpasswd \
httpd:2.4 -bn admin secretpassword > auth/htpasswd
# Jalankan
docker compose up -d
# Login dan push
docker login registry.local:5000
docker tag myapp:v1.0 registry.local:5000/myapp:v1.0
docker push registry.local:5000/myapp:v1.0
Untuk setup enterprise, Harbor adalah pilihan yang lebih solid. Harbor menambah:
- Web UI untuk browse image dan manage user.
- Image scanning (Trivy/Clair built-in).
- Replication antar Harbor instance (multi-region).
- Image signing dan verification (Cosign, Notary).
- RBAC granular per project.
Best Practice Registry untuk Production #
Strategi Tag yang Aman #
# JANGAN di production
docker push myapp:latest # mutable, tidak reproducible
# GUNAKAN di production
docker push myapp:v1.4.2 # semantic version
docker push myapp:v1.4.2-alpine # base variant
docker push myapp:1.4.2-build.123 # build number
docker push myapp:2026-02-07-abc1234 # tanggal + short SHA
# TERBAIK untuk reproducibility
docker push myapp@sha256:b5b2b2c5... # digest penuh
Pisahkan Registry per Environment #
flowchart TB
DEV[Development] --> R1[registry.dev.internal]
STAGING[Staging] --> R2[registry.staging.internal]
PROD[Production] --> R3[registry.prod.internal]
CI[CI/CD Pipeline] --> R1
CI --> R2
CI --> R3
Memisahkan registry per environment mencegah image yang belum di-test bocor ke production, dan memudahkan audit (siapa push ke production registry).
Aktifkan Image Scanning #
Pastikan setiap image yang masuk ke registry di-scan, dan deployment di-block untuk image dengan critical CVE.
Retention Policy #
Registry yang tidak pernah dibersifikasi akan membengkak. Implementasikan retention policy:
- Keep last N tags per repository.
- Keep tags from last X days.
- Delete untagged images older than Y days.
- Archive old images ke object storage (S3, GCS) sebelum hapus.
Bersihkan Image Lama #
# Hapus image yang tidak ada tag-nya dan lebih dari 30 hari
docker exec registry /bin/registry garbage-collect \
-m /etc/docker/registry/config.yml
# Atau di Harbor: Settings > Tag Retention > buat policy otomatis
Best practice umum: atur retention policy per environment — dev/staging bisa lebih agresif (hapus setelah 7 hari), production lebih konservatif (simpan 90 hari atau sesuai compliance). Untuk disaster recovery, selalu backup registry production ke region kedua.
Decision Tree — Memilih Registry yang Tepat #
flowchart TD
A{Deployment<br/>environment?}
A -- Public internet --> B{Budget?}
B -- Minim --> C[Docker Hub free]
B -- Ada --> D[Docker Hub Pro / Team]
A -- Cloud AWS --> E[ECR]
A -- Cloud GCP --> F[Artifact Registry]
A -- Cloud Azure --> G[Container Registry]
A -- On-premise --> H{Need enterprise<br/>features?}
H -- Ya --> I[Harbor]
H -- Minimal --> J[Docker Registry 2.x]
A -- Hybrid --> K[Harbor replicated<br/>dengan cloud registry]
E --> L[Enable scan, KMS]
F --> M[Enable scan, CMEK]
G --> N[Enable scan, geo-replication]
I --> O[Setup RBAC, scan, signing]
J --> P[TLS, basic auth, backup]
Pilihan registry bukan keputusan satu kali. Banyak organisasi memulai dengan cloud registry (ECR/GAR) untuk kecepatan setup, lalu menambah Harbor untuk image tertentu yang butuh kontrol lebih (misalnya image proprietary dengan IP sensitif). Pola hybrid seperti ini umum di perusahaan besar.
Ringkasan #
- Docker Registry adalah single source of truth untuk image di organisasi. Ia menjawab “di mana image disimpan” dan “bagaimana image didistribusikan ke semua host” — tanpa registry, image hanya bisa di-share manual lewat file.
- Empat konsep inti registry: repository (kumpulan image terkait), tag (label mutable untuk identifikasi), manifest (JSON yang mendeskripsikan image), layer (unit filesystem immutable). Tag mutable, digest immutable — untuk reproducibility, selalu pull by digest.
- Tiga jenis registry: public (Docker Hub, GHCR) untuk image open source dan komunitas; private cloud (ECR, GAR, ACR) untuk image proprietary dengan integrasi IAM; self-hosted (Harbor) untuk kontrol penuh dan compliance ketat.
- Workflow push meng-upload layer satu per satu (chunked), dengan mounting trick untuk layer yang sudah ada. Workflow pull mendownload manifest dulu, lalu layer yang belum ada di cache. Layer sharing membuat pull inkremental dan storage efisien.
- Image scanning adalah gate wajib di production pipeline. Trivy, Snyk, dan Docker Scout mendeteksi CVE di package. Supply chain security memerlukan pertahanan berlapis: pin base image ke digest, sign image (Cosign), scan setiap tahap, dan allowlist image di K8s admission controller.
- Tag strategy yang aman: gunakan semantic version, commit SHA, atau digest. JANGAN pakai
latestdi production. Pisahkan registry per environment, aktifkan image scanning, dan atur retention policy untuk mencegah registry bengkak.- Docker Registry 2.x adalah pilihan minimal untuk self-hosted. Harbor adalah pilihan enterprise dengan UI, RBAC, scanning, dan replication. Pilih berdasarkan kebutuhan kontrol, compliance, dan operasional overhead.
- Image signing (Cosign, Notary) dan admission controller (OPA, Kyverno) di K8s memberikan pertahanan terakhir: hanya image yang signed dan dari registry yang diizinkan yang bisa di-deploy.