Nhiệm vụ: Thiết lập docker registry cục bộ trên máy chủ

Thiết lập docker registry cục bộ trên máy chủ

10.06.2026

Việc build app-container yêu cầu RAM từ 3GB trở lên và nhìn chung mất khác nhiều thời gian để hoàn tất.

Cần thiết lập sao cho image có thể được build cục bộ trên máy tính và push lên registry.

Ворклоги

Khởi chạy registry của riêng bạn trên máy chủ

Điều này cho phép chúng ta có một kho chứa hình ảnh (repository) cục bộ trên máy chủ để có thể đẩy (push) các image của mình lên đó, từ đó tạo và chạy các container cuối cùng.


docker run -d \
  -p 127.0.0.1:5000:5000 \
  --restart always \
  --name registry \
  registry:2

127.0.0.1:5000:5000 là để nó chỉ lắng nghe (listen) các kết nối cục bộ trên cổng 5000, nếu không, bất kể tường lửa, cổng vẫn sẽ mở ra bên ngoài và chúng ta hoàn toàn không muốn mất thời gian bận tâm về cài đặt quyền truy cập. Ở đây chúng ta sẽ sử dụng reverse proxy, vì vậy quyền truy cập sẽ chỉ mang tính cục bộ.

--restart always là để container tự động khởi động lại, nghĩa là nó luôn hoạt động.

--name registry đơn giản là tên để dễ dàng nhìn thấy trong danh sách container bằng lệnh docker ps.

registry:2 là tên image từ Docker Hub.

Tự build image cục bộ

Tất nhiên, các dự án docker-compose thực tế có thể rất khác nhau, vì vậy lệnh build image có thể khác nhau, nhưng nhiệm vụ của tôi liên quan đến agent của tôi tại https://github.com/haih-net/agent/tree/main/docker và ở đó tôi có một số file config. Đối với môi trường production, cần sử dụng hai file config này:

docker compose -f docker-compose.yml -f docker-compose.prod.yml build app

Nếu mọi thứ diễn ra OK và image đã được build thành công, cuối cùng bạn sẽ thấy một cái gì đó như thế này:

[+] Building 2/2lt c6cfb7caa875
 ✔ Service app  Built                                                                                                   269.2s 
 ✔ app          Built    

Điều quan trọng đối với chúng ta ở đây là mã hash c6cfb7caa875. Hãy xem một số thông tin về nó.

docker inspect c6cfb7caa875 | head -10
[
    {
        "Id": "sha256:c6cfb7caa875cf984db7fcf13bc6a886e92ddbe091f1c824a5aa871ab711bd59",
        "RepoTags": [
            "fi1osof-ru-agent-app:latest"
        ],
        "RepoDigests": [],
        "Parent": "sha256:96a5516e1319785787c218b1f04415763e20ea4b135e906d1b4138d0b7d82ae9",
        "Comment": "",
        "Created": "2026-06-10T21:41:51.224372504Z",

Ngay đây chúng ta có RepoTags fi1osof-ru-agent-app:latest, đây là cái tôi sẽ sử dụng và commit.

docker tag fi1osof-ru-agent-app:latest localhost:5000/fi1osof-agent-app:latest

Điều này là cần thiết để Docker biết nơi để đẩy image lên. Nhưng tôi không chắc chắn 100%. Tôi làm theo hướng dẫn và không hiểu hoàn toàn khi nào cái gì là cần thiết, nhưng theo logic thì nó cần điều này.

Đẩy image từ máy cục bộ lên registry của máy chủ

Đến đây bắt đầu có một chút phép thuật, bởi vì lệnh push của chúng ta là:

docker push localhost:5000/fi1osof-agent-app:latest

Nhưng lúc này, nếu chúng ta chạy nó, chúng ta sẽ nhận được kết quả như sau:

The push refers to repository [localhost:5000/fi1osof-agent-app]
Get "http://localhost:5000/v2/": dial tcp 127.0.0.1:5000: connect: connection refused

Đó là bởi vì chúng ta đang đẩy tới cổng cục bộ và hiển nhiên là chúng ta không có registry ở đây — nó nằm trên máy chủ. Tại sao lại như vậy và chúng ta phải làm gì để khắc phục? Như tôi đã nói ở trên, tôi không muốn bận tâm về quyền truy cập công khai, vì vậy một thủ thuật đơn giản được áp dụng - SSH tunnel. Đây là một kết nối trong đó cổng cục bộ được liên kết với cổng của máy chủ đích thông qua giao thức SSH. Tương đối mà nói, khi một kết nối như vậy được thiết lập, cổng cục bộ của chúng ta sẽ trở thành một cửa sổ dẫn đến cổng của máy chủ đích.

Đây là lệnh. Chỉ cần chạy nó trong một tab terminal riêng biệt, vì đây không phải là tiến trình chạy ngầm và nó sẽ chiếm dụng tab đó.

ssh -L 5000:localhost:5000 root@example.com

Thay vì example.com, tất nhiên bạn hãy chỉ định máy chủ hoặc IP của mình, và tất nhiên SSH phải được bật truy cập trên máy chủ.

Nếu mọi thứ suôn sẻ, bạn sẽ thấy mình đã đăng nhập vào máy chủ qua SSH, mọi thứ như bình thường. Nhưng điểm khác biệt là bây giờ bạn có thể truy cập cổng 5000 cục bộ. Hãy kiểm tra xem nó có hoạt động và registry có phản hồi không.

ssh -L 5000:localhost:5000 root@fi1osof.ru

Nếu mọi thứ OK, ít nhất một đối tượng trống {} sẽ được trả về.

Bây giờ bạn có thể thử đẩy image của mình lên một lần nữa. Nếu mọi thứ OK, các request sẽ bắt đầu chạy :-). Tất nhiên việc này sẽ mất một chút thời gian, đặc biệt nếu image nặng vài gigabyte.

Tải image xuống trên máy chủ

Cách đơn giản nhất là thêm nguồn image vào file compose.

# git diff
diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml
index 72c18f8..9b8c69f 100644
--- a/docker/docker-compose.prod.yml
+++ b/docker/docker-compose.prod.yml
@@ -8,6 +8,7 @@ services:
       - 443:443
 
   app:
+    image: localhost:5000/fi1osof-agent-app:latest
     restart: unless-stopped
     build:
       args:

Hiện tại đây là hardcode trên máy chủ, sau này tôi sẽ cần suy nghĩ xem làm thế nào cho đúng cách hơn.

Sau đó, bạn có thể tải xuống trực tiếp thông qua compose.

docker compose -f docker-compose.yml -f docker-compose.prod.yml pull app

Nhân tiện, một lợi ích phụ tuyệt vời là các bản cập nhật sau đó được build và triển khai rất nhanh, bởi vì có cache build, và một số layer đã có sẵn trong registry, nên chỉ một phần của dự án được đẩy lên.

docker push localhost:5000/fi1osof-agent-app:latest
The push refers to repository [localhost:5000/fi1osof-agent-app]
e9a428849d13: Pushed 
dc967676af36: Pushed 
3ad5267c7022: Pushed 
c74007ef1379: Layer already exists 
4aac218d60da: Layer already exists 
e57f06c69e56: Layer already exists 
aa40e465aa3b: Layer already exists 
f89beb6cb85b: Layer already exists 
4015bc6fbe7e: Layer already exists 
b06d6a345ba0: Layer already exists 
e75204ff1bca: Layer already exists 
f9093a7aaa16: Layer already exists 
1c49688bd8eb: Layer already exists 
f5b8fb1def00: Layer already exists 
8f003894a7ef: Layer already exists 
latest: digest: sha256:6c8820f4c3301f4160748cdb38e911e2f68f7fa701864048c605c8c4384f1949 size: 3483