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 tag latest di production. Tag latest adalah default tag yang otomatis di-resolve ke digest TERBARU. Jika kamu re-push image dengan tag latest, container yang sedang jalan (atau deployment script yang pakai latest) 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 sha256 dari 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.04 di 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 docker CLI.
  • 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:

  1. Resolve image & layer — daemon membaca image ID, lalu daftar layer yang membentuknya.
  2. Cek manifest existingHEAD ke registry untuk tahu apakah manifest sudah ada. Mounting trick: untuk layer yang sudah ada, daemon bisa POST .../?mount=<digest> untuk “mount” layer dari blob lain tanpa upload ulang.
  3. Upload layer satu per satu — layer yang tidak ada di registry di-upload via chunked upload (PATCH untuk tiap chunk).
  4. 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:GetDownloadUrlForLayer dll.
  • 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]
  1. Pin base image ke digestFROM ubuntu@sha256:abc... bukan FROM ubuntu:22.04. Ini mencegah tag mutable.
  2. Verifikasi image signature — gunakan Cosign (bagian dari Sigstore) atau Docker Content Trust (DCT) untuk sign image.
  3. Scan di setiap tahap — jangan cuma scan image final, scan juga base image dan intermediate layer.
  4. Gunakan trusted base imagedocker.io/library/* (official) atau image dari vendor terpercaya.
  5. 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 latest di 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.

← Sebelumnya: Container   Berikutnya: How It Works →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact