Unregistry – ส่ง “docker push” ไปยังเซิร์ฟเวอร์โดยตรงโดยไม่ต้องมี registry
(github.com/psviderski)- Unregistry เป็นเครื่องมือโอเพนซอร์สที่สามารถส่ง Docker image ไปยัง เซิร์ฟเวอร์ระยะไกลโดยตรง ได้โดยไม่ต้องพึ่ง external registry
- ด้วยคำสั่ง
docker pusshสามารถส่ง image ไปยังเซิร์ฟเวอร์ปลายทางผ่าน SSH ได้อย่าง มีประสิทธิภาพ และจะข้ามเลเยอร์ที่มีอยู่แล้ว - ช่วยแก้ปัญหา ความซับซ้อนและความไม่มีประสิทธิภาพ ของ Docker Hub แบบดั้งเดิม, self-hosted registry และวิธี save/load
- เหมาะอย่างยิ่งสำหรับ การ deploy ไปยัง production, CI/CD และสภาพแวดล้อมแบบปิด ที่ต้องการย้าย image อย่างรวดเร็วและปลอดภัย
- การติดตั้ง การใช้งาน และข้อกำหนด เรียบง่ายมาก และไม่จำเป็นต้องรันบริการเพิ่มหรือเปิดพอร์ต
แนะนำ Unregistry และจุดเด่นหลัก
- Unregistry คือ image registry แบบเบา ที่เก็บและให้บริการ image โดยตรงจาก storage ของ Docker daemon
- เมื่อใช้คำสั่ง
docker pusshจะสามารถย้าย image ไปยัง Docker server ระยะไกลผ่าน SSH ได้ทันทีโดยไม่ต้องมี external registry - ระหว่างการส่ง ระบบจะตัดเลเยอร์ที่มีอยู่บนเซิร์ฟเวอร์แล้วออกไป ทำให้ ส่งเฉพาะส่วนที่จำเป็นได้อย่างรวดเร็ว
ปัญหาของการ deploy Docker image แบบเดิม
- เมื่อต้อง build image บนเครื่อง local แล้วส่งไปยังเซิร์ฟเวอร์ ตัวเลือกที่มีมักเป็นดังนี้
- Docker Hub/GitHub Container Registry: อาจต้องเปิดเผยโค้ดต่อภายนอก หรือมีค่าใช้จ่ายเมื่อใช้ private repository
- self-hosted registry: เพิ่มภาระในการดูแลบริการแยกต่างหาก รวมถึงเรื่องความปลอดภัยและการจัดการ storage
- Save/Load: ต้องส่งทั้ง image ทุกครั้ง จึงไม่มีประสิทธิภาพ
- rebuild บนเซิร์ฟเวอร์โดยตรง: สิ้นเปลืองเวลาและทรัพยากรของเซิร์ฟเวอร์ รวมถึงทำให้การดีบักยุ่งยาก
โซลูชันของ Unregistry
-
ใช้เพียงคำสั่ง
docker pussh myapp:latest user@serverครั้งเดียวก็สามารถ ส่งตรงได้โดยไม่ต้องมีที่เก็บกลาง -
ไม่ต้องตั้งค่า registry เพิ่มเติม ไม่ต้องเปิดพอร์ต ไม่ต้องเตรียม storage และไม่ต้องสมัครบริการใดๆ
-
กระบวนการส่งมีดังนี้
- เชื่อมต่อ SSH tunnel ไปยังเซิร์ฟเวอร์ระยะไกล
- รันคอนเทนเนอร์ unregistry ชั่วคราว
- เชื่อมพอร์ต local แบบสุ่มเข้ากับพอร์ตของ unregistry
- ใช้ docker push เพื่อส่งเฉพาะเลเยอร์ที่ยังไม่มีอยู่ (และใช้งานได้ทันที)
- ปิดคอนเทนเนอร์ unregistry และ SSH tunnel
-
เป็นแนวทางที่ เรียบง่ายและมีประสิทธิภาพ คล้าย
rsync -
โปรเจกต์นี้ถูกพัฒนาขึ้นจาก Uncloud เพื่อทำให้ความซับซ้อนของการ deploy คอนเทนเนอร์ไปยังหลาย Docker host ง่ายขึ้น
ตัวอย่างการใช้งาน
ส่ง image ไปยังสภาพแวดล้อมสำหรับ deploy โดยตรง
- build จาก local แล้ว push ไปยัง production server ได้โดยตรง
docker build --platform linux/amd64 -t myapp:1.2.3 .docker pussh myapp:1.2.3 deploy@prod-serverssh deploy@prod-server docker run -d myapp:1.2.3
CI/CD pipeline
- รองรับการ build และ deploy โดยไม่เพิ่มความซับซ้อนจาก registry
- สามารถใช้การส่งโดยตรงใน GitHub Action YAML เป็นต้น
homelab และสภาพแวดล้อมแบบปิดที่ไม่มีอินเทอร์เน็ต
- ส่ง image ไปยัง เครือข่ายแยก ได้อย่างปลอดภัยโดยไม่ต้องเผยแพร่ image สู่อินเทอร์เน็ต
วิธีใช้งาน
- บัญชีผู้ใช้ SSH ต้องสามารถใช้คำสั่ง docker บนเครื่องปลายทางได้
- รองรับตัวเลือกเพิ่มเติม เช่น SSH private key หรือพอร์ต SSH แบบกำหนดเอง
- รองรับการส่ง multi-platform image ด้วยเช่นกัน (ในกรณีที่ใช้ containerd)
ข้อกำหนด
สภาพแวดล้อม local
- Docker CLI (รองรับ plugin, 19.03+)
- OpenSSH client
เซิร์ฟเวอร์ปลายทาง
- ต้องติดตั้งและรัน Docker อยู่
- ผู้ใช้ ssh ต้องมีสิทธิ์ใช้งาน docker และหากจำเป็นต้องสามารถรัน
sudo dockerแบบไม่ต้องใช้รหัสผ่านได้ - หากใช้ containerd image store จะช่วยเพิ่มประสิทธิภาพ
- ต้องเพิ่มการตั้งค่าต่อไปนี้ใน
/etc/docker/daemon.jsonและรีสตาร์ต docker{ "features": { "containerd-snapshotter": true } }
- ต้องเพิ่มการตั้งค่าต่อไปนี้ใน
การใช้งานขั้นสูง
ใช้เป็น local standalone registry
- สามารถใช้งาน unregistry เป็น local registry ได้อย่างง่ายดายโดยไม่ต้องมีคอมโพเนนต์เพิ่มเติม
- สามารถ deploy และ push ได้ผ่านคำสั่ง Docker
การใช้ตัวเลือก SSH แบบกำหนดเอง
- สามารถใช้ไฟล์ SSH config เพื่อกำหนดรายละเอียดเพิ่มเติมให้ตรงตามเงื่อนไข เช่น วิธีการยืนยันตัวตนหรือพอร์ต
การมีส่วนร่วมและคอมมูนิตี้
- หากพบบั๊ก สามารถเปิด GitHub issue ได้
- สามารถพูดคุยเรื่องฟีเจอร์, roadmap และรายละเอียดการพัฒนาได้ในชุมชน Discord ของ Uncloud
โอเพนซอร์สที่เป็นแรงบันดาลใจและใช้อ้างอิง
- Spegel: ได้แรงบันดาลใจจากการทำ image registry แบบ P2P บน containerd
- Docker Distribution: ใช้เป็นฐานสำหรับการทำ registry จริง
สรุป
- Unregistry เป็นเครื่องมือที่ช่วยย้าย Docker image ไปยังเซิร์ฟเวอร์ระยะไกลได้โดยตรงอย่างง่ายและรวดเร็ว โดย ตัดภาระการสร้างและดูแล registry ออกไป
- มีจุดเด่นอย่างมากในหลายสถานการณ์ เช่น การ deploy production, CI/CD และเครือข่ายแบบปิด
- เหมาะมากสำหรับกรณีที่ต้องการย้ายเฉพาะ image ระหว่างเซิร์ฟเวอร์กับผู้ดูแลระบบแบบเรียบง่ายโดยไม่ต้องมีขั้นตอนเพิ่มเติม
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
จากมุมมองเรื่องลักษณะของเซิร์ฟเวอร์ ขอบเขตความปลอดภัย และการ hardening ผมไม่อยากแนะนำให้ใช้ Homebrew บน Linux การติดตั้งสำหรับ Linux ดูเหมือนถูกเพิ่มเข้ามาทีหลัง และพฤติกรรมก็ให้ความรู้สึกเหมือนนกพิราบบนกระดานหมากรุกมากกว่าจะเป็น package manager
คิดว่าเป็นไอเดียเจ๋งที่เข้ากันได้ดีกับที่ที่ใช้ tooling แบบ push deployment อย่าง Ansible อยู่แล้วในระบบ และยังน่าจะเหมาะเป็นเทคนิคการปล่อย hotfix สำหรับองค์กรที่ไม่มี Docker registry ให้ใช้งานตลอด 24 ชั่วโมงด้วย สงสัยว่าเชื่อมกับ OCI tooling (เช่น buildah) ได้เนียนแค่ไหน หรือจำเป็นต้องติดตั้ง Docker เต็มชุดทั้งสองฝั่ง ตอนนี้ยังไม่ได้ลงลึกจริงจัง แต่ตั้งใจจะลองทำอะไรเกี่ยวกับเรื่องนี้อยู่ และรู้สึกว่า skopeo ยังขาดความสามารถในการ bootstrap registry ของตัวเองบนเซิร์ฟเวอร์ปลายทางเพื่อให้ทำงานในสภาพแวดล้อมแบบนี้ได้
ฝั่งเซิร์ฟเวอร์ปลายทางต้องมี containerd (Docker และ Kubernetes ก็ใช้ containerd เช่นกัน) ส่วนฝั่งไคลเอนต์จะเป็นอะไรก็ได้ที่เข้าใจ registry API (OCI Distribution spec: https://github.com/opencontainers/distribution-spec) โดย Unregistry นำโค้ด Docker registry อย่างเป็นทางการมาใช้ซ้ำในชั้น API เลยให้ความรู้สึกคล้าย registry ของ Docker Hub สามารถใช้ OCI registry ต่างๆ ได้ เช่น skopeo, crane, regclient, BuildKit แต่ถ้าจะใช้พวกนี้ต้องรัน unregistry โดยตรงบนโฮสต์ปลายทาง คำสั่ง
docker pusshทำหน้าที่ใช้ Docker ในเครื่องเพื่อทำให้ flow ทั้งหมดนี้เป็นอัตโนมัติ เป็น bash script จึงแนะนำให้ลองดู https://github.com/psviderski/unregistry/blob/main/docker-pussh, และแก้ไขตามต้องการได้ง่ายต้องมี docker daemon ทั้งสองฝั่ง วิธีนี้ใช้แนวทางที่ชาญฉลาดคือแชร์ layer ผ่าน ssh ระหว่างสอง daemon
คิดว่าคำสั่ง
pusshจำง่าย อธิบายตัวเองได้ดี และเป็นการเล่นคำที่ดีมากเพราะต่างจากคำสั่งมาตรฐานเดิมแค่ตัวอักษรเดียว"pussh" ก็ดี แต่ในงาน automation น่าจะมี alias ที่ชัดกว่านี้อย่าง "docker push-over-ssh" จะเหมาะกว่า คนที่เห็น "pussh" ครั้งแรกอาจคิดว่าเป็นพิมพ์ผิดและเกิดความสับสนโดยไม่จำเป็น ถ้ารองรับทั้งเวอร์ชันสั้นและเวอร์ชันแบบเต็มก็น่าจะดี
มีมุกอธิบายว่าที่เพิ่ม 's' มาอีกตัวเพราะอยากสื่อถึง 'sssh' บางคนก็บอกว่าแค่พิมพ์ผิดเฉยๆ
ชื่อ 'pussh' อาจมีโอกาสชนกับคำสั่งอื่นได้
รู้สึกว่าฟีเจอร์แบบนี้ควรมีมาตั้งนานแล้วและเจ๋งมาก Docker registry มีคุณค่าในตัวเอง แต่โดยรวมมันซับซ้อนเกินไปและห่างไกลจากความเป็นแฮ็กเกอร์ไปมาก
ตัวโปรเจกต์และแนวทางน่าประทับใจ เคยเบื่อ registry ราคาแพงจนลอง self-host ของอย่าง Zot(https://zotregistry.dev) แต่รู้สึกว่าวิธีนี้ดูง่ายกว่ามากสำหรับบาง use case อยากให้มี private registry service ที่ใช้ง่าย ราคาถูก และคิดเงินตามการใช้งานแพร่หลายกว่านี้
คิดว่า Docker ควรทำงานแบบนี้มาตั้งแต่แรก เป็นไอเดียที่เจ๋งมาก
docker save -o my-app.tar my-app:latestแล้วโหลดด้วยdocker load -i /path/to/my-app.tarถ้าเอาไปใช้คู่กับเครื่องมืออัตโนมัติอย่าง ansible ก็ทำสิ่งที่ Unregistry ทำให้อัตโนมัติได้ด้วยตัวเอง อย่างไรก็ตามใน GitHub repo ก็ระบุไว้ว่าวิธี save/load ต้องส่ง image ทั้งก้อนทุกครั้ง และการจัดการ image ก็สะดวกน้อยกว่าการจัดการผ่าน archive fileยินดีกับการหวนกลับไปสู่ self-hosting ที่อาศัยเครื่องมือแนวนี้และ SSH tooling และคิดว่างานชิ้นนี้ทำออกมาได้ดี มีแผนจะลองใช้เอง
เครื่องมือนี้ทำให้เพิ่งรู้จักโปรเจกต์ชื่อ uncloud และดูน่าสนใจเพราะเหมือนเป็นโซลูชันสำหรับ deploy เซิร์ฟเวอร์แบบ dokku ที่ทรงพลังยิ่งกว่าและตรงกับสิ่งที่ผมอยากได้
เห็นด้วยว่า uncloud น่าจะเหมาะกับคุณมาก ถ้ามีคำถามยินดีให้มาถามใน Discord
ขอแนะนำบริการที่ใช้แนวทางคล้ายกันคือ https://skateco.github.io/
แนะนำ Portainer ตอนนี้ใช้งาน Portainer Community Edition กับ Portainer Agent อยู่ได้ดีบน AWS EC2 สองเครื่อง โดยฟีเจอร์ stack (อิงกับ docker compose) คือจุดเด่นสำคัญ บน EC2 เครื่องหนึ่ง portainer agent รัน Caddy เป็นคอนเทนเนอร์เพื่อทำหน้าที่ load balancer และ reverse proxy
เป็นไอเดียที่แปลกใหม่ แต่ก็ผูกเข้ากับการ deploy บริการค่อนข้างแน่น ทำให้การ deploy และการขยายระบบ เช่น blue/green deployment ต้องมี logic เพิ่มเติมที่รับรู้เรื่อง "push" พอลองคิดดูแล้วก็พบว่านี่คือโครงสร้างที่ uncloud นำไปทำไว้แล้ว แต่สุดท้ายก็เป็นเรื่อง trade-off และถ้าคุณให้ความสำคัญกับความเรียบง่ายบน Hetzner VM เครื่องเดียว การ build image จากในเครื่องแล้วส่งแบบนี้ก็อาจเป็นตัวเลือกที่น่าพอใจมาก