คู่มือ DigitalOcean Container Registry 2026 — เก็บ Docker Image
A practical guide to DigitalOcean Container Registry covering pricing tiers, pushing and pulling images with doctl, and integrating with Kubernetes and App Platform.
DigitalOcean Container Registry เป็นบริการเก็บ Docker image ส่วนตัวที่ DigitalOcean ดูแล infrastructure ให้ทั้งหมด ใช้งานร่วมกับ Docker CLI มาตรฐานและเชื่อมต่อกับ DigitalOcean Kubernetes และ App Platform ได้โดยตรง คู่มือนี้พาไล่ตั้งแต่แผนราคา วิธี push/pull image ด้วย doctl ไปจนถึงการดูแลรักษา Registry ระยะยาวด้วยคำสั่งจริงที่ใช้งานได้ทันที
สารบัญ
Container Registry คืออะไร
DigitalOcean Container Registry (DOCR) คือบริการเก็บ Docker image ส่วนตัวที่ DigitalOcean ดูแลให้ทั้งหมด ไม่ต้องตั้งเซิร์ฟเวอร์ Registry เอง ไม่ต้องดูแล storage หรือ patch ระบบรักษาความปลอดภัยด้วยตัวเอง ตัว Registry รองรับมาตรฐาน OCI (Open Container Initiative) เต็มรูปแบบ จึงใช้งานร่วมกับเครื่องมือ Docker, Buildx, Podman หรือเครื่องมือ CI/CD ทั่วไปที่พูดโปรโตคอล Docker Registry API v2 ได้โดยไม่ต้องปรับ workflow เดิมมากนัก สำหรับทีมพัฒนาที่ deploy แอปด้วย container ไม่ว่าจะขึ้น Droplet เอง, DigitalOcean Kubernetes (DOKS) หรือ App Platform, Container Registry เป็นจุดกลางเก็บ image ที่ build เสร็จแล้วก่อนนำไป deploy แทนที่จะใช้ Docker Hub public repo ที่ image จะเปิดให้ใครก็เห็นได้ (เว้นแต่จ่ายแผน private) หรือแทนที่จะรัน Registry เองบน Droplet ซึ่งต้องดูแล SSL, disk space และ backup เอง รูปแบบ URL ของ image ใน DOCR คือ registry.digitalocean.com/<ชื่อ registry>/<ชื่อ image>:<tag> เช่น registry.digitalocean.com/my-registry/my-app:v1.2 บัญชี DigitalOcean หนึ่งบัญชีสร้าง Registry ได้ 1 ชุด (namespace เดียว) แต่ภายในสร้างได้หลาย repository ตามจำนวนที่แผนราคาอนุญาต จุดเด่นที่ทำให้ DOCR ต่างจากการรัน Registry เองคือการเชื่อมต่อกับบริการอื่นของ DigitalOcean แบบไม่ต้องตั้งค่า credential เพิ่มเอง DOKS ดึง image จาก DOCR ได้โดยไม่ต้องสร้าง imagePullSecrets ด้วยมือ และ App Platform ใช้ DOCR เป็น image source สำหรับ auto-deploy เมื่อมี image tag ใหม่ถูก push เข้ามาได้ทันที ข้อจำกัดที่ควรรู้ก่อนใช้งานจริงคือ Container Registry ไม่ได้เปิดให้บริการในทุก region ปัจจุบันไม่มีที่ Richmond (ric1) และ Kansas City (mkc1) ต่างจาก Droplet, Kubernetes, Load Balancer และ VPC ที่เปิดครบทั้ง 15 datacenter ดังนั้นก่อนวางแผนสถาปัตยกรรมที่ผูก Registry เข้ากับ cluster หรือ Droplet ใน region เหล่านี้ ควรตรวจสอบ region ที่รองรับก่อนเสมอ
DigitalOcean Container Registry (DOCR) is a private Docker image storage service fully managed by DigitalOcean. You don't need to set up your own Registry server, manage storage, or patch security systems yourself. The Registry fully supports the OCI (Open Container Initiative) standard, so it works seamlessly with Docker, Buildx, Podman, or any CI/CD tool that speaks Docker Registry API v2 without requiring major workflow changes. For development teams deploying apps via containers—whether on Droplets, DigitalOcean Kubernetes (DOKS), or App Platform—Container Registry is the central hub for storing finished images before deployment, replacing the need for Docker Hub public repos (which expose your images to everyone unless you pay for private repos) or running your own Registry on a Droplet (which requires you to manage SSL, disk space, and backups yourself). Image URLs in DOCR follow the format registry.digitalocean.com/<registry-name>/<image-name>:<tag>, for example registry.digitalocean.com/my-registry/my-app:v1.2. One DigitalOcean account creates one Registry (a single namespace), but you can create multiple repositories within it depending on your plan's repository limit. What sets DOCR apart from self-hosted Registry is its seamless integration with other DigitalOcean services without requiring manual credential setup. DOKS pulls images from DOCR without needing to create imagePullSecrets by hand, and App Platform uses DOCR as its image source for instant auto-deploy when new image tags are pushed. One important limitation to be aware of: Container Registry is not available in every DigitalOcean region. It currently lacks service in Richmond (ric1) and Kansas City (mkc1), unlike Droplets, Kubernetes, Load Balancers, and VPCs which cover all 15 datacenters. Before architecting a setup that ties Registry to clusters or Droplets in those regions, always check regional availability first.
- Registry ส่วนตัว มาตรฐาน OCI ใช้กับ Docker/Buildx/Podman ได้ตรง
- URL รูปแบบ registry.digitalocean.com/
/ : - เชื่อมกับ DOKS และ App Platform โดยไม่ต้องตั้ง credential เพิ่มเอง
- 1 บัญชี = 1 Registry namespace แต่สร้างได้หลาย repository
แผนราคา Starter/Basic/Professional
ที่พบบ่อยในทางปฏิบัติ — digitalOcean Container Registry แบ่งเป็น 3 แผนตามขนาดการใช้งาน คือ Starter, Basic และ Professional ความแตกต่างหลักอยู่ที่จำนวน repository ที่สร้างได้ พื้นที่ storage ที่รวมมาในราคา และค่าใช้จ่ายส่วนเกินเมื่อใช้พื้นที่เกินโควตา (ข้อมูล ณ กรกฎาคม 2026 — ควรตรวจสอบราคาล่าสุดที่เว็บผู้ให้บริการก่อนตัดสินใจ) แผน Starter ราคา $0 ต่อเดือน ให้สร้างได้ 1 repository และพื้นที่เก็บข้อมูลรวม 500 MiB เหมาะสำหรับทดลองใช้งาน โปรเจกต์ส่วนตัวขนาดเล็ก หรือทีมที่มี image เดียวไม่ซับซ้อน แผนนี้ไม่มีการคิดค่าใช้จ่ายส่วนเกิน (overage) เพราะเป็นแผนฟรีที่จำกัดการใช้งานไว้ตายตัว แผน Basic ราคา $5 ต่อเดือน ให้สร้างได้สูงสุด 5 repository พื้นที่เก็บข้อมูลรวม 5 GiB หากใช้พื้นที่เกินโควตาจะถูกคิดเพิ่ม $0.02 ต่อ GiB เหมาะกับทีมขนาดเล็กถึงกลางที่มีหลาย service หรือหลาย microservice ที่ต้องแยก image กัน แผน Professional ราคา $20 ต่อเดือน ให้สร้าง repository ได้ไม่จำกัดจำนวน พื้นที่เก็บข้อมูลรวม 100 GiB และคิดค่าใช้จ่ายส่วนเกินในอัตราเดียวกันคือ $0.02 ต่อ GiB เหมาะกับทีมที่มี image จำนวนมาก เก็บหลาย tag ต่อ image เพื่อ rollback ย้อนหลัง หรือใช้งานร่วมกับ CI/CD ที่ build image บ่อยจนสะสมพื้นที่เร็ว การเลือกแผนควรพิจารณาจากพฤติกรรมจริงของทีม ไม่ใช่แค่จำนวน service ที่มี เพราะ image แต่ละ layer จะถูกเก็บสะสมทุกครั้งที่ push tag ใหม่ ถ้าไม่ตั้ง garbage collection ลบ image เก่าที่ไม่ใช้แล้ว พื้นที่จะเต็มโควตาเร็วกว่าที่คาด การสร้าง Registry พร้อมระบุแผนทำผ่านคำสั่ง doctl registry create my-registry --subscription-tier basic --region sgp1 และตรวจสอบแผนปัจจุบันรวมถึงปริมาณ storage ที่ใช้ไปแล้วด้วยคำสั่ง doctl registry get ซึ่งจะแสดงชื่อ Registry, endpoint, แผนที่ใช้อยู่ และปริมาณ storage เทียบกับโควตา การอัปเกรดแผนทำได้ทุกเมื่อผ่าน doctl registry update-subscription --subscription-tier professional โดยไม่ต้องสร้าง Registry ใหม่หรือย้าย image เดิม
- Starter: ฟรี, 1 repository, storage 500 MiB, ไม่มี overage
- Basic: $5/เดือน, 5 repository, storage 5 GiB, overage $0.02/GiB
- Professional: $20/เดือน, repository ไม่จำกัด, storage 100 GiB, overage $0.02/GiB
- อัปเกรดแผนได้ทุกเมื่อด้วย doctl registry update-subscription โดยไม่ต้องย้าย image
Push/Pull Docker image ด้วย doctl
การใช้งาน Container Registry เริ่มจากติดตั้ง doctl ซึ่งเป็น CLI อย่างเป็นทางการของ DigitalOcean (github.com/digitalocean/doctl) ติดตั้งผ่าน Homebrew บน macOS ด้วย brew install doctl ผ่าน snap บน Linux ด้วย sudo snap install doctl หรือดาวน์โหลด binary จากหน้า GitHub releases โดยตรงก็ได้ หลังติดตั้งเสร็จต้อง authenticate ด้วย Personal Access Token ที่สร้างจากหน้า cloud.digitalocean.com/account/api/tokens ผ่านคำสั่ง doctl auth init แล้ววาง token ตามที่ระบบถาม เมื่อ auth เรียบร้อยแล้ว ให้ login เข้า Registry ด้วยคำสั่ง doctl registry login คำสั่งนี้จะไปเรียก Docker credential helper ให้อัตโนมัติ ทำให้ Docker CLI ที่เครื่องสามารถ push/pull กับ registry.digitalocean.com ได้โดยไม่ต้อง docker login แยกต่างหาก และไม่ต้องจัดการ password เอง (token จะหมดอายุตามรอบและต้อง login ใหม่เป็นระยะ) ขั้นตอน push image เริ่มจาก build image ตามปกติด้วย docker build -t my-app . จากนั้น tag image ให้ชี้ไปที่ Registry ด้วย docker tag my-app registry.digitalocean.com/my-registry/my-app:v1 แล้วค่อย push ด้วย docker push registry.digitalocean.com/my-registry/my-app:v1 เวลา deploy ที่ปลายทางไม่ว่าจะเป็น Droplet, Kubernetes หรือ App Platform ก็ pull image กลับมาด้วย docker pull registry.digitalocean.com/my-registry/my-app:v1 ด้าน doctl เองก็มีคำสั่งจัดการ repository และ tag โดยตรงโดยไม่ต้องพึ่ง Docker CLI เสมอไป เช่น doctl registry repository list ดู repository ทั้งหมดใน Registry, doctl registry repository list-tags my-app ดู tag ทั้งหมดของ repository นั้นพร้อมขนาดไฟล์และวันที่ push และ doctl registry repository delete-tag my-app v1 สำหรับลบ tag ที่ไม่ใช้แล้วออกก่อนรัน garbage collection เพื่อคืนพื้นที่ storage สำหรับทีมที่ใช้ CI/CD pipeline เช่น GitHub Actions สามารถใส่ขั้นตอน doctl registry login และ docker push ไว้ใน workflow YAML โดยเก็บ Personal Access Token เป็น GitHub Secret แล้วเรียกใช้ตอน build เสร็จ ทำให้ image ใหม่ถูก push เข้า Registry อัตโนมัติทุกครั้งที่ merge code เข้า branch หลัก
- ติดตั้ง doctl: brew (macOS) / snap (Linux) / binary จาก GitHub releases
- doctl auth init ผูก Personal Access Token ก่อนใช้งานทุกครั้ง
- doctl registry login ตั้งค่า Docker credential helper ให้อัตโนมัติ
เชื่อมกับ DigitalOcean Kubernetes
DigitalOcean Kubernetes (DOKS) เชื่อมกับ Container Registry ได้แบบ native โดยไม่ต้องสร้าง Kubernetes Secret สำหรับดึง image ด้วยมือ ซึ่งเป็นขั้นตอนที่ปกติต้องทำเวลาใช้ private registry เจ้าอื่น ปกติแล้วเวลา cluster ต้อง pull image จาก private registry จะต้องสร้าง imagePullSecrets ที่เก็บ credential แล้วอ้างอิงใน pod spec ทุกตัว แต่ DOCR ผูกสิทธิ์เข้ากับ cluster ได้ในคำสั่งเดียว การเชื่อมทำผ่าน doctl kubernetes cluster registry add my-cluster คำสั่งนี้จะสร้างและกระจาย Secret ที่จำเป็นเข้าไปใน namespace ของ cluster ให้อัตโนมัติ ทำให้ pod ที่ต้องการ pull image จาก registry.digitalocean.com สามารถทำได้ทันทีโดยผู้ดูแลระบบไม่ต้อง base64-encode credential เองหรือรัน kubectl create secret docker-registry ด้วยมือ ถ้าต้องการยกเลิกการเชื่อมก็ทำผ่าน doctl kubernetes cluster registry remove my-cluster หลังเชื่อมเรียบร้อย การอ้างอิง image ใน Deployment manifest ทำเหมือนใช้ registry ทั่วไป เช่น กำหนด image: registry.digitalocean.com/my-registry/my-app:v1 ใน container spec โดยไม่ต้องระบุ imagePullSecrets เพิ่มเติมในแต่ละ pod เพราะ cluster ผูกสิทธิ์ไว้ที่ระดับ service account เริ่มต้นแล้ว ในแง่ต้นทุน DOKS เองไม่คิดค่า control plane (ฟรี) ค่าใช้จ่ายเริ่มที่ node pool ซึ่งใช้ราคา Droplet ปกติ เริ่มต้นที่ $12 ต่อเดือนต่อ node ส่วน Container Registry คิดแยกตามแผนที่เลือกไว้ (Starter/Basic/Professional) การเชื่อม Registry เข้ากับ cluster ไม่มีค่าใช้จ่ายเพิ่มเติมนอกเหนือจากสองส่วนนี้ ข้อควรระวังคือ Registry และ Kubernetes cluster ไม่จำเป็นต้องอยู่ region เดียวกันเพื่อให้เชื่อมกันได้ (การเชื่อมทำผ่าน API ไม่ใช่ private network ภายใน region เดียว) แต่การ pull image ข้าม region บ่อยครั้งอาจทำให้ deploy ช้ากว่าที่คาด โดยเฉพาะ image ขนาดใหญ่ ควรพิจารณาตั้ง Registry ให้อยู่ใกล้ region ที่ cluster ทำงานจริงเพื่อลด latency ระหว่าง pull
- doctl kubernetes cluster registry add ผูก Secret ให้ cluster อัตโนมัติ ไม่ต้องสร้าง imagePullSecrets เอง
- ยกเลิกการเชื่อมด้วย doctl kubernetes cluster registry remove
- Deployment manifest อ้าง image ตรงได้เลยหลังเชื่อม cluster แล้ว
- DOKS control plane ฟรี, node pool เริ่ม $12/เดือน, Registry คิดแยกตามแผน
- Registry กับ cluster อยู่คนละ region ได้ แต่ควรอยู่ใกล้กันเพื่อลด latency ตอน pull
เชื่อมกับ App Platform สำหรับ CI/CD
App Platform เป็นบริการ PaaS ของ DigitalOcean ที่รองรับ deploy จาก container image โดยตรง ไม่ใช่แค่จาก source code ใน GitHub/GitLab เท่านั้น เมื่อสร้าง App ใหม่และเลือก image source เป็น DigitalOcean Container Registry ระบบจะให้เลือก repository และ tag ที่ต้องการ deploy ได้จากรายการ Registry ที่มีอยู่ในบัญชีเดียวกันทันที โดยไม่ต้องกรอก credential แยก เพราะ App Platform กับ Registry อยู่ในบัญชีเดียวกันอยู่แล้ว จุดที่มีประโยชน์กับ CI/CD workflow คือ App Platform เปิดตัวเลือก auto-deploy เมื่อมี image tag ใหม่ถูก push เข้า repository ที่ผูกไว้ ทำให้ pipeline ทำงานแบบ CI build image ใหม่ แล้ว push เข้า DOCR ด้วย tag ที่กำหนด (เช่น tag แบบ latest หรือ tag ตาม commit SHA) จากนั้น App Platform ตรวจพบ tag ใหม่แล้ว trigger deploy ให้อัตโนมัติ โดยไม่ต้องเรียก DigitalOcean API แยกต่างหากจาก CI pipeline เพื่อสั่ง deploy เอง การตั้งค่านี้กำหนดได้ทั้งผ่านหน้าเว็บ Control Panel ตอนสร้าง/แก้ไข App หรือกำหนดผ่านไฟล์ app spec (YAML) ที่ระบุ image.registry_type: DOCR, image.repository และ image.tag แล้ว deploy ด้วย doctl apps create --spec app.yaml หรือ doctl apps update <app-id> --spec app.yaml สำหรับ deploy ซ้ำ ด้านต้นทุน App Platform มี free tier สำหรับ static site เท่านั้น (สูงสุด 3 app, transfer 1 GiB ต่อ app) ส่วนการ deploy จาก container image ต้องใช้แผนเสียเงินซึ่งเริ่มต้นที่ระดับ Shared 1vCPU/512MiB RAM/50GiB transfer ราคา $5 ต่อเดือน ไล่ระดับขึ้นไปตามขนาด instance ที่เลือก (DigitalOcean ยกเลิกชื่อแผน Basic/Professional แบบเดิมกลางปี 2026 เปลี่ยนมาให้เลือก container instance size เองโดยตรง) ข้อจำกัดที่ควรรู้คือการอ้างอิง image จาก Registry ต้องอยู่ในบัญชี DigitalOcean เดียวกันเท่านั้น จะดึง image จาก Registry ของบัญชีอื่นหรือ Docker Hub public โดยตรงผ่านกลไก auto-deploy นี้ไม่ได้ ต้อง mirror image เข้า DOCR ของบัญชีตัวเองก่อน
- เลือก DOCR เป็น image source ตอนสร้าง App ได้โดยไม่ต้องกรอก credential แยก
- เปิด auto-deploy เมื่อมี tag ใหม่ถูก push เข้า repository ที่ผูกไว้
- ตั้งค่าผ่าน app spec YAML (image.registry_type: DOCR) แล้ว deploy ด้วย doctl apps create/update
ดูแลรักษา Registry: Garbage Collection และลบ Image เก่า
เมื่อใช้งาน Registry ไปนาน push image ใหม่บ่อยครั้งโดยไม่ลบ tag เก่า พื้นที่ storage จะเต็มโควตาของแผนที่ใช้อยู่เร็วกว่าที่คาด เพราะทุกครั้งที่ push tag ใหม่ layer ของ image (แม้จะซ้ำกับ tag เดิมบางส่วน) จะถูกเก็บไว้จนกว่าจะมีการลบทิ้งจริง DigitalOcean Container Registry มีระบบ garbage collection ให้เรียกใช้เพื่อคืนพื้นที่จาก layer และ manifest ที่ไม่มี tag ใดอ้างอิงถึงแล้ว ขั้นตอนมาตรฐานคือก่อนรัน garbage collection ต้องลบ tag ที่ไม่ต้องการออกก่อน ด้วยคำสั่ง doctl registry repository delete-tag my-app v0.9 หรือจะลบทั้ง repository ด้วย doctl registry repository delete my-old-app --force ก็ได้ถ้าไม่ใช้ repository นั้นแล้ว การลบ tag เพียงอย่างเดียวยังไม่คืนพื้นที่ storage ทันที เพราะ layer ที่อยู่เบื้องหลังยังอยู่ในระบบจนกว่าจะรัน garbage collection การเริ่ม garbage collection ทำผ่าน doctl registry garbage-collection start my-registry ระบบจะสแกนหา manifest และ layer ที่ไม่มี tag อ้างอิงแล้วลบทิ้งจริง ระหว่างที่ garbage collection กำลังทำงาน ไม่ควร push image ใหม่เข้า Registry เดียวกัน เพราะอาจชนกับกระบวนการสแกน ตรวจสถานะว่ากำลังทำงานอยู่หรือไม่ด้วย doctl registry garbage-collection get-active my-registry และดูประวัติการรันครั้งก่อนหน้าด้วย doctl registry garbage-collection list my-registry ทีมที่ push image บ่อยจาก CI/CD ควรวางเป็นกระบวนการประจำ เช่น ตั้ง policy เก็บแค่ N tag ล่าสุดต่อ repository (เช่น 10 tag ล่าสุดสำหรับ rollback) แล้วลบ tag เก่ากว่านั้นด้วยสคริปต์ที่เรียก doctl registry repository list-tags มาเทียบวันที่ ก่อนสั่ง delete-tag เป็นชุด แล้วค่อยรัน garbage collection ตามรอบ เช่น สัปดาห์ละครั้ง วิธีนี้ช่วยให้ไม่ต้องอัปเกรดแผนบ่อยเกินจำเป็นทั้งที่ไม่ได้ใช้พื้นที่จริงมากขึ้น เพียงแต่ไม่เคยลบ image เก่าออกเท่านั้น
- ลบ tag เก่าด้วย doctl registry repository delete-tag ก่อนเสมอ ก่อนรัน garbage collection
- เริ่ม garbage collection ด้วย doctl registry garbage-collection start
- ห้าม push image ใหม่ระหว่าง garbage collection กำลังทำงานอยู่
- ตรวจสถานะด้วย get-active และดูประวัติด้วย list
- ตั้ง policy เก็บเฉพาะ N tag ล่าสุดต่อ repository ช่วยลดพื้นที่สะสมโดยไม่ต้องอัปเกรดแผนบ่อย
ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข
ข้อผิดพลาดที่พบบ่อยที่สุดข้อหนึ่งเมื่อใช้งาน Container Registry ต่อเนื่องคือลืมรัน garbage collection เป็นประจำ เพราะการลบ tag ด้วย doctl registry repository delete-tag เพียงอย่างเดียวไม่ได้คืนพื้นที่ storage ทันที layer ของ image ที่ไม่มี tag อ้างอิงยังค้างอยู่ในระบบจนกว่าจะสั่ง doctl registry garbage-collection start ทีมที่ CI/CD push image ทุกครั้งที่ commit โดยไม่เคยรัน garbage collection เลย มักเจอบิล overage ที่ $0.02 ต่อ GiB ไต่ขึ้นเรื่อยๆ ทั้งที่ image ที่ใช้งานจริงมีไม่กี่ตัว เพราะพื้นที่ที่เหลือเป็น layer เก่าที่ไม่มีใครอ้างอิงแล้วสะสมอยู่เบื้องหลัง ปัญหาที่พบบ่อยรองลงมาคือการตั้ง tag ไม่รัดกุม โดยเฉพาะการใช้ tag latest เป็น tag เดียวใน production แล้ว push ทับซ้ำทุกครั้งที่ deploy ทำให้ไม่สามารถ rollback กลับไป version ก่อนหน้าได้เลย เพราะ tag latest ปัจจุบันชี้ไปที่ image ล่าสุดเสมอ image เวอร์ชันก่อนหน้าแม้จะยังไม่ถูกลบแต่ก็ไม่มี tag ให้เรียกกลับมาใช้ วิธีแก้คือ tag ทุก build ด้วยค่าที่ระบุตัวตนได้ เช่น commit SHA หรือเลข version ควบคู่ไปกับ latest เพื่อให้ rollback ได้เสมอ อีกปัญหาที่พบเฉพาะทีมที่ใช้ CI/CD คือ Personal Access Token ที่ใช้ authenticate กับ doctl หมดอายุโดยไม่รู้ตัว ทำให้ pipeline ที่เคย push image สำเร็จมาตลอดจู่ๆ ก็ fail ที่ขั้นตอน doctl registry login เพราะ token ที่เก็บไว้ใน CI secret หมดอายุหรือถูก revoke จากหน้า cloud.digitalocean.com/account/api/tokens โดยไม่ได้อัปเดต secret ให้ตรงกัน ทีมควรตั้งปฏิทินตรวจสอบอายุ token หรือใช้ token ที่ตั้งค่าไว้เฉพาะบัญชี service ที่ใช้กับ CI/CD เท่านั้น แยกจาก token ส่วนตัวของนักพัฒนาแต่ละคน ข้อผิดพลาดสุดท้ายที่พบได้บ่อยในทีมที่มีหลายโปรเจกต์คือ push image ผิด repository หรือผิดบัญชี โดยเฉพาะเมื่อสลับ context ระหว่างหลาย DigitalOcean team โดยไม่ได้ตรวจสอบก่อนว่า context ปัจจุบันของ doctl ชี้ไปที่บัญชีไหนอยู่ หรือ tag ผิดชื่อ registry ทำให้ image ไปอยู่ผิดที่โดยไม่มี error ชัดเจนตอน push เพราะ Docker CLI จะสร้าง repository ใหม่ให้อัตโนมัติถ้ายังไม่มีอยู่ ซึ่งอาจไปชนกับโควตาจำนวน repository ของแผนที่ใช้อยู่โดยไม่รู้ตัว โดยเฉพาะแผน Basic ที่จำกัดไว้แค่ 5 repository
- ลืมรัน garbage collection ทำให้บิล overage ($0.02/GiB) ไต่ขึ้นทั้งที่ image ใช้งานจริงมีไม่กี่ตัว
- ใช้ tag latest เพียง tag เดียวใน production ทำให้ rollback ย้อนหลังไม่ได้
- Personal Access Token หมดอายุทำให้ doctl registry login fail กลางทาง CI/CD
แนวทางปฏิบัติที่ดีที่สุด (Best Practices)
กลยุทธ์การตั้ง tag ที่ดีเป็นจุดเริ่มต้นสำคัญของการดูแล Container Registry ให้ยั่งยืน แนวทางที่ทีมพัฒนาส่วนใหญ่ใช้คือ tag แบบ semantic versioning ร่วมกับ commit SHA เช่น docker tag my-app registry.digitalocean.com/my-registry/my-app:v1.4.2 ควบคู่กับ docker tag my-app registry.digitalocean.com/my-registry/my-app:$(git rev-parse --short HEAD) เพื่อให้ตามรอยได้ว่า image แต่ละตัวมาจาก commit ไหน tag latest ยังใช้ได้สำหรับ environment ทดสอบ แต่ไม่ควรเป็น tag เดียวที่ใช้ deploy ขึ้น production เพราะ rollback ย้อนหลังจะทำไม่ได้ รูปแบบ CI/CD ที่แนะนำคือ build image ครั้งเดียวแล้ว promote image ตัวเดิมผ่านแต่ละ environment (build once, promote everywhere) แทนที่จะ build ใหม่ทุกครั้งที่ deploy ไป staging แล้ว deploy ไป production วิธีนี้ลดความเสี่ยงที่ image ระหว่าง environment จะต่างกันโดยไม่ตั้งใจ เช่น dependency version เปลี่ยนระหว่าง build สองครั้ง ทำได้โดย push image พร้อม tag ที่ระบุ commit ครั้งเดียว แล้วให้แต่ละ environment ดึง tag เดียวกันนั้นไปใช้ พร้อมกับตั้ง App Platform หรือ DOKS ให้ deploy จาก tag ที่ระบุชัดเจนแทนการอ้างอิง latest เสมอในสาย production การลดขนาด image ช่วยทั้งความเร็วในการ push/pull และลดพื้นที่ storage ที่ใช้ในแต่ละแผน แนวทางพื้นฐานคือใช้ multi-stage build แยกขั้นตอน compile/build ออกจาก image สุดท้ายที่ใช้รัน เช่น build ด้วย image ที่มี toolchain ครบ แล้ว copy เฉพาะ binary หรือไฟล์ที่จำเป็นไปยัง base image ที่เล็กกว่าอย่าง alpine หรือ distroless ร่วมกับตั้งไฟล์ .dockerignore ไม่ให้ copy ไฟล์ที่ไม่จำเป็นอย่าง node_modules เก่า, .git หรือไฟล์ log เข้าไปใน build context ตั้งแต่ต้น image ที่เล็กลงยังทำให้ garbage collection มีงานน้อยลงและ overage ต่ำลงตามไปด้วย สำหรับทีมที่มีสมาชิกหลายคนหรือหลายทีมย่อย ควรจัดการสิทธิ์การเข้าถึง Registry ผ่านระบบ Teams ของ DigitalOcean แทนที่จะแชร์ Personal Access Token เดียวกันทั้งทีม โดยแยก token ตามหน้าที่ เช่น token สำหรับ CI/CD pipeline ให้สิทธิ์เฉพาะที่จำเป็น แยกจาก token ที่นักพัฒนาแต่ละคนใช้จากเครื่องตัวเอง หากมีการเปลี่ยนทีมงานหรือ token รั่วไหล จะ revoke เฉพาะ token ที่เกี่ยวข้องได้โดยไม่กระทบ pipeline หรือสมาชิกคนอื่น และควรตรวจสอบสิทธิ์ระดับ Project ใน DigitalOcean Teams ให้ Registry ผูกอยู่กับ Project ที่ถูกต้องตามสภาพแวดล้อม dev/staging/production ที่แยกกันชัดเจน
- Tag ด้วย semantic version + commit SHA คู่กัน ไม่ใช้ latest เป็น tag เดียวใน production
- Build once, promote everywhere: build image ครั้งเดียวแล้วส่งต่อ tag เดิมข้าม environment
- Multi-stage build + base image เล็ก (alpine/distroless) + .dockerignore ลดขนาด image
- แยก Personal Access Token ตามหน้าที่ (CI/CD vs ส่วนตัว) ผ่านระบบ Teams ของ DigitalOcean
- ผูก Registry กับ Project ที่ถูกต้องตามสภาพแวดล้อม dev/staging/production