Lệnh docker pull khá rõ ràng, nhưng có rất nhiều thứ diễn ra bên dưới mà ngay cả chuyên gia dày dạn cũng không biết.
Mọi developer đều nên biết điều này. Bạn pull image hằng ngày, nhưng khi có sự cố, thật khó để xác định nguyên nhân. Hoặc xác thực thất bại không rõ lý do, hoặc bị áp giới hạn tần suất, hoặc bạn lại dùng nhầm phiên bản image trong production. Mỗi lần lỗi như vậy sẽ tiêu tốn thời gian để khắc phục, lẽ ra không nên xảy ra ngay từ đầu.
Hiểu docker pull thực sự hoạt động thế nào sẽ giúp bạn kiểm soát. Bạn sẽ biết image đến từ đâu, cách pull chúng, và cách xử lý sự cố trước khi ảnh hưởng đến production.
Trong bài viết này, tôi sẽ giải thích cơ chế pull image phía sau hậu trường, vai trò của registry, và cách pull image trong cả môi trường phát triển cục bộ lẫn production.
Nếu bạn hoàn toàn mới với Docker, tôi rất khuyến khích bạn học qua khóa Giới thiệu về Dockervì khóa học sẽ cung cấp nền tảng cần thiết để hiểu bài này.
Cách docker pull hoạt động phía dưới
Trong phần này, tôi sẽ đi qua cơ chế của lệnh docker pull và xóa bỏ mọi nhầm lẫn về những gì diễn ra đằng sau.
Mặc định, lệnh này sẽ giao tiếp với Docker Hub, tải image Python xuống và lưu cục bộ trên máy của bạn. Nhưng còn nhiều thứ diễn ra hơn những gì bạn thấy.
Luồng xử lý như sau:
Docker client của bạn gửi yêu cầu đến registry (Docker Hub, trừ khi bạn chỉ định khác)
Registry phản hồi bằng manifest của image, liệt kê tất cả các layer cấu thành image
Client của bạn sau đó tải từng layer chưa có và lưu vào /var/lib/docker trên hệ thống Linux, và vào các thư mục do Docker Desktop quản lý (ví dụ, dưới ~Library/Containers/… trên macOS và C:\Users\[Username]\AppData\... trên Windows.)
Thẻ :latestlà mặc định của Docker khi bạn không chỉ định phiên bản. Chạy docker pull python mà không có tag, bạn sẽ nhận python:latest. Nghe có vẻ tiện, nhưng rủi ro. Thẻ :latest không có nghĩa là "phiên bản ổn định mới nhất." Nó nghĩa là "bất kỳ thứ gì maintainer gắn là latest." Điều đó có thể thay đổi giữa các lần pull và âm thầm phá vỡ build của bạn.
Các layer của image và lưu trữ định địa chỉ theo nội dung
Docker image được xây dựng từ các layer.
Mỗi layer biểu diễn một thay đổi so với layer trước đó. Khi bạn build một image, mỗi chỉ thị RUN, COPY hoặc ADD trong Dockerfile sẽ tạo một layer mới. Image cuối cùng là một chồng các layer này, ghép lại theo thứ tự.
Ví dụ, hãy xem các lệnh phía sau image Python 3.14 ở trên - có rất nhiều thứ diễn ra.
Lưu trữ định địa chỉ theo nội dung (content-addressable storage) là thứ khiến cơ chế này hoạt động. Mỗi layer nhận một hash duy nhất dựa trên nội dung của nó. Nếu hai image chia sẻ cùng base layer (như ubuntu:24.04), Docker chỉ lưu layer đó một lần. Khi bạn pull một image mới dùng chung base, Docker bỏ qua việc tải về.
Điều này giảm băng thông và dung lượng lưu trữ. Pull mười image Python với các tag khác nhau, Docker sẽ tái sử dụng các layer chung giữa tất cả. Bạn chỉ tải những phần thực sự khác biệt.
docker pull vs docker image pull
Cả hai lệnh đều tương đương về chức năng. Chúng pull image từ registry và lưu cục bộ.
Sự khác biệt nằm ở tổ chức. Docker giới thiệu nhóm lệnh docker image như một phần tái cấu trúc CLI để các lệnh trực quan hơn. Thay vì có docker pull, docker rmi và docker images rải rác, họ nhóm các lệnh liên quan đến image dưới docker image pull, docker image rm và docker image ls.
Dùng cái nào bạn thích. docker pull ngắn hơn và phổ biến trong tài liệu. docker image pull rõ ràng hơn và phù hợp trong script nơi cần minh bạch. Hãy chọn một phong cách và dùng nhất quán trong đội của bạn.
Giải thích tham chiếu image Docker
Một tham chiếu image có tối đa năm phần: HOST/NAMESPACE/REPOSITORY:TAG@DIGEST.
Ý nghĩa từng phần:
HOST: Địa chỉ registry (ví dụ, docker.io, gcr.io, quay.io). Bỏ qua phần này, Docker mặc định dùng Docker Hub.
NAMESPACE: Thường là tên người dùng hoặc tổ chức của bạn (ví dụ, library cho image chính thức, hoặc mycompany cho image riêng tư).
REPOSITORY: Tên image thực tế (ví dụ, python, nginx, redis).
TAG: Định danh phiên bản (ví dụ, 3.14.2-bookworm, latest). Mặc định là :latest nếu bạn bỏ qua.
DIGEST: Hash SHA256 của manifest image (ví dụ, @sha256:abc123...). Đây là bất biến - tag có thể thay đổi, digest thì không.
Trong hậu trường, lệnh này được mở rộng thành docker.io/library/python:3.14.2-bookworm.
Với registry riêng tư, bạn cần tham chiếu đầy đủ:
docker pull myregistry.example.com/myteam/myimageĐược hỗ trợ bởi
Dùng tham chiếu chính xác (tag hoặc digest cụ thể) giúp triển khai có thể tái lập. Pull python:3.14.2-bookworm hôm nay và tháng sau, bạn sẽ nhận cùng một image. Pull python:latest hai lần, khả năng cao là không.
Docker Registry và nguồn gốc của image
Registry là nơi Docker lưu trữ và phân phối image - chúng là nguồn cho mọi lệnh docker pull bạn chạy.
Docker Hub là registry mặc định
Docker Hub là registry mặc định cho mọi lệnh docker pull trừ khi bạn chỉ định khác.
Chạy docker pull python:3.14.2-bookworm, Docker tự động chuyển thành docker.io/library/python:3.14.2-bookworm. Bạn không cần đăng nhập với image public - Docker Hub phục vụ ẩn danh, nhưng có giới hạn tần suất với người dùng chưa xác thực.
Có hai loại image trên Docker Hub: Image chính thức và image cộng đồng.
Image chính thức đến từ các publisher đã xác minh và được Docker hoặc chính nhà cung cấp phần mềm duy trì. Chúng nằm dưới namespace library (Docker ẩn khỏi bạn). Khi bạn pull python, nginx, hoặc redis, bạn đang nhận Image chính thức tuân theo best practice của Docker về bảo mật và cập nhật định kỳ.
Image cộng đồng là tất cả phần còn lại. Bất kỳ ai cũng có thể xuất bản image lên Docker Hub dưới tên người dùng hoặc tổ chức của họ. Pull johndoe/python-custom, và bạn đang đặt niềm tin vào johndoe để duy trì image đó đúng cách. Một số image cộng đồng rất tốt và được bảo trì. Số khác không được cập nhật trong nhiều năm và chứa lỗ hổng đã biết.
Sự tin cậy rất quan trọng ở đây. Image chính thức nhận bản vá bảo mật thường xuyên và có tài liệu rõ ràng. Với image cộng đồng, bạn tự chịu trách nhiệm xác minh ai duy trì và liệu chúng có an toàn để sử dụng hay không.
Registry riêng tư và tùy chỉnh
Phần lớn công ty không muốn image container của họ nằm trên Docker Hub công khai.
Registry riêng tư là lựa chọn phù hợp. Bạn quyết định ai có thể pull image, kiểm soát chính sách lưu trữ, và giữ mã nguồn sở hữu trí tuệ trong hạ tầng của mình. Điều này quan trọng cho tuân thủ, bảo mật, và quản lý truy cập giữa các nhóm.
Các giải pháp registry riêng tư phổ biến gồm:
Harbor: Registry mã nguồn mở với quét bảo mật và kiểm soát truy cập tích hợp
JFrog Artifactory: Giải pháp enterprise xử lý Docker image cùng các loại artifact khác
Tất nhiên, tham chiếu image sẽ thay đổi khi bạn dùng registry tùy chỉnh. Thay vì python:3.14.2-bookworm, bạn cần chỉ định đầy đủ đường dẫn:
docker pull myregistry.company.com/team/python:3.14.2-bookwormĐược hỗ trợ bởi
Hostname của registry đặt trước, sau đó là namespace của bạn (thường là tên nhóm hoặc dự án), rồi đến repository và tag. Docker sẽ không mặc định về Docker Hub khi thấy một hostname tùy chỉnh - nó đi thẳng đến registry riêng tư của bạn.
Xác thực, giới hạn tần suất và kiểm soát truy cập
Xác thực áp dụng cho cả push và pull image, và đặc biệt quan trọng khi bạn chạm ngưỡng giới hạn tần suất hoặc truy cập registry riêng tư.
Đăng nhập và quản lý thông tin xác thực
Bạn có thể dùng lệnh docker login để xác thực với một registry:
Docker lưu thông tin xác thực cục bộ sau khi đăng nhập. Trên Linux, chúng nằm ở ~/.docker/config.json. Trên macOS, Docker sử dụng keychain của hệ thống để tăng bảo mật.
Vấn đề là file cấu hình mặc định lưu thông tin xác thực bằng mã hóa base64, vốn không phải mã hóa bảo mật. Bất kỳ ai có quyền truy cập thư mục home của bạn đều có thể giải mã. Để giảm rủi ro, bạn có thể dùng credential helper - Docker hỗ trợ keychain gốc của hệ điều hành để lưu mật khẩu an toàn.
Một vài thực hành tốt để quản lý thông tin xác thực:
Sử dụng credential helper (docker-credential-osxkeychain, docker-credential-wincred)
Không bao giờ commit config.json vào hệ thống quản lý phiên bản
Ưu tiên dùng access token thay cho mật khẩu khi có thể
Xoay vòng thông tin xác thực định kỳ, đặc biệt với tài khoản dùng chung
Giới hạn tần suất của Docker Hub
Docker Hub giới hạn số lượng image bạn có thể pull trong một khoảng thời gian.
Người dùng ẩn danh (không đăng nhập) được 100 lần pull mỗi 6 giờ trên mỗi địa chỉ IP. Người dùng miễn phí đã xác thực được 200 lần mỗi 6 giờ. Gói trả phí có giới hạn cao hơn hoặc không giới hạn tùy bậc.
Những giới hạn này quan trọng khi bạn chạy pipeline CI/CD, pull image thường xuyên trong quá trình phát triển, hoặc làm việc trên hạ tầng dùng chung nơi nhiều người dùng chung một IP. Khi chạm giới hạn, các lần pull sẽ thất bại cho đến khi cửa sổ thời gian được đặt lại.
Bạn có thể kiểm tra trạng thái giới hạn hiện tại:
TOKEN=$(curl"<https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull>"| jq -r .token)curl--head-H"Authorization: Bearer $TOKEN"<https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest>Được hỗ trợ bởi
Một vài cách tăng giới hạn tần suất (đa số developer sẽ không gặp vấn đề này):
Xác thực khi pull: Đăng nhập để có giới hạn cao hơn, ngay cả với tài khoản miễn phí
Dùng mirror của registry: Thiết lập bộ nhớ đệm pull-through để lưu image cục bộ
Chuyển sang registry riêng: Tự host registry để tránh hoàn toàn giới hạn của Docker Hub
Cache image cục bộ: Pull một lần, tái sử dụng nhiều lần thay vì pull lặp lại
Cách đơn giản nhất là đăng nhập. Việc này một mình đã nhân đôi giới hạn của bạn.
Tùy chọn nâng cao khi pull image
Các tùy chọn nâng cao này mang lại độ chính xác và kiểm soát, đúng thứ bạn cần trong môi trường production.
Pull image theo digest
Digest là định danh bất biến dựa trên hash nội dung của image.
Tag có thể thay đổi. Ai đó push image mới với cùng tag, và đột nhiên python:3.14.2-bookworm trỏ đến nội dung khác ngày hôm qua. Digest thì không thể thay đổi - chúng là hash SHA256 của manifest image. Cùng một digest luôn đồng nghĩa với đúng image đó.
Pull theo digest như sau:
docker pull python@sha256:6d58c1a9444bc2664f0fa20c43a592fcdb2698eb9a9c32257516538a2746c19aĐược hỗ trợ bởi
docker pull --platform linux/amd64 python:3.14.2-bookwormĐược hỗ trợ bởi
Điều này quan trọng nhất trong CI/CD và production. Bạn kiểm thử với một image cụ thể, bạn triển khai đúng image đó. Không bất ngờ, không trôi lệch giữa các môi trường. Nếu triển khai phụ thuộc vào phiên bản cụ thể, hãy dùng digest - không dùng tag.
Pull image đa kiến trúc
Image đa kiến trúc gói các phiên bản cho kiến trúc CPU khác nhau trong một tham chiếu image duy nhất.
Pull python:3.14.2-bookworm, và Docker tự động chọn phiên bản phù hợp với hệ thống của bạn - amd64 cho máy x86, arm64 cho Apple Silicon hoặc máy chủ ARM. Registry sẽ phục vụ đúng kiến trúc mà không cần bạn làm gì.
Nhưng đôi khi bạn cần kiến trúc cụ thể. Hãy dùng cờ --platform:
docker pull --platform linux/amd64 python:3.14.2-bookwormĐược hỗ trợ bởi
Điều này hữu ích khi bạn phát triển trên Apple Silicon nhưng cần kiểm thử phiên bản amd64 sẽ chạy trong production, hoặc khi bạn build image cho kiến trúc khác với máy build.
Pull nhiều tag
Cờ --all-tags sẽ pull toàn bộ tag của một repository:
Lệnh này sẽ tải mọi tag của Python - hàng tá phiên bản, biến thể và kiến trúc. Bạn sẽ có hàng gigabyte image.
Đừng dùng trừ khi thực sự cần. Băng thông tốn chi phí, dung lượng lưu trữ sẽ đầy nhanh, và bạn có lẽ không cần mọi phiên bản Python từng phát hành. Hãy pull những tag cụ thể bạn thực sự dùng.
Hủy một lệnh pull
Nhấn Ctrl+C hoặc CMD+C để hủy một lệnh pull đang diễn ra.
Docker dừng tải các layer mới nhưng giữ lại những layer đã hoàn tất. Lần sau khi bạn pull cùng image, nó sẽ tiếp tục từ chỗ dở thay vì bắt đầu lại.
Điều này hữu ích khi bạn lỡ pull sai image, khi pull mất quá lâu do kết nối chậm, hoặc khi bạn nhận ra hiện tại không cần image đó. Hủy, sửa lệnh và pull lại mà không lãng phí công sức đã làm.
Các cân nhắc về hiệu năng với docker pull
Mạng trong thực tế có các ràng buộc như giới hạn băng thông, proxy và kết nối chậm. Chúng có thể khiến việc pull image lâu hơn mức cần thiết, sau đây là những gì bạn có thể làm.
Tối ưu hiệu năng pull
Docker mặc định tải các layer của image đồng thời.
Thay vì tải từng layer một, Docker mở nhiều kết nối và tải nhiều layer cùng lúc. Điều này tăng tốc trên đường truyền nhanh, nhưng bạn sẽ khó nhận thấy khác biệt trên mạng chậm nơi băng thông là nút thắt.
Hai chiến lược phổ biến giúp hiệu quả hơn nữa:
Bộ nhớ đệm giữ các image đã pull cục bộ. Pull một image một lần, dùng hàng trăm lần. Docker kiểm tra bạn đã có các layer hay chưa trước khi tải. Nếu image không đổi, lệnh pull hoàn tất gần như ngay lập tức.
Preload image nghĩa là pull chúng vào giờ thấp điểm hoặc như một phần quy trình triển khai. Hệ thống CI/CD thường cache các base image trên máy build để developer không phải chờ pull mỗi lần build. Máy chủ production có thể làm ấm cache trong quá trình triển khai để tránh pull khi lưu lượng truy cập tăng.
Pull image qua proxy
Mạng doanh nghiệp định tuyến lưu lượng qua proxy vì lý do bảo mật, giám sát và kiểm soát truy cập.
Docker cần biết về các proxy này để pull image. Nếu không cấu hình proxy, lệnh pull sẽ lỗi timeout kết nối hoặc lỗi DNS vì Docker cố gắng kết nối trực tiếp đến registry thay vì qua proxy.
Bạn cấu hình proxy ở hai mức: Docker client và Docker daemon. Client (lệnh docker) tự động dùng thiết lập proxy HTTP của hệ thống. Daemon cần cấu hình tường minh trong /etc/docker/daemon.json hoặc thông qua file service của systemd.
Khắc phục sự cố pull thường gặp
Đây là danh sách kiểm tra thực tế khi lệnh pull thất bại - vì điều đó sẽ xảy ra, và bạn cần biết nên kiểm tra gì trước.
Lỗi thường gặp và cách chẩn đoán
Lỗi xác thực xuất hiện dưới dạng "unauthorized" hoặc "access denied".
Kiểm tra xem bạn đã đăng nhập với docker login chưa. Nếu rồi, thông tin xác thực có thể đã hết hạn hoặc sai. Đăng xuất bằng docker logout, rồi đăng nhập lại. Với registry riêng, đảm bảo bạn dùng đúng hostname trong lệnh đăng nhập.
Thiếu tag sẽ gây lỗi "manifest unknown" hoặc "not found".
Tag bạn cố pull không tồn tại. Hãy kiểm tra kỹ tên tag vì rất dễ gõ sai. Kiểm tra giao diện web của registry để xem các tag thật sự tồn tại. Lưu ý tag có thể bị xóa, nên thứ hoạt động hôm qua có thể hôm nay không còn.
Timeout mạng xảy ra khi Docker không thể kết nối đến registry.
Đầu tiên, kiểm tra kết nối internet của bạn. Sau đó xác minh bạn có thể kết nối trực tiếp đến registry - chạy ping registry-1.docker.io hoặc curl -I <https://registry-1.docker.io>. Nếu bạn ở sau proxy, đảm bảo Docker biết về proxy đó. Nếu là registry riêng, kiểm tra rule firewall và kết nối VPN.
Vấn đề quyền hạn xuất hiện dưới dạng lỗi "denied" ngay cả khi bạn đã xác thực.
Bạn đã đăng nhập, nhưng tài khoản của bạn không có quyền pull repository cụ thể này. Hãy liên hệ chủ repository hoặc quản trị viên registry để được cấp quyền. Với Docker Hub, thường là image ở chế độ private và bạn không nằm trong danh sách truy cập.
Sự cố DNS và phân giải mạng
Lỗi DNS khiến Docker không tìm được máy chủ registry.
Bạn sẽ thấy lỗi như "no such host" hoặc "temporary failure in name resolution." Thực tế là Docker không thể chuyển hostname của registry thành địa chỉ IP, nên không thể kết nối.
Để khắc phục, kiểm tra phân giải DNS bằng nslookup registry-1.docker.io hoặc dig registry-1.docker.io. Nếu các lệnh này thất bại, máy chủ DNS của bạn không thể truy cập hoặc cấu hình sai. Hãy thử chuyển tạm thời sang DNS công cộng như 8.8.8.8 để xem có khắc phục không.
Trong mạng doanh nghiệp, máy chủ DNS có thể chỉ phân giải hostname nội bộ. Hãy đảm bảo hostname của registry riêng nằm trong máy chủ DNS, hoặc thêm vào /etc/hosts như một giải pháp tạm cho đến khi DNS được sửa.
docker pull trong quy trình điều phối và cục bộ
Giờ đến phần thú vị - cách lệnh docker pull hoạt động trong các kịch bản bạn có thể gặp trong công việc hằng ngày.
Pull image trong Kubernetes
Kubernetes tự động pull image khi bạn triển khai pod.
Bạn định nghĩa một container trong pod spec với tham chiếu image, và Kubernetes sẽ xử lý việc pull cho bạn. Kubelet trên mỗi node kiểm tra image có sẵn cục bộ hay chưa. Nếu chưa, nó pull từ registry trước khi khởi động container.
Chính sách pull kiểm soát khi nào Kubernetes pull image:
Always: Luôn pull image, kể cả khi đã có cục bộ
IfNotPresent: Chỉ pull nếu image chưa có trên node (mặc định cho image có tag)
Never: Không bao giờ pull, lỗi nếu image chưa có cục bộ
Thiết lập chính sách trong pod spec với imagePullPolicy. Dùng Always cho tag :latest trong phát triển để nhận cập nhật. Dùng IfNotPresentcho các tag cụ thể trong production để tránh pull không cần thiết.
imagePullSecrets cung cấp cho Kubernetes quyền truy cập registry riêng. Bạn có thể tạo một secret với thông tin xác thực registry, sau đó tham chiếu trong pod spec. Nếu không có, Kubernetes chỉ có thể pull image public.
Docker Compose và phát triển cục bộ
Compose tự động pull khi bạn khởi động ứng dụng đa dịch vụ.
Chạy docker compose up, Compose kiểm tra image của mỗi service. Nếu một image thiếu, Compose sẽ pull trước khi khởi động container. Bạn không cần chạy docker pull thủ công cho từng service, vì Compose xử lý giúp bạn.
Cách này rất phù hợp cho phát triển. Bạn định nghĩa service trong docker-compose.yml, chạy một lệnh, và Compose sẽ pull mọi thứ bạn cần. Lần up đầu mất lâu hơn do tải image, nhưng các lần sau sẽ tức thì nếu image không đổi.
docker compose vs docker compose pull
Đây là hai lệnh khác nhau làm những việc khác nhau.
docker compose up khởi động service của bạn. Nó tự động pull các image thiếu, nhưng chỉ khi chúng chưa có cục bộ. Nếu bạn đã có python:3.14.2-bookworm trên máy, Compose sẽ dùng luôn mà không kiểm tra cập nhật.
docker compose pull sẽ pull tường minh tất cả image được định nghĩa trong file compose, bất kể chúng đã có cục bộ hay chưa. Lệnh này kiểm tra cập nhật từ registry và tải phiên bản mới nếu có.
Khi nào bạn cần docker compose pull:
Bạn dùng tag :latest và muốn phiên bản mới nhất. Chạy docker compose pull trước để cập nhật, rồi docker compose up để khởi động với image mới.
Bạn đang debug và nghi ngờ image cục bộ đã lỗi thời hoặc hỏng. Hãy pull bản mới với docker compose pull, rồi khởi động lại.
Bạn muốn preload image trước khi thực sự khởi động service. Chạy docker compose pull trong lúc triển khai để cache image, sau đó docker compose up sẽ chạy ngay mà không phải chờ tải.
Khác biệt cốt lõi là up chỉ pull phần thiếu, còn pull sẽ cập nhật tất cả bất kể bạn đã có gì.
Kết luận
Lệnh docker pull trông đơn giản, nhưng có rất nhiều thứ diễn ra bên dưới và có nhiều điểm bạn có thể tinh chỉnh. Dưới đây là một số thực hành tốt cần ghi nhớ.
Hãy dùng tag hoặc digest tường minh thay vì :latest. Xác thực khi pull để tránh giới hạn tần suất. Lưu ý băng thông và lưu trữ khi pull image, đặc biệt trong pipeline CI/CD nơi bạn pull liên tục.
Xem việc pull image như một phần của pipeline bảo mật. Mỗi lần pull đều có thể là điểm tấn công nếu bạn dùng nguồn không tin cậy hoặc image lỗi thời có lỗ hổng đã biết. Hãy xác minh nguồn, quét vấn đề, và giữ base image luôn cập nhật.
Docker registry và công cụ thay đổi thường xuyên. Theo kịp các cập nhật từ nhà cung cấp registry của bạn để tránh bất ngờ phá vỡ quy trình làm việc.
Chuyên gia Khoa học Dữ liệu Cấp cao, làm việc tại Croatia. Tác giả Công nghệ Hàng đầu với hơn 700 bài viết đã xuất bản, đạt trên 10 triệu lượt xem. Tác giả cuốn sách Tự động hóa Machine Learning với TPOT.
Câu hỏi thường gặp về docker pull
docker pull làm gì?⌄
docker pull tải image container từ các registry như Docker Hub về máy cục bộ của bạn. Lệnh sẽ lấy các layer image bạn chưa có và lưu cục bộ để bạn có thể chạy container từ image đó. Nếu không pull image trước, bạn không thể khởi động container trừ khi image đã tồn tại trên hệ thống.
Làm sao tránh giới hạn tần suất của Docker Hub?⌄
Đăng nhập bằng docker login để tăng gấp đôi hạn mức từ 100 lên 200 lần pull mỗi 6 giờ. Với đội ngũ thường xuyên chạm giới hạn, hãy dùng registry riêng hoặc thiết lập pull-through cache lưu image cục bộ. Cách dễ nhất là xác thực - ngay cả tài khoản Docker Hub miễn phí cũng tạo khác biệt lớn.
Sự khác nhau giữa docker pull và docker image pull là gì?⌄
Chúng tương đương về chức năng và làm đúng cùng một việc. Docker giới thiệu docker image pull như một phần tái tổ chức CLI để nhóm các lệnh liên quan. Dùng cái nào bạn thích - docker pull ngắn hơn và phổ biến hơn, còn docker image pull rõ ràng hơn trong script.
Tôi nên dùng tag hay digest trong production?⌄
Hãy dùng digest trong production để đảm bảo tính bất biến. Tag như python:3.14.2-bookworm có thể thay đổi nếu ai đó push image mới với cùng tag, nhưng digest là hash SHA256 không bao giờ đổi. Pull theo digest với docker pull python@sha256:abc123… để đảm bảo bạn luôn nhận đúng image.
Vì sao docker pull báo lỗi "manifest unknown"?⌄
Tag bạn đang cố pull không tồn tại trong registry. Hãy kiểm tra kỹ tên tag để tránh gõ sai và xác minh tag tồn tại bằng giao diện web của registry. Tag cũng có thể bị xóa, nên thứ từng hoạt động có thể không còn nữa.
Tìm hiểu về Docker và khám phá tầm quan trọng của nó trong bộ công cụ của chuyên gia dữ liệu. Tìm hiểu về Docker container, Docker image và nhiều nội dung khác.
Lệnh
docker pullkhá rõ ràng, nhưng có rất nhiều thứ diễn ra bên dưới mà ngay cả chuyên gia dày dạn cũng không biết.Mọi developer đều nên biết điều này. Bạn pull image hằng ngày, nhưng khi có sự cố, thật khó để xác định nguyên nhân. Hoặc xác thực thất bại không rõ lý do, hoặc bị áp giới hạn tần suất, hoặc bạn lại dùng nhầm phiên bản image trong production. Mỗi lần lỗi như vậy sẽ tiêu tốn thời gian để khắc phục, lẽ ra không nên xảy ra ngay từ đầu.
Hiểu
docker pullthực sự hoạt động thế nào sẽ giúp bạn kiểm soát. Bạn sẽ biết image đến từ đâu, cách pull chúng, và cách xử lý sự cố trước khi ảnh hưởng đến production.Trong bài viết này, tôi sẽ giải thích cơ chế pull image phía sau hậu trường, vai trò của registry, và cách pull image trong cả môi trường phát triển cục bộ lẫn production.
Nếu bạn hoàn toàn mới với Docker, tôi rất khuyến khích bạn học qua khóa Giới thiệu về Docker vì khóa học sẽ cung cấp nền tảng cần thiết để hiểu bài này.
Cách docker pull hoạt động phía dưới
Trong phần này, tôi sẽ đi qua cơ chế của lệnh
docker pullvà xóa bỏ mọi nhầm lẫn về những gì diễn ra đằng sau.Điều gì xảy ra trong một lần docker pull
Cú pháp cơ bản rất đơn giản:
Mặc định, lệnh này sẽ giao tiếp với Docker Hub, tải image Python xuống và lưu cục bộ trên máy của bạn. Nhưng còn nhiều thứ diễn ra hơn những gì bạn thấy.
Luồng xử lý như sau:
Docker client của bạn gửi yêu cầu đến registry (Docker Hub, trừ khi bạn chỉ định khác)
Registry phản hồi bằng manifest của image, liệt kê tất cả các layer cấu thành image
/var/lib/dockertrên hệ thống Linux, và vào các thư mục do Docker Desktop quản lý (ví dụ, dưới~Library/Containers/…trên macOS vàC:\Users\[Username]\AppData\...trên Windows.)Thẻ
:latestlà mặc định của Docker khi bạn không chỉ định phiên bản. Chạydocker pull pythonmà không có tag, bạn sẽ nhậnpython:latest. Nghe có vẻ tiện, nhưng rủi ro. Thẻ:latestkhông có nghĩa là "phiên bản ổn định mới nhất." Nó nghĩa là "bất kỳ thứ gì maintainer gắn là latest." Điều đó có thể thay đổi giữa các lần pull và âm thầm phá vỡ build của bạn.Các layer của image và lưu trữ định địa chỉ theo nội dung
Docker image được xây dựng từ các layer.
Mỗi layer biểu diễn một thay đổi so với layer trước đó. Khi bạn build một image, mỗi chỉ thị
RUN,COPYhoặcADDtrong Dockerfile sẽ tạo một layer mới. Image cuối cùng là một chồng các layer này, ghép lại theo thứ tự.Ví dụ, hãy xem các lệnh phía sau image Python 3.14 ở trên - có rất nhiều thứ diễn ra.
Lưu trữ định địa chỉ theo nội dung (content-addressable storage) là thứ khiến cơ chế này hoạt động. Mỗi layer nhận một hash duy nhất dựa trên nội dung của nó. Nếu hai image chia sẻ cùng base layer (như
ubuntu:24.04), Docker chỉ lưu layer đó một lần. Khi bạn pull một image mới dùng chung base, Docker bỏ qua việc tải về.Điều này giảm băng thông và dung lượng lưu trữ. Pull mười image Python với các tag khác nhau, Docker sẽ tái sử dụng các layer chung giữa tất cả. Bạn chỉ tải những phần thực sự khác biệt.
docker pull vs docker image pull
Cả hai lệnh đều tương đương về chức năng. Chúng pull image từ registry và lưu cục bộ.
Sự khác biệt nằm ở tổ chức. Docker giới thiệu nhóm lệnh
docker imagenhư một phần tái cấu trúc CLI để các lệnh trực quan hơn. Thay vì códocker pull,docker rmivàdocker imagesrải rác, họ nhóm các lệnh liên quan đến image dướidocker image pull,docker image rmvàdocker image ls.Dùng cái nào bạn thích.
docker pullngắn hơn và phổ biến trong tài liệu.docker image pullrõ ràng hơn và phù hợp trong script nơi cần minh bạch. Hãy chọn một phong cách và dùng nhất quán trong đội của bạn.Giải thích tham chiếu image Docker
Một tham chiếu image có tối đa năm phần:
HOST/NAMESPACE/REPOSITORY:TAG@DIGEST.Ý nghĩa từng phần:
HOST: Địa chỉ registry (ví dụ,
docker.io,gcr.io,quay.io). Bỏ qua phần này, Docker mặc định dùng Docker Hub.NAMESPACE: Thường là tên người dùng hoặc tổ chức của bạn (ví dụ,
librarycho image chính thức, hoặcmycompanycho image riêng tư).REPOSITORY: Tên image thực tế (ví dụ,
python,nginx,redis).TAG: Định danh phiên bản (ví dụ,
3.14.2-bookworm, latest). Mặc định là:latestnếu bạn bỏ qua.DIGEST: Hash SHA256 của manifest image (ví dụ,
@sha256:abc123...). Đây là bất biến - tag có thể thay đổi, digest thì không.Hầu hết các lệnh pull trông như sau:
Trong hậu trường, lệnh này được mở rộng thành
docker.io/library/python:3.14.2-bookworm.Với registry riêng tư, bạn cần tham chiếu đầy đủ:
Dùng tham chiếu chính xác (tag hoặc digest cụ thể) giúp triển khai có thể tái lập. Pull
python:3.14.2-bookwormhôm nay và tháng sau, bạn sẽ nhận cùng một image. Pullpython:latesthai lần, khả năng cao là không.Docker Registry và nguồn gốc của image
Registry là nơi Docker lưu trữ và phân phối image - chúng là nguồn cho mọi lệnh
docker pullbạn chạy.Docker Hub là registry mặc định
Docker Hub là registry mặc định cho mọi lệnh
docker pulltrừ khi bạn chỉ định khác.Chạy
docker pull python:3.14.2-bookworm, Docker tự động chuyển thànhdocker.io/library/python:3.14.2-bookworm. Bạn không cần đăng nhập với image public - Docker Hub phục vụ ẩn danh, nhưng có giới hạn tần suất với người dùng chưa xác thực.Có hai loại image trên Docker Hub: Image chính thức và image cộng đồng.
Image chính thức đến từ các publisher đã xác minh và được Docker hoặc chính nhà cung cấp phần mềm duy trì. Chúng nằm dưới namespace
library(Docker ẩn khỏi bạn). Khi bạn pullpython,nginx, hoặcredis, bạn đang nhận Image chính thức tuân theo best practice của Docker về bảo mật và cập nhật định kỳ.Image cộng đồng là tất cả phần còn lại. Bất kỳ ai cũng có thể xuất bản image lên Docker Hub dưới tên người dùng hoặc tổ chức của họ. Pull
johndoe/python-custom, và bạn đang đặt niềm tin vào johndoe để duy trì image đó đúng cách. Một số image cộng đồng rất tốt và được bảo trì. Số khác không được cập nhật trong nhiều năm và chứa lỗ hổng đã biết.Sự tin cậy rất quan trọng ở đây. Image chính thức nhận bản vá bảo mật thường xuyên và có tài liệu rõ ràng. Với image cộng đồng, bạn tự chịu trách nhiệm xác minh ai duy trì và liệu chúng có an toàn để sử dụng hay không.
Registry riêng tư và tùy chỉnh
Phần lớn công ty không muốn image container của họ nằm trên Docker Hub công khai.
Registry riêng tư là lựa chọn phù hợp. Bạn quyết định ai có thể pull image, kiểm soát chính sách lưu trữ, và giữ mã nguồn sở hữu trí tuệ trong hạ tầng của mình. Điều này quan trọng cho tuân thủ, bảo mật, và quản lý truy cập giữa các nhóm.
Các giải pháp registry riêng tư phổ biến gồm:
Tất nhiên, tham chiếu image sẽ thay đổi khi bạn dùng registry tùy chỉnh. Thay vì
python:3.14.2-bookworm, bạn cần chỉ định đầy đủ đường dẫn:Hostname của registry đặt trước, sau đó là namespace của bạn (thường là tên nhóm hoặc dự án), rồi đến repository và tag. Docker sẽ không mặc định về Docker Hub khi thấy một hostname tùy chỉnh - nó đi thẳng đến registry riêng tư của bạn.
Xác thực, giới hạn tần suất và kiểm soát truy cập
Xác thực áp dụng cho cả push và pull image, và đặc biệt quan trọng khi bạn chạm ngưỡng giới hạn tần suất hoặc truy cập registry riêng tư.
Đăng nhập và quản lý thông tin xác thực
Bạn có thể dùng lệnh
docker loginđể xác thực với một registry:Lệnh sẽ yêu cầu tên người dùng và mật khẩu Docker Hub của bạn. Với registry riêng tư, chỉ cần chỉ định hostname:
Docker lưu thông tin xác thực cục bộ sau khi đăng nhập. Trên Linux, chúng nằm ở
~/.docker/config.json. Trên macOS, Docker sử dụng keychain của hệ thống để tăng bảo mật.Vấn đề là file cấu hình mặc định lưu thông tin xác thực bằng mã hóa base64, vốn không phải mã hóa bảo mật. Bất kỳ ai có quyền truy cập thư mục home của bạn đều có thể giải mã. Để giảm rủi ro, bạn có thể dùng credential helper - Docker hỗ trợ keychain gốc của hệ điều hành để lưu mật khẩu an toàn.
Một vài thực hành tốt để quản lý thông tin xác thực:
Sử dụng credential helper (docker-credential-osxkeychain, docker-credential-wincred)
Không bao giờ commit
config.jsonvào hệ thống quản lý phiên bảnƯu tiên dùng access token thay cho mật khẩu khi có thể
Xoay vòng thông tin xác thực định kỳ, đặc biệt với tài khoản dùng chung
Giới hạn tần suất của Docker Hub
Docker Hub giới hạn số lượng image bạn có thể pull trong một khoảng thời gian.
Người dùng ẩn danh (không đăng nhập) được 100 lần pull mỗi 6 giờ trên mỗi địa chỉ IP. Người dùng miễn phí đã xác thực được 200 lần mỗi 6 giờ. Gói trả phí có giới hạn cao hơn hoặc không giới hạn tùy bậc.
Những giới hạn này quan trọng khi bạn chạy pipeline CI/CD, pull image thường xuyên trong quá trình phát triển, hoặc làm việc trên hạ tầng dùng chung nơi nhiều người dùng chung một IP. Khi chạm giới hạn, các lần pull sẽ thất bại cho đến khi cửa sổ thời gian được đặt lại.
Bạn có thể kiểm tra trạng thái giới hạn hiện tại:
Một vài cách tăng giới hạn tần suất (đa số developer sẽ không gặp vấn đề này):
Cách đơn giản nhất là đăng nhập. Việc này một mình đã nhân đôi giới hạn của bạn.
Tùy chọn nâng cao khi pull image
Các tùy chọn nâng cao này mang lại độ chính xác và kiểm soát, đúng thứ bạn cần trong môi trường production.
Pull image theo digest
Digest là định danh bất biến dựa trên hash nội dung của image.
Tag có thể thay đổi. Ai đó push image mới với cùng tag, và đột nhiên python:3.14.2-bookworm trỏ đến nội dung khác ngày hôm qua. Digest thì không thể thay đổi - chúng là hash SHA256 của manifest image. Cùng một digest luôn đồng nghĩa với đúng image đó.
Pull theo digest như sau:
Điều này quan trọng nhất trong CI/CD và production. Bạn kiểm thử với một image cụ thể, bạn triển khai đúng image đó. Không bất ngờ, không trôi lệch giữa các môi trường. Nếu triển khai phụ thuộc vào phiên bản cụ thể, hãy dùng digest - không dùng tag.
Pull image đa kiến trúc
Image đa kiến trúc gói các phiên bản cho kiến trúc CPU khác nhau trong một tham chiếu image duy nhất.
Pull
python:3.14.2-bookworm, và Docker tự động chọn phiên bản phù hợp với hệ thống của bạn - amd64 cho máy x86, arm64 cho Apple Silicon hoặc máy chủ ARM. Registry sẽ phục vụ đúng kiến trúc mà không cần bạn làm gì.Nhưng đôi khi bạn cần kiến trúc cụ thể. Hãy dùng cờ
--platform:Điều này hữu ích khi bạn phát triển trên Apple Silicon nhưng cần kiểm thử phiên bản amd64 sẽ chạy trong production, hoặc khi bạn build image cho kiến trúc khác với máy build.
Pull nhiều tag
Cờ
--all-tagssẽ pull toàn bộ tag của một repository:Lệnh này sẽ tải mọi tag của Python - hàng tá phiên bản, biến thể và kiến trúc. Bạn sẽ có hàng gigabyte image.
Đừng dùng trừ khi thực sự cần. Băng thông tốn chi phí, dung lượng lưu trữ sẽ đầy nhanh, và bạn có lẽ không cần mọi phiên bản Python từng phát hành. Hãy pull những tag cụ thể bạn thực sự dùng.
Hủy một lệnh pull
Nhấn Ctrl+C hoặc CMD+C để hủy một lệnh pull đang diễn ra.
Docker dừng tải các layer mới nhưng giữ lại những layer đã hoàn tất. Lần sau khi bạn pull cùng image, nó sẽ tiếp tục từ chỗ dở thay vì bắt đầu lại.
Điều này hữu ích khi bạn lỡ pull sai image, khi pull mất quá lâu do kết nối chậm, hoặc khi bạn nhận ra hiện tại không cần image đó. Hủy, sửa lệnh và pull lại mà không lãng phí công sức đã làm.
Các cân nhắc về hiệu năng với docker pull
Mạng trong thực tế có các ràng buộc như giới hạn băng thông, proxy và kết nối chậm. Chúng có thể khiến việc pull image lâu hơn mức cần thiết, sau đây là những gì bạn có thể làm.
Tối ưu hiệu năng pull
Docker mặc định tải các layer của image đồng thời.
Thay vì tải từng layer một, Docker mở nhiều kết nối và tải nhiều layer cùng lúc. Điều này tăng tốc trên đường truyền nhanh, nhưng bạn sẽ khó nhận thấy khác biệt trên mạng chậm nơi băng thông là nút thắt.
Hai chiến lược phổ biến giúp hiệu quả hơn nữa:
Pull image qua proxy
Mạng doanh nghiệp định tuyến lưu lượng qua proxy vì lý do bảo mật, giám sát và kiểm soát truy cập.
Docker cần biết về các proxy này để pull image. Nếu không cấu hình proxy, lệnh pull sẽ lỗi timeout kết nối hoặc lỗi DNS vì Docker cố gắng kết nối trực tiếp đến registry thay vì qua proxy.
Bạn cấu hình proxy ở hai mức: Docker client và Docker daemon. Client (lệnh
docker) tự động dùng thiết lập proxy HTTP của hệ thống. Daemon cần cấu hình tường minh trong/etc/docker/daemon.jsonhoặc thông qua file service của systemd.Khắc phục sự cố pull thường gặp
Đây là danh sách kiểm tra thực tế khi lệnh pull thất bại - vì điều đó sẽ xảy ra, và bạn cần biết nên kiểm tra gì trước.
Lỗi thường gặp và cách chẩn đoán
Lỗi xác thực xuất hiện dưới dạng "unauthorized" hoặc "access denied".
Kiểm tra xem bạn đã đăng nhập với
docker loginchưa. Nếu rồi, thông tin xác thực có thể đã hết hạn hoặc sai. Đăng xuất bằngdocker logout, rồi đăng nhập lại. Với registry riêng, đảm bảo bạn dùng đúng hostname trong lệnh đăng nhập.Thiếu tag sẽ gây lỗi "manifest unknown" hoặc "not found".
Tag bạn cố pull không tồn tại. Hãy kiểm tra kỹ tên tag vì rất dễ gõ sai. Kiểm tra giao diện web của registry để xem các tag thật sự tồn tại. Lưu ý tag có thể bị xóa, nên thứ hoạt động hôm qua có thể hôm nay không còn.
Timeout mạng xảy ra khi Docker không thể kết nối đến registry.
Đầu tiên, kiểm tra kết nối internet của bạn. Sau đó xác minh bạn có thể kết nối trực tiếp đến registry - chạy
ping registry-1.docker.iohoặccurl -I <https://registry-1.docker.io>. Nếu bạn ở sau proxy, đảm bảo Docker biết về proxy đó. Nếu là registry riêng, kiểm tra rule firewall và kết nối VPN.Vấn đề quyền hạn xuất hiện dưới dạng lỗi "denied" ngay cả khi bạn đã xác thực.
Bạn đã đăng nhập, nhưng tài khoản của bạn không có quyền pull repository cụ thể này. Hãy liên hệ chủ repository hoặc quản trị viên registry để được cấp quyền. Với Docker Hub, thường là image ở chế độ private và bạn không nằm trong danh sách truy cập.
Sự cố DNS và phân giải mạng
Lỗi DNS khiến Docker không tìm được máy chủ registry.
Bạn sẽ thấy lỗi như "no such host" hoặc "temporary failure in name resolution." Thực tế là Docker không thể chuyển hostname của registry thành địa chỉ IP, nên không thể kết nối.
Để khắc phục, kiểm tra phân giải DNS bằng
nslookup registry-1.docker.iohoặcdig registry-1.docker.io. Nếu các lệnh này thất bại, máy chủ DNS của bạn không thể truy cập hoặc cấu hình sai. Hãy thử chuyển tạm thời sang DNS công cộng như 8.8.8.8 để xem có khắc phục không.Trong mạng doanh nghiệp, máy chủ DNS có thể chỉ phân giải hostname nội bộ. Hãy đảm bảo hostname của registry riêng nằm trong máy chủ DNS, hoặc thêm vào
/etc/hostsnhư một giải pháp tạm cho đến khi DNS được sửa.docker pull trong quy trình điều phối và cục bộ
Giờ đến phần thú vị - cách lệnh docker pull hoạt động trong các kịch bản bạn có thể gặp trong công việc hằng ngày.
Pull image trong Kubernetes
Kubernetes tự động pull image khi bạn triển khai pod.
Bạn định nghĩa một container trong pod spec với tham chiếu image, và Kubernetes sẽ xử lý việc pull cho bạn. Kubelet trên mỗi node kiểm tra image có sẵn cục bộ hay chưa. Nếu chưa, nó pull từ registry trước khi khởi động container.
Chính sách pull kiểm soát khi nào Kubernetes pull image:
Always: Luôn pull image, kể cả khi đã có cục bộIfNotPresent: Chỉ pull nếu image chưa có trên node (mặc định cho image có tag)Never: Không bao giờ pull, lỗi nếu image chưa có cục bộThiết lập chính sách trong pod spec với
imagePullPolicy. DùngAlwayscho tag:latesttrong phát triển để nhận cập nhật. DùngIfNotPresentcho các tag cụ thể trong production để tránh pull không cần thiết.imagePullSecrets cung cấp cho Kubernetes quyền truy cập registry riêng. Bạn có thể tạo một secret với thông tin xác thực registry, sau đó tham chiếu trong pod spec. Nếu không có, Kubernetes chỉ có thể pull image public.
Docker Compose và phát triển cục bộ
Compose tự động pull khi bạn khởi động ứng dụng đa dịch vụ.
Chạy
docker compose up, Compose kiểm tra image của mỗi service. Nếu một image thiếu, Compose sẽ pull trước khi khởi động container. Bạn không cần chạydocker pullthủ công cho từng service, vì Compose xử lý giúp bạn.Cách này rất phù hợp cho phát triển. Bạn định nghĩa service trong
docker-compose.yml, chạy một lệnh, và Compose sẽ pull mọi thứ bạn cần. Lầnupđầu mất lâu hơn do tải image, nhưng các lần sau sẽ tức thì nếu image không đổi.docker compose vs docker compose pull
Đây là hai lệnh khác nhau làm những việc khác nhau.
docker compose upkhởi động service của bạn. Nó tự động pull các image thiếu, nhưng chỉ khi chúng chưa có cục bộ. Nếu bạn đã cópython:3.14.2-bookwormtrên máy, Compose sẽ dùng luôn mà không kiểm tra cập nhật.docker compose pullsẽ pull tường minh tất cả image được định nghĩa trong file compose, bất kể chúng đã có cục bộ hay chưa. Lệnh này kiểm tra cập nhật từ registry và tải phiên bản mới nếu có.Khi nào bạn cần
docker compose pull:Bạn dùng tag
:latestvà muốn phiên bản mới nhất. Chạydocker compose pulltrước để cập nhật, rồidocker compose upđể khởi động với image mới.Bạn đang debug và nghi ngờ image cục bộ đã lỗi thời hoặc hỏng. Hãy pull bản mới với
docker compose pull, rồi khởi động lại.Bạn muốn preload image trước khi thực sự khởi động service. Chạy
docker compose pulltrong lúc triển khai để cache image, sau đódocker compose upsẽ chạy ngay mà không phải chờ tải.Khác biệt cốt lõi là up chỉ pull phần thiếu, còn pull sẽ cập nhật tất cả bất kể bạn đã có gì.
Kết luận
Lệnh
docker pulltrông đơn giản, nhưng có rất nhiều thứ diễn ra bên dưới và có nhiều điểm bạn có thể tinh chỉnh. Dưới đây là một số thực hành tốt cần ghi nhớ.Hãy dùng tag hoặc digest tường minh thay vì
:latest. Xác thực khi pull để tránh giới hạn tần suất. Lưu ý băng thông và lưu trữ khi pull image, đặc biệt trong pipeline CI/CD nơi bạn pull liên tục.Xem việc pull image như một phần của pipeline bảo mật. Mỗi lần pull đều có thể là điểm tấn công nếu bạn dùng nguồn không tin cậy hoặc image lỗi thời có lỗ hổng đã biết. Hãy xác minh nguồn, quét vấn đề, và giữ base image luôn cập nhật.
Docker registry và công cụ thay đổi thường xuyên. Theo kịp các cập nhật từ nhà cung cấp registry của bạn để tránh bất ngờ phá vỡ quy trình làm việc.
Khi bạn sẵn sàng nâng kỹ năng Docker và containerization lên mức chuyên nghiệp, hãy xem khóa Docker trung cấp của chúng tôi hoặc chọn toàn bộ lộ trình Containerization và Virtualization với Docker và Kubernetes.