Tại sao lỗi này xảy ra
Khi bạn nhấn Enter cho lệnh docker run --gpus all, thay vì một container đang chạy, bạn lại nhận được một thông báo lỗi khó chịu. Điều này về cơ bản có nghĩa là Docker đang tìm kiếm một driver hỗ trợ GPU nhưng không tìm thấy. Mặc định, Docker sử dụng runtime runc tiêu chuẩn. Mặc dù runc rất tuyệt vời trong việc cô lập CPU và RAM, nhưng nó không biết cách giao tiếp với phần cứng NVIDIA.
Để khắc phục điều này, bạn cần một "thông dịch viên" có tên là NVIDIA Container Toolkit. Không có nó, Docker thậm chí không hiểu cờ --gpus có ý nghĩa gì.
Bước 1: Kiểm tra Driver trên máy chủ
Mọi thứ bắt đầu với các driver cơ bản. Nếu hệ điều hành máy chủ (host OS) không nhìn thấy GPU, Docker chắc chắn cũng sẽ không thấy. Hãy mở terminal và chạy lệnh:
nvidia-smi
Bạn sẽ thấy một bảng trạng thái hiển thị phiên bản driver (ví dụ: 535.129.03) và model GPU của bạn, như RTX 3080 hoặc A100. Nếu bạn thấy lỗi "command not found" hoặc lỗi giao tiếp, hãy dừng lại ở đây. Bạn phải cài đặt driver độc quyền của NVIDIA trước khi đụng đến Docker.
Bước 2: Cài đặt NVIDIA Container Toolkit
Hầu hết các thiết lập Linux hiện đại (Ubuntu 22.04, Debian hoặc CentOS) đều tuân theo một quy trình tương tự. Chúng ta cần thêm kho lưu trữ gói chính thức của NVIDIA để hệ thống biết nơi tải xuống bộ công cụ.
Đầu tiên, hãy thiết lập khóa GPG và danh sách kho lưu trữ:
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
Bây giờ, hãy cập nhật danh sách gói và cài đặt bộ công cụ. Đây là một bản tải xuống nhỏ, thường dưới 20MB.
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
Bước 3: Đăng ký NVIDIA Runtime
Chỉ cài đặt bộ công cụ trên ổ cứng là chưa đủ. Bạn phải yêu cầu Docker thực sự sử dụng nó. NVIDIA cung cấp một tiện ích tiện lợi giúp tự động hóa việc cấu hình tệp daemon.json của bạn.
sudo nvidia-ctk runtime configure --runtime=docker
Lệnh này sẽ cập nhật /etc/docker/daemon.json. Nó thêm một runtime mới tên là "nvidia" và trỏ nó đến tệp thực thi của bộ công cụ. Nếu tò mò, bạn có thể xem tệp bằng lệnh cat /etc/docker/daemon.json để thấy khối cấu hình mới.
Bước 4: Khởi động lại và Xác nhận
Docker chỉ đọc cấu hình khi nó khởi động. Hãy khởi động lại dịch vụ để áp dụng các thay đổi:
sudo systemctl restart docker
Bây giờ là lúc kiểm tra kết quả. Hãy chạy một container CUDA nhỏ để xem nó có thể truy cập GPU hay không. Chúng ta sẽ sử dụng image chính thức của NVIDIA để chạy nvidia-smi từ bên trong container.
docker run --rm --gpus all nvidia/cuda:12.0-base-ubuntu22.04 nvidia-smi
Thành công là khi bảng thông số GPU quen thuộc xuất hiện trong terminal của bạn. Nếu bạn thấy nó, nghĩa là kết nối đã được thiết lập.
Khắc phục sự cố với Docker Compose
Nếu bạn đang sử dụng Docker Compose và vẫn gặp lỗi, tệp YAML của bạn có khả năng là nguyên nhân. Compose yêu cầu một khối deploy cụ thể để dự phòng phần cứng. Đảm bảo docker-compose.yml của bạn sử dụng phiên bản 3.8 trở lên.
services:
gpu-worker:
image: nvidia/cuda:12.0-base-ubuntu22.04
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
Mẹo chuyên nghiệp để duy trì sự ổn định
- Người dùng WSL2: Đừng cài đặt driver NVIDIA bên trong bản phân phối Ubuntu WSL của bạn. Hãy cài đặt driver Game Ready hoặc Studio mới nhất trên Windows. Docker Desktop sẽ tự động xử lý phần còn lại.
- Cập nhật Kernel: Đôi khi bản cập nhật kernel Linux làm hỏng driver NVIDIA. Nếu
nvidia-smingừng hoạt động trên máy chủ, Docker cũng sẽ thất bại. Một lệnhsudo apt install --reinstall nvidia-driver-<version>đơn giản thường sẽ khắc phục được vấn đề. - Tính kiên định (Persistence): Trên các máy chủ production, hãy sử dụng
sudo nvidia-smi -pm 1để bật chế độ persistence. Điều này giúp driver luôn được tải và giảm độ trễ khi khởi động container khoảng 100-200ms.

