Lần trước tôi đã kiểm tra, Docker không có bất kỳ phương tiện nào để cấp quyền truy cập container vào cổng nối tiếp hoặc cổng USB . Có một mẹo cho phép làm điều đó?
Lần trước tôi đã kiểm tra, Docker không có bất kỳ phương tiện nào để cấp quyền truy cập container vào cổng nối tiếp hoặc cổng USB . Có một mẹo cho phép làm điều đó?
Câu trả lời:
Có một vài sự lựa chon. Bạn có thể sử dụng --device
cờ sử dụng có thể sử dụng để truy cập các thiết bị USB mà không cần --privileged
chế độ:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
Ngoài ra, giả sử thiết bị USB của bạn khả dụng với trình điều khiển hoạt động, v.v. trên máy chủ lưu trữ /dev/bus/usb
, bạn có thể gắn thiết bị này vào bộ chứa bằng chế độ đặc quyền và tùy chọn âm lượng . Ví dụ:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Lưu ý rằng như tên của nó, --privileged
là không an toàn và cần được xử lý cẩn thận.
Với các phiên bản hiện tại của Docker, bạn có thể sử dụng --device
cờ để đạt được những gì bạn muốn mà không cần phải cấp quyền truy cập cho tất cả các thiết bị USB.
Ví dụ: nếu bạn chỉ muốn /dev/ttyUSB0
truy cập trong bộ chứa Docker của mình, bạn có thể làm một cái gì đó như:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
--device
cờ, làm cách nào để xác định /dev/<device>
thiết bị Android được liên kết trên máy chủ, đặc biệt là khi sử dụng Docker Quickstart Terminal (VirtualBox Host) cho Windows hoặc Mac?
--device
hoạt động cho đến khi thiết bị USB của bạn được rút / cắm lại và sau đó thiết bị ngừng hoạt động. Bạn phải sử dụng thiết bị cgroup. Hãy đi xung quanh nó.
Bạn chỉ có thể sử dụng -v /dev:/dev
nhưng điều đó không an toàn vì nó ánh xạ tất cả các thiết bị từ máy chủ của bạn vào trong thùng chứa, bao gồm cả các thiết bị đĩa thô, v.v. Về cơ bản, điều này cho phép container chứa root trên máy chủ, thường không phải là những gì bạn muốn.
Sử dụng phương pháp tiếp cận nhóm là tốt hơn trong khía cạnh đó và hoạt động trên các thiết bị được thêm vào sau khi container được bắt đầu.
Xem chi tiết tại đây: Truy cập các thiết bị USB trong Docker mà không cần sử dụng - đặc quyền
Hơi khó dán một chút, nhưng tóm lại, bạn cần lấy số chính cho thiết bị nhân vật của mình và gửi nó đến cgroup:
189 là số lượng lớn / dev / ttyUSB *, mà bạn có thể nhận được với 'ls -l'. Nó có thể khác trên hệ thống của bạn so với của tôi:
root@server:~# echo 'c 189:* rwm' > /sys/fs/cgroup/devices/docker/$A*/devices.allow
(A contains the docker containerID)
Sau đó bắt đầu container của bạn như thế này:
docker run -v /dev/bus:/dev/bus:ro -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash debian:amd64
không làm điều này, bất kỳ thiết bị mới được cắm hoặc khởi động lại sau khi container bắt đầu, sẽ nhận được ID bus mới và sẽ không được phép truy cập vào container.
189
phải được thay thế. Có devices.allow
thể tìm thấy mô tả về những gì cần gửi tại đây: kernel.org/doc/Documentation/cgroup-v1/devices.txt
Tôi muốn mở rộng các câu trả lời đã được đưa ra để bao gồm hỗ trợ cho các thiết bị được kết nối động không được ghi lại /dev/bus/usb
và cách để hoạt động này khi sử dụng máy chủ Windows cùng với VM boot2docker.
Nếu bạn đang làm việc với Windows, bạn sẽ cần thêm bất kỳ quy tắc USB nào cho các thiết bị mà bạn muốn Docker truy cập trong trình quản lý VirtualBox. Để làm điều này, bạn có thể dừng VM bằng cách chạy:
host:~$ docker-machine stop default
Mở Trình quản lý VirtualBox và thêm hỗ trợ USB với các bộ lọc theo yêu cầu.
Khởi động VM boot2docker:
host:~$ docker-machine start default
Vì các thiết bị USB được kết nối với VM boot2docker, nên các lệnh cần được chạy từ máy đó. Mở một thiết bị đầu cuối với VM và chạy lệnh chạy docker:
host:~$ docker-machine ssh
docker@default:~$ docker run -it --privileged ubuntu bash
Lưu ý, khi lệnh được chạy như thế này, thì chỉ các thiết bị USB được kết nối trước đó mới được chụp. Cờ âm lượng chỉ được yêu cầu nếu bạn muốn nó hoạt động với các thiết bị được kết nối sau khi container được khởi động. Trong trường hợp đó, bạn có thể sử dụng:
docker@default:~$ docker run -it --privileged -v /dev:/dev ubuntu bash
Lưu ý, tôi đã phải sử dụng /dev
thay vì /dev/bus/usb
trong một số trường hợp để chụp một thiết bị như thế nào /dev/sg2
. Tôi chỉ có thể giả sử điều tương tự sẽ đúng với các thiết bị như /dev/ttyACM0
hoặc /dev/ttyUSB0
.
Các lệnh chạy docker cũng sẽ hoạt động với máy chủ Linux.
Một tùy chọn khác là điều chỉnh udev, điều khiển cách các thiết bị được gắn kết và với những đặc quyền nào. Hữu ích để cho phép truy cập không root vào các thiết bị nối tiếp. Nếu bạn có thiết bị gắn vĩnh viễn, --device
tùy chọn là cách tốt nhất để đi. Nếu bạn có thiết bị phù du, đây là những gì tôi đã sử dụng:
Theo mặc định, các thiết bị nối tiếp được gắn để chỉ người dùng root mới có thể truy cập thiết bị. Chúng ta cần thêm một quy tắc udev để làm cho chúng dễ đọc bởi những người dùng không phải root.
Tạo một tệp có tên /etc/udev/rules.d/99-serial.rules. Thêm dòng sau vào tập tin đó:
KERNEL=="ttyUSB[0-9]*",MODE="0666"
MODE = "0666" sẽ cung cấp cho tất cả người dùng quyền đọc / ghi (nhưng không thực thi) cho các thiết bị ttyUSB của bạn. Đây là tùy chọn cho phép nhất và bạn có thể muốn hạn chế điều này hơn nữa tùy thuộc vào yêu cầu bảo mật của bạn. Bạn có thể đọc trên udev để tìm hiểu thêm về cách kiểm soát những gì xảy ra khi thiết bị được cắm vào cổng Linux.
Các thiết bị nối tiếp thường là phù du (có thể cắm và rút phích cắm bất cứ lúc nào). Vì lý do này, chúng tôi không thể gắn vào thiết bị trực tiếp hoặc thậm chí thư mục / dev / serial, bởi vì những thứ đó có thể biến mất khi mọi thứ được rút ra. Ngay cả khi bạn cắm lại và thiết bị xuất hiện trở lại, về mặt kỹ thuật, đây là một tệp khác với tệp được gắn vào, vì vậy Docker sẽ không nhìn thấy nó. Vì lý do này, chúng tôi gắn toàn bộ thư mục / dev từ máy chủ vào thùng chứa. Bạn có thể làm điều này bằng cách thêm lệnh âm lượng sau vào lệnh chạy Docker của bạn:
-v /dev:/dev
Nếu thiết bị của bạn được gắn vĩnh viễn, thì sử dụng tùy chọn --device hoặc giá đỡ âm lượng cụ thể hơn có thể là một tùy chọn tốt hơn từ góc độ bảo mật.
Nếu bạn không sử dụng tùy chọn --device và được gắn trong toàn bộ thư mục / dev, bạn sẽ được yêu cầu chạy container ở chế độ đặc quyền (Tôi sẽ kiểm tra nội dung cgroup được đề cập ở trên để xem liệu có thể xóa được không ). Bạn có thể làm điều này bằng cách thêm phần sau vào lệnh chạy Docker của bạn:
--privileged
Nếu thiết bị của bạn có thể được cắm và rút phích cắm, Linux không đảm bảo thiết bị sẽ luôn được gắn tại cùng một vị trí ttyUSBxxx (đặc biệt nếu bạn có nhiều thiết bị). May mắn thay, Linux sẽ tự động tạo một liên kết tượng trưng đến thiết bị trong thư mục / dev / serial / by-id. Các tập tin trong thư mục này sẽ luôn được đặt tên giống nhau.
Đây là tóm tắt nhanh, tôi có một bài viết blog đi sâu vào chi tiết hơn.
Thật khó để chúng tôi liên kết một thiết bị USB cụ thể với hộp chứa docker cũng cụ thể. Như bạn có thể thấy, cách được đề xuất để đạt được là:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Nó sẽ liên kết tất cả các thiết bị với container này. Nó không an toàn. Mỗi container được cấp để vận hành tất cả chúng.
Một cách khác là ràng buộc các thiết bị bằng devpath. Nó có thể trông giống như:
docker run -t -i --privileged -v /dev/bus/usb/001/002:/dev/bus/usb/001/002 ubuntu bash
hoặc --device
(tốt hơn, không privileged
):
docker run -t -i --device /dev/bus/usb/001/002 ubuntu bash
An toàn hơn nhiều. Nhưng thực sự rất khó để biết sự sai lệch của một thiết bị cụ thể là gì.
Tôi đã viết repo này để giải quyết vấn đề này.
https://github.com/williamfzc/usb2container
Sau khi triển khai máy chủ này, bạn có thể dễ dàng lấy tất cả thông tin của các thiết bị được kết nối thông qua yêu cầu HTTP:
curl 127.0.0.1:9410/api/device
và lấy:
{
"/devices/pci0000:00/0000:00:14.0/usb1/1-13": {
"ACTION": "add",
"DEVPATH": "/devices/pci0000:00/0000:00:14.0/usb1/1-13",
"DEVTYPE": "usb_device",
"DRIVER": "usb",
"ID_BUS": "usb",
"ID_FOR_SEAT": "xxxxx",
"ID_MODEL": "xxxxx",
"ID_MODEL_ID": "xxxxx",
"ID_PATH": "xxxxx",
"ID_PATH_TAG": "xxxxx",
"ID_REVISION": "xxxxx",
"ID_SERIAL": "xxxxx",
"ID_SERIAL_SHORT": "xxxxx",
"ID_USB_INTERFACES": "xxxxx",
"ID_VENDOR": "xxxxx",
"ID_VENDOR_ENC": "xxxxx",
"ID_VENDOR_FROM_DATABASE": "",
"ID_VENDOR_ID": "xxxxx",
"INTERFACE": "",
"MAJOR": "189",
"MINOR": "119",
"MODALIAS": "",
"PRODUCT": "xxxxx",
"SEQNUM": "xxxxx",
"SUBSYSTEM": "usb",
"TAGS": "",
"TYPE": "0/0/0",
"USEC_INITIALIZED": "xxxxx",
"adb_user": "",
"_empty": false,
"DEVNAME": "/dev/bus/usb/001/120",
"BUSNUM": "001",
"DEVNUM": "120",
"ID_MODEL_ENC": "xxxxx"
},
...
}
và ràng buộc chúng vào thùng chứa của bạn. Ví dụ: bạn có thể thấy DEVNAME của thiết bị này là /dev/bus/usb/001/120
:
docker run -t -i --device /dev/bus/usb/001/120 ubuntu bash
Có lẽ nó sẽ giúp.
Với các phiên bản mới nhất của docker, điều này là đủ:
docker run -ti --privileged ubuntu bash
Nó sẽ cấp quyền truy cập vào tất cả các tài nguyên hệ thống (ví dụ: in / dev)
Thêm vào các câu trả lời ở trên, đối với những người muốn sử dụng nhanh thiết bị USB ngoài (ổ cứng, ổ đĩa flash) hoạt động bên trong docker và không sử dụng chế độ riêng tư:
Tìm đường dẫn đến thiết bị của bạn trên máy chủ:
sudo fdisk -l
Bạn có thể nhận ra ổ đĩa của mình bằng dung lượng khá dễ dàng từ danh sách. Sao chép đường dẫn này (ví dụ như sau /dev/sda2
).
Disque /dev/sda2 : 554,5 Go, 57151488 octets, 111624 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Mount devpath này (thích hợp hơn /media
):
sudo mount <drive path> /media/<mount folder name>
Sau đó, bạn có thể sử dụng điều này như một thông số để docker run
thích:
docker run -it -v /media/<mount folder name>:/media/<mount folder name>
hoặc trong docker soạn theo khối lượng:
services:
whatevermyserviceis:
volumes:
- /media/<mount folder name>:/media/<mount folder name>
Và bây giờ khi bạn chạy và nhập container của mình, bạn sẽ có thể truy cập ổ đĩa bên trong container tại /media/<mount folder name>
TUYÊN BỐ TỪ CHỐI:
Nếu bạn muốn truy cập động các thiết bị USB có thể được cắm trong khi bộ chứa docker đang chạy, ví dụ: truy cập webcam usb được đính kèm tại / dev / video0, bạn có thể thêm quy tắc nhóm khi khởi động bộ chứa. Tùy chọn này không cần một thùng chứa - đặc quyền và chỉ cho phép truy cập vào các loại phần cứng cụ thể.
Kiểm tra số lượng thiết bị chính của loại thiết bị bạn muốn thêm. Bạn có thể tra cứu nó trong tài liệu kernel linux . Hoặc bạn có thể kiểm tra nó cho thiết bị của bạn. Ví dụ: để kiểm tra số chính của thiết bị cho webcam được kết nối với / dev / video0, bạn có thể thực hiện a ls -la /dev/video0
. Điều này dẫn đến một cái gì đó như:
crw-rw----+ 1 root video 81, 0 Jul 6 10:22 /dev/video0
Trong đó số đầu tiên (81) là số chính của thiết bị. Một số số chính của thiết bị phổ biến:
Thêm quy tắc khi bạn khởi động container docker:
--device-cgroup-rule='c major_number:* rmw'
quy tắc cho mọi loại thiết bị bạn muốn truy cập-v /run/udev:/run/udev:ro
-v /dev:/dev
Vì vậy, để thêm tất cả webcam webcam và thiết bị serial2usb vào thùng chứa docker của bạn, hãy làm:
docker run -it -v /dev:/dev --device-cgroup-rule='c 188:* rmw' --device-cgroup-rule='c 81:* rmw' ubuntu bash