- Unregistry là một container image registry gọn nhẹ lưu trữ và phục vụ image trực tiếp từ kho của Docker daemon, đồng thời với lệnh
docker pussh có thể truyền image thẳng tới máy chủ Docker từ xa qua SSH
- Các lựa chọn trước đây gồm Docker Hub/GitHub Container Registry, registry tự host,
docker save | ssh... docker load, hoặc rebuild từ xa, nhưng mỗi cách đều có vấn đề như kho công khai hoặc mất phí, gánh nặng vận hành, phải truyền toàn bộ image, hoặc lãng phí tài nguyên máy chủ
docker pussh myapp:latest user@server tạo SSH tunnel, khởi chạy một container unregistry tạm thời trên máy chủ từ xa, rồi thực hiện docker push qua cổng localhost được forward để chỉ truyền các layer chưa có ở phía từ xa
- Máy chủ từ xa cần có môi trường chạy Docker, quyền thực thi lệnh
docker, và ở lần chạy đầu tiên phải truy cập được ghcr.io/psviderski/unregistry:latest; container unregistry chạy bằng root do cần truy cập /run/containerd/containerd.sock
- Nếu bật containerd image store của Docker thì image đã truyền sẽ dùng được ngay trong Docker và tránh lưu trùng lặp, nhưng các image và container được tạo bằng classic storage driver có thể tạm thời không hiển thị
Vấn đề triển khai mà Unregistry giải quyết
- Unregistry là một container image registry gọn nhẹ để chuyển Docker image sang máy chủ từ xa mà không cần registry bên ngoài
- Lệnh plugin Docker CLI đi kèm là
docker pussh, trong đó chữ s thêm vào là viết tắt của SSH
- Khi chuyển Docker image được build cục bộ lên máy chủ, các lựa chọn phổ biến thường có những hạn chế sau
- Docker Hub / GitHub Container Registry: phải công khai mã nguồn hoặc trả phí cho kho private
- Self-hosted registry: phát sinh một dịch vụ riêng cần bảo trì, bảo mật và chi phí lưu trữ
- Save/Load:
docker save | ssh <remote server> docker load sẽ truyền toàn bộ image dù máy chủ đã có sẵn 90%
- Remote rebuild: tốn thời gian và tài nguyên máy chủ, đồng thời có thể phải debug lỗi build ngay trên production
Cách docker pussh hoạt động
- Cách dùng cơ bản chỉ là một dòng sau
docker pussh myapp:latest user@server
- Lệnh này truyền trực tiếp chỉ các layer còn thiếu qua SSH mà không cần cấu hình registry, đăng ký dịch vụ, kho trung gian hay mở cổng public
- Trình tự hoạt động nội bộ như sau
- Tạo SSH tunnel tới máy chủ từ xa
- Khởi chạy một container unregistry tạm thời trên máy chủ
- Forward một cổng localhost ngẫu nhiên qua tunnel tới cổng của unregistry
- Thực hiện
docker push qua cổng đã forward để chỉ truyền các layer chưa có ở máy từ xa
- Image đã truyền có thể dùng ngay trên Docker daemon từ xa
- Dừng container unregistry và đóng SSH tunnel
- Dự án hướng tới cơ chế truyền đơn giản và hiệu quả, giống
rsync cho Docker image
- Unregistry được tạo ra cho Uncloud, một công cụ gọn nhẹ để triển khai container lên nhiều Docker host, vì cần một cách đơn giản hơn full registry và hiệu quả hơn save/load
Yêu cầu chạy và các giới hạn
- Máy cục bộ cần hỗ trợ Docker CLI plugin, Docker 19.03 trở lên và OpenSSH client
- Máy chủ từ xa phải cài Docker và đang chạy
- Người dùng SSH phải có quyền chạy lệnh
docker
- Người dùng đó phải là
root hoặc là người dùng non-root thuộc nhóm docker
- Xem tài liệu Docker Manage Docker as a non-root user
- Nếu cần
sudo thì phải chạy được sudo docker mà không bị hỏi mật khẩu
- Ở lần chạy
docker pussh đầu tiên, máy chủ từ xa phải kéo được image ghcr.io/psviderski/unregistry:latest từ ghcr.io
- Với máy chủ cần proxy, phải cấu hình theo hướng dẫn Docker Daemon proxy configuration
- Trong môi trường air-gapped hoặc bị hạn chế truy cập
ghcr.io, có thể kiểm tra phiên bản unregistry image cần thiết rồi preload thủ công
- Container unregistry chạy bằng root vì cần truy cập
/run/containerd/containerd.sock để có đủ quyền
Cài đặt và nền tảng hỗ trợ
- Trên macOS/Linux có thể cài
docker-pussh bằng Homebrew
brew install psviderski/tap/docker-pussh
- Sau khi cài bằng Homebrew, để dùng
docker pussh như Docker CLI plugin cần tạo symbolic link ~/.docker/cli-plugins/docker-pussh
- Trên macOS/Linux cũng có cách tải trực tiếp
- Ví dụ phiên bản hiện tại là tải script
docker-pussh của v0.4.3 vào thư mục Docker plugin rồi cấp quyền thực thi
- Cũng có thể tải script mới nhất từ nhánh main
- Debian có thể cài qua kho gói không chính thức unregistry-debian do @dariogriffo tạo và duy trì
- Windows hiện chưa được hỗ trợ, nhưng có thể thử WSL 2 và quy trình cài đặt trên Linux
- Có thể kiểm tra cài đặt bằng lệnh sau
docker pussh --help
Thiết lập containerd image store
Ví dụ sử dụng
- Cách truyền cơ bản chỉ cần chỉ định tên image và đích SSH từ xa
docker pussh myapp:latest user@server.example.com
- Nếu private key chưa được thêm vào SSH agent, có thể chỉ định key bằng
-i
docker pussh myapp:latest ubuntu@192.168.1.100 -i ~/.ssh/id_rsa
- Có thể chỉ định cổng SSH tùy chỉnh bằng cách thêm cổng sau địa chỉ đích
docker pussh myapp:latest user@server:2222
- Có thể chỉ định file SSH config tùy chỉnh bằng
-F
docker pussh myapp:latest prod-server -F ~/.ssh/config.prod
- Để chỉ push một nền tảng cụ thể trong image đa nền tảng, dùng
--platform
docker pussh myapp:latest user@server --platform linux/amd64
- Để dùng một phiên bản unregistry image cụ thể trên host từ xa, đặt biến môi trường
UNREGISTRY_IMAGE
UNREGISTRY_IMAGE=ghcr.io/psviderski/unregistry:A.B.C docker pussh myapp:latest user@server.example.com
Trường hợp sử dụng tiêu biểu
- Khi triển khai lên máy chủ production, có thể push trực tiếp image build cục bộ lên máy chủ và chạy mà không cần registry trung gian
docker build --platform linux/amd64 -t myapp:1.2.3 .
docker pussh myapp:1.2.3 deploy@prod-server
ssh deploy@prod-server docker run -d myapp:1.2.3
- Trong pipeline CI/CD, có thể gửi image trực tiếp tới đích triển khai mà bỏ qua độ phức tạp của registry
- name: Build and deploy
run: |
docker build -t myapp:${{ github.sha }} .
docker pussh myapp:${{ github.sha }} deploy@staging-server
- Trong homelab và môi trường air-gapped, có thể triển khai image trong mạng cô lập không có truy cập Internet tới registry công cộng
Cách dùng nâng cao và các dự án liên quan
- Unregistry cũng có thể dùng như một local registry chạy độc lập
- Mount
/run/containerd/containerd.sock rồi chạy container ghcr.io/psviderski/unregistry
- Sau đó có thể dùng
localhost:5000 như một registry thông thường với docker tag và docker push
- Thiết lập SSH có thể dùng file SSH config chuẩn hoặc truyền file config riêng bằng
-F
- Có các dự án bên thứ ba liên quan
- Phần triển khai có nhắc tới Spegel và Docker Distribution
- Spegel là P2P container image registry đã truyền cảm hứng cho cách triển khai registry dùng containerd image store làm backend
- Docker Distribution là triển khai Docker registry làm nền tảng cho unregistry
1 bình luận
Ý kiến trên Hacker News
Với tư cách là người tạo ra Docker, tôi thích điều này. Có lẽ thiết kế lý tưởng nên là một máy chủ duy nhất không tách biệt Docker engine và registry
Nếu có thể lưu trữ, truyền và chạy container khi cần thì nó đã trở thành một thành phần vững chắc hơn nhiều, đồng thời cũng tránh được hướng đi đáng tiếc là engine và registry lưu image theo những cách không đồng nhất
Tôi cũng cho rằng mọi cụm production nên có kho lưu trữ image phân tán, và việc push image vào kho đó phải là thứ kích hoạt triển khai. Cách làm hiện nay là push lên registry, cấu hình cụm, rồi từng node tự kéo từ registry về thì vừa mong manh vừa kém hiệu quả. Tôi đã cố lập luận cho một thiết kế tốt hơn, nhưng quán tính khi đó đã quá lớn, và cộng đồng Kubernetes thời kỳ đầu lại thù địch với những ý tưởng xuất phát từ Docker
Triển khai bằng cách push vào cụm nghe rất thông minh. Tôi cũng đang nghĩ đến một kho image phân tán kiểu cài unregistry trên mọi node để chúng tự lấy và chia sẻ image với nhau, nhưng cách để push trở thành thứ kích hoạt triển khai thì tôi cần suy nghĩ thêm
Hay đấy. Lệnh
pusshthực sự xứng đáng được công nhận là một cách chơi chữ rất thanh lịch. Dễ nhớ, ý nghĩa hiện ra ngay, và chỉ khác một chữ cái so với lệnh chuẩn cùng họdocker push-over-sshTrong tự động hóa được phát triển theo nhóm,
pusshcó thể trông như lỗi gõ với những người không biết chức năng này, và gây ra sự bối rối không cần thiết. Ngược lại,push-over-sshcho thấy rõ đây là một cái tên có chủ đích. Cứ xem như tùy chọn ngắn và tùy chọn dài vậysthêm vào là chữscủasssh“Cái extra
sđó là gì vậy?”“Lỗi gõ đấy”
Năm 2015 tôi đã ngây thơ gửi một PR[1] để đưa tính năng này vào dòng chính Docker, nhưng nhanh chóng bị hướng sang chuyện hỗ trợ một lĩnh vực khác. Có lẽ việc làm cho registry trở nên không còn cần thiết đã đụng chạm quá mạnh đến mô hình kinh doanh của Docker
[1]: https://github.com/richardcrichardc/docker2docker
Rốt cuộc tôi đoán kế hoạch là chuyển mặc định sang kho image của containerd. Khi cả local lẫn remote đều dùng kho image của containerd, có vẻ sẽ làm được điều ban đầu bạn từng triển khai mà không cần wrapper registry nữa
Đây có vẻ là một ý tưởng hay, rất hợp với những hệ thống đã dùng công cụ triển khai kiểu push như Ansible. Với các công ty không có hỗ trợ 24/7 cho Docker registry, nó cũng có vẻ là một cơ chế triển khai hotfix tốt
Tôi tò mò không biết nó có tích hợp gọn gàng với các công cụ OCI như buildah không, hay là bắt buộc phải có cài đặt Docker đầy đủ ở cả hai đầu. Tôi chưa xem kỹ, nhưng trong kiểu cấu hình này, có vẻ mảnh ghép còn thiếu để skopeo hoạt động là phải bootstrap một mini registry trên máy chủ từ xa
Unregistry tái sử dụng mã Docker registry chính thức ở lớp API, nên nó trông và hoạt động tương tự https://hub.docker.com/_/registry
Ở phía client, có thể dùng các công cụ nói chuyện với OCI registry như skopeo, crane, regclient, BuildKit. Tuy nhiên để dùng chúng, bạn phải tự chạy unregistry trên host từ xa. Lệnh
docker pusshchỉ đơn giản là dùng Docker cục bộ để tự động hóa luồng đóCứ coi nó là một script Bash: https://github.com/psviderski/unregistry/blob/main/docker-pu...
Bạn có thể dễ dàng chỉnh lại theo cách mình muốn
Lẽ ra từ đầu nó phải như thế này mới đúng. Quá tuyệt
Docker registry vẫn có chỗ để dùng, nhưng nhìn chung nó bị thiết kế quá mức và đứng ở phía đối lập với tinh thần hacker
Tôi mất khoảng 20 phút để thiết lập workflow
.yamlbuild và push image lên registry ghcr.io riêng tư, và khoảng 5 phút để cho phép máy chủ kéo image từ đó. Cấu hình này khá thực dụngTôi đang nhìn thấy một pipeline kiểu: build image trong GitLab rồi push lên Artifactory, sau đó triển khai được kích hoạt để kéo từ Artifactory và push lại sang AWS ECR, rồi cập nhật template triển khai của EKS để kéo từ ECR xuống node và khởi chạy container Pod
Tôi cần điều này trong đời mình
Nhờ xem cái này mà tôi biết đến uncloud. Tôi đang tìm một thứ giống dokku nhưng mạnh hơn một chút để dựng server cho side project, và nó đúng kiểu như vậy
Tính năng stack cũng rất hay, về cơ bản chính là Docker Compose. Trên một EC2 instance, Portainer Agent chạy Caddy bên trong container, còn Caddy đóng vai trò load balancer và reverse proxy
Khá lạ khi Docker ngay từ đầu lại không hoạt động theo cách này. Trông rất hay
Việc lưu archive là kiểu
docker save -o may-app.tar my-app:latest, còn load là kiểudocker load -i /path/to/my-app.tarNếu dùng công cụ như Ansible thì có thể dễ dàng đạt được điều mà “Unregistry” tự động hóa. Theo kho lưu trữ GitHub, nhược điểm của cách save/load là truyền toàn bộ image qua mạng, và điều đó thực sự có thể thành vấn đề. Có vẻ việc quản lý trực tiếp image thay vì file archive cũng tiện hơn
Dự án và cách tiếp cận rất gọn gàng. Tôi đã quá chán các registry đắt đỏ nên cuối cùng tự host Zot[1], nhưng với một số trường hợp thì cách này có vẻ dễ hơn nhiều
Tôi tự hỏi có ai khác cũng thấy sẽ rất tuyệt nếu có một dịch vụ private registry dễ cấu hình, giá rẻ và tính phí theo mức sử dụng hay không
[1]: https://zotregistry.dev
Ý tưởng ổn đấy. Tuy vậy, có thể có nhược điểm là việc triển khai bị gắn chặt với dịch vụ. Ví dụ, tôi không rõ sẽ xử lý scale-out hay triển khai red/green thế nào, và có vẻ phía làm việc đó sẽ phải biết về push
Chỉnh sửa: hóa ra thứ làm việc đó là uncloud. Tôi vừa mới nhận ra
Dù vậy thì đây vẫn là một đánh đổi. Nếu quy mô nhỏ, dùng một Hetzner VM và hài lòng với sự đơn giản, đồng thời cũng không ngại build image ở local, thì đây là một lựa chọn tuyệt vời