Giới thiệu về Private Docker Registry
Khi làm việc với Docker, chúng ta thường xuyên xây dựng và đóng gói ứng dụng thành các Docker image. Những image này cần được lưu trữ để các môi trường khác (như phát triển, staging, hay production) có thể dễ dàng kéo về và sử dụng.
Docker Hub là registry công cộng phổ biến, lý tưởng cho các image mã nguồn mở hoặc public. Tuy nhiên, khi phát triển ứng dụng nội bộ, chứa dữ liệu nhạy cảm hoặc không muốn chia sẻ image ra bên ngoài, việc dùng Private Docker Registry trở nên thiết yếu. Một Private Registry giúp bạn kiểm soát hoàn toàn việc lưu trữ và phân phối image Docker của mình.
So sánh các phương pháp quản lý Docker Images
Để lưu trữ và quản lý Docker image, chúng ta có vài lựa chọn chính:
1. Docker Hub
Ưu điểm:
- Dễ sử dụng: Việc bắt đầu rất đơn giản, đây gần như là lựa chọn mặc định cho mọi người dùng Docker.
- Miễn phí cho Public Repos: Bạn có thể lưu trữ không giới hạn số lượng image công khai.
- Cộng đồng lớn: Dễ dàng tìm thấy các image nền tảng (base images) và thư viện phổ biến.
Nhược điểm:
- Giới hạn Private Repos: Nếu không trả phí, bạn chỉ có một số lượng giới hạn private repository (hiện tại là 1).
- Rate Limit: Có giới hạn về số lượt kéo (pull) image, ví dụ 100 lượt mỗi 6 giờ cho người dùng ẩn danh, đặc biệt ảnh hưởng đến người dùng không trả phí.
- Phụ thuộc bên thứ ba: Bạn không có toàn quyền kiểm soát dữ liệu của mình.
2. Các dịch vụ Container Registry trên Cloud (AWS ECR, GCP GCR/Artifact Registry, Azure ACR)
Ưu điểm:
- Managed Service: Nhà cung cấp cloud lo mọi việc từ hạ tầng, scaling, bảo mật, backup.
- Scalable: Tự động mở rộng theo nhu cầu sử dụng của bạn.
- Tích hợp sâu: Kết nối chặt chẽ với các dịch vụ cloud khác (CI/CD, Kubernetes).
- Bảo mật tốt: Thường đi kèm với các tính năng bảo mật nâng cao.
Nhược điểm:
- Chi phí: Có thể khá cao, đặc biệt khi lưu trữ nhiều dữ liệu hoặc có lượng truy cập lớn.
- Vendor Lock-in: Khó khăn hơn khi muốn chuyển đổi giữa các nhà cung cấp cloud.
- Phụ thuộc vào nhà cung cấp: Vẫn không có toàn quyền kiểm soát như tự host.
3. Tự host Private Docker Registry
Ưu điểm:
- Toàn quyền kiểm soát: Bạn sở hữu và kiểm soát hoàn toàn dữ liệu image của mình.
- Bảo mật tối đa: Có thể triển khai trong mạng nội bộ, sau tường lửa. Điều này giúp đáp ứng các yêu cầu bảo mật và tuân thủ khắt khe nhất.
- Không giới hạn: Dung lượng và số lượng repository chỉ phụ thuộc vào phần cứng và hạ tầng của bạn.
- Tối ưu chi phí: Với quy mô lớn, việc tự host có thể rẻ hơn so với các dịch vụ cloud.
Nhược điểm:
- Tốn công sức: Cần thời gian và kiến thức để cài đặt, cấu hình, duy trì, backup và xử lý sự cố.
- Yêu cầu kiến thức: Cần hiểu biết về Docker, mạng, bảo mật và quản lý hệ thống.
Khi nào nên tự host Private Docker Registry?
Dựa trên những phân tích trên, mình nghĩ bạn nên cân nhắc tự host Private Docker Registry trong các trường hợp sau:
- Yêu cầu bảo mật và tuân thủ cao: Khi bạn không thể lưu trữ image trên các dịch vụ công cộng vì lý do bảo mật nội bộ, quy định pháp luật (như GDPR, HIPAA).
- Kiểm soát dữ liệu tuyệt đối: Bạn muốn toàn quyền quyết định dữ liệu image của mình được lưu trữ ở đâu, ai có thể truy cập, và bằng cách nào.
- Tối ưu chi phí cho quy mô lớn: Nếu bạn có một số lượng lớn image và lượng lớn lượt pull/push, việc tự host trên hạ tầng sẵn có có thể giúp tiết kiệm đáng kể chi phí băng thông và lưu trữ so với các dịch vụ cloud.
- Môi trường nội bộ/offline: Khi bạn cần một registry hoạt động trong mạng nội bộ không có kết nối internet hoặc cần tốc độ pull/push cực nhanh giữa các server trong cùng datacenter.
Mình nhớ hồi trước, team mình có một production cluster chạy tới 30+ container. Lúc đó, việc kéo image từ Docker Hub hay thậm chí các cloud registry cũng tốn kém băng thông và thời gian. Mình quyết định tự host private registry ngay trên một server cục bộ. Kết quả là giảm được 40% resource usage cho việc pull/push image so với việc phải đi qua Internet ra các registry bên ngoài, đồng thời tăng tốc độ deploy đáng kể. Nó thực sự tạo ra sự khác biệt lớn trong hiệu suất của hệ thống.
Hướng dẫn triển khai Private Docker Registry an toàn
Bây giờ, chúng ta sẽ cùng đi sâu vào các bước triển khai một Private Docker Registry với bảo mật HTTPS và xác thực người dùng. Mình sẽ hướng dẫn từng bước chi tiết để bạn dễ dàng làm theo.
Bước 1: Chuẩn bị môi trường
Bạn cần một server Linux (Ubuntu hoặc CentOS đều được) và Docker đã được cài đặt. Mình khuyến khích sử dụng Docker Compose để quản lý các service dễ dàng hơn.
1.1. Cài đặt Docker (nếu chưa có):
sudo apt update
sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Thêm người dùng vào nhóm docker để không cần dùng sudo
sudo usermod -aG docker $USER
newgrp docker
1.2. Cài đặt Docker Compose (v2):
Nếu bạn cài đặt Docker theo hướng dẫn trên, Docker Compose Plugin (v2) đã được cài đặt cùng. Bạn chỉ cần gõ docker compose (có khoảng trắng) thay vì docker-compose.
Bước 2: Chạy Docker Registry cơ bản (HTTP – Insecure)
Trước tiên, chúng ta sẽ chạy một Registry cơ bản qua HTTP. Đây chỉ là bước đầu để kiểm tra và không nên dùng cho production vì không bảo mật.
2.1. Tạo thư mục lưu trữ dữ liệu:
Registry sẽ lưu trữ image trên ổ đĩa. Bạn nên ánh xạ một thư mục trên host vào container để dữ liệu không bị mất khi container dừng hoặc xóa.
sudo mkdir -p /var/lib/registry
2.2. Chạy container Registry:
docker run -d -p 5000:5000 --restart=always --name registry -v /var/lib/registry:/var/lib/registry registry:2
Lệnh này sẽ kéo image registry:2 (phiên bản ổn định nhất của Docker Registry), chạy nó ở port 5000, và ánh xạ thư mục /var/lib/registry của host vào bên trong container.
2.3. Cấu hình Docker daemon để cho phép insecure registry (chỉ để test):
Mặc định Docker daemon chỉ cho phép kết nối HTTPS. Để test với HTTP, bạn cần chỉnh sửa file /etc/docker/daemon.json.
sudo nano /etc/docker/daemon.json
Thêm hoặc chỉnh sửa nội dung như sau (thay your_server_ip:5000 bằng IP hoặc domain của bạn):
{
"insecure-registries": [
"your_server_ip:5000"
]
}
Sau đó, khởi động lại Docker service:
sudo systemctl restart docker
2.4. Test Push/Pull một image:
docker pull hello-world
docker tag hello-world your_server_ip:5000/hello-world
docker push your_server_ip:5000/hello-world
docker rmi your_server_ip:5000/hello-world hello-world # Xóa local image để test pull
docker pull your_server_ip:5000/hello-world
Nếu mọi thứ hoạt động, bạn sẽ thấy image hello-world được đẩy lên và kéo về thành công. Đừng quên xóa insecure-registries khỏi daemon.json và khởi động lại Docker sau khi test xong bước này.
Bước 3: Bảo mật với HTTPS (Nginx Reverse Proxy + Let’s Encrypt)
Đây là bước cực kỳ quan trọng để đảm bảo an toàn cho Private Registry của bạn. Chúng ta sẽ dùng Nginx làm reverse proxy và Let’s Encrypt để cấp chứng chỉ SSL miễn phí.
3.1. Chuẩn bị Domain và DNS:
Bạn cần có một tên miền (ví dụ: registry.yourdomain.com) và trỏ bản ghi A (hoặc CNAME) của nó về địa chỉ IP công cộng của server.
3.2. Dừng Registry cũ và chuẩn bị Docker Compose:
Dừng và xóa container registry cũ:
docker stop registry
docker rm registry
Tạo file docker-compose.yml:
version: '3.8'
services:
registry:
image: registry:2
volumes:
- /var/lib/registry:/var/lib/registry
environment:
REGISTRY_HTTP_ADDR: 0.0.0.0:5000
restart: always
Lưu ý: Chúng ta không expose port 5000 ra ngoài host nữa, Nginx sẽ làm nhiệm vụ đó.
3.3. Cài đặt Nginx:
sudo apt update
sudo apt install nginx
3.4. Cài đặt Certbot và lấy chứng chỉ SSL (Let’s Encrypt):
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d registry.yourdomain.com
Certbot sẽ tự động cấu hình Nginx cho bạn và gia hạn chứng chỉ.
3.5. Cấu hình Nginx làm Reverse Proxy:
File cấu hình Nginx cho domain của bạn sẽ nằm ở /etc/nginx/sites-available/registry.yourdomain.com (hoặc tương tự), đã được Certbot tạo. Hãy kiểm tra và chỉnh sửa nếu cần, đảm bảo nó chuyển tiếp request tới port 5000 của registry container.
Một cấu hình cơ bản sẽ trông như thế này (Certbot sẽ thêm phần SSL tự động):
server {
listen 80;
listen [::]:80;
server_name registry.yourdomain.com;
location / {
# Chuyển hướng HTTP sang HTTPS
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name registry.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/registry.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/registry.yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
client_max_body_size 0; # Cho phép upload image dung lượng lớn
location / {
proxy_pass http://localhost:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900s; # Tăng timeout cho các tác vụ push/pull lớn
# Bắt buộc các header cần thiết cho Docker Registry
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_buffering off;
chunked_transfer_encoding on;
}
}
Kiểm tra cấu hình Nginx và khởi động lại:
sudo nginx -t
sudo systemctl restart nginx
3.6. Chạy Registry với Docker Compose:
Vào thư mục chứa docker-compose.yml và chạy:
docker compose up -d
Bây giờ Registry của bạn đã chạy qua HTTPS. Bạn có thể test push/pull lại, lần này sử dụng domain của bạn và không cần --insecure-registry.
docker pull hello-world
docker tag hello-world registry.yourdomain.com/hello-world
docker push registry.yourdomain.com/hello-world
Bước 4: Thêm xác thực người dùng (Basic Authentication)
Để ngăn chặn truy cập trái phép, chúng ta sẽ thêm Basic Authentication cho Registry.
4.1. Cài đặt apache2-utils (để dùng htpasswd):
sudo apt install apache2-utils
4.2. Tạo file htpasswd:
Tạo một file chứa thông tin người dùng và mật khẩu (ví dụ: /etc/nginx/conf.d/registry.password). Lần đầu tạo dùng -c, các lần sau thêm người dùng mới thì bỏ -c.
sudo htpasswd -c /etc/nginx/conf.d/registry.password your_username
Nhập mật khẩu khi được hỏi.
4.3. Cấu hình Nginx để yêu cầu xác thực:
Chỉnh sửa file cấu hình Nginx cho Registry (/etc/nginx/sites-available/registry.yourdomain.com), thêm hai dòng sau vào trong khối location / {} của server HTTPS:
auth_basic "Registry Restricted";
auth_basic_user_file /etc/nginx/conf.d/registry.password;
Sau đó, kiểm tra cấu hình Nginx và khởi động lại:
sudo nginx -t
sudo systemctl restart nginx
4.4. Đăng nhập vào Registry:
Bây giờ khi bạn push/pull, Docker sẽ yêu cầu bạn đăng nhập:
docker login registry.yourdomain.com
Nhập username và password bạn đã tạo bằng htpasswd. Sau khi đăng nhập thành công, bạn có thể push/pull image như bình thường.
Bước 5: Quản lý Storage (Persistent Volume)
Chúng ta đã cấu hình volume /var/lib/registry ở Bước 2. Điều quan trọng là đảm bảo thư mục này có đủ dung lượng và được backup thường xuyên. Nếu bạn chạy trên một VPS, hãy đảm bảo volume này được gắn trên một ổ đĩa có độ bền cao và khả năng phục hồi dữ liệu.
Bước 6: Tối ưu và bảo trì
Tự host Registry không chỉ là cài đặt mà còn bao gồm bảo trì định kỳ:
- Garbage Collection: Khi bạn xóa một image khỏi Registry, các layer của nó vẫn còn trên đĩa. Để giải phóng dung lượng, bạn cần chạy lệnh garbage collection. Tuy nhiên, hãy chắc chắn rằng không có hoạt động push/pull nào đang diễn ra khi chạy lệnh này.
docker compose stop registry
docker run --rm -v /var/lib/registry:/var/lib/registry registry:2 garbage-collect /etc/docker/registry/config.yml
docker compose start registry
Bạn có thể cần ánh xạ file cấu hình của Registry nếu nó không dùng mặc định.
- Giới hạn quyền truy cập mạng: Dùng firewall (UFW, firewalld) để chỉ cho phép các IP hoặc dải IP cụ thể truy cập vào port 443 của Registry.
- Backup: Thiết lập kế hoạch backup định kỳ cho thư mục
/var/lib/registryđể tránh mất dữ liệu.
Kết luận
Tự host Private Docker Registry mang lại sự linh hoạt, bảo mật và khả năng kiểm soát cao đối với Docker image của bạn. Mặc dù yêu cầu một chút công sức ban đầu để cài đặt và cấu hình, với hướng dẫn chi tiết này, mình tin bạn có thể triển khai thành công một Registry an toàn và hiệu quả. Đây là một giải pháp tối ưu cho các dự án cần bảo mật thông tin, tối ưu hóa hạ tầng và kiểm soát hoàn toàn vòng đời ứng dụng.

