도커 - 호스트 USB 또는 직렬 장치에 액세스할 수 있는 방법?
지난번에 확인했을 때 도커는 호스트 시리얼이나 USB 포트에 컨테이너 접근을 허용할 방법이 없었습니다.그렇게 할 수 있는 요령이 있습니까?
몇 가지 옵션이 있습니다.다를 .--device
사용하는 플래그는 사용하지 않고 USB 장치에 액세스하는 데 사용할 수 있습니다.--privileged
드:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
를 USB 합니다의 등과 할 수 가정합니다./dev/bus/usb
, 권한 모드와 volume 옵션을 사용하여 컨테이너에 마운트할 수 있습니다.예를 들어,
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
에서 알 수 --privileged
안전하지 않으므로 주의하여 처리해야 합니다.
의 할 수 .--device
모든 USB 장치에 액세스할 필요 없이 원하는 것을 달성할 수 있도록 플래그를 지정합니다.
를 들어,이 만 ,/dev/ttyUSB0
도커 컨테이너 내에서 액세스할 수 있으며 다음과 같은 작업을 수행할 수 있습니다.
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
--device
USB 장치가 분리/제거될 때까지 작동한 다음 작동을 중지합니다.cgroup 장치를 사용해야 합니다.도망갈 수 있게 해주세요.
당신은 그냥 사용할 수 있습니다.-v /dev:/dev
그러나 이는 원시 디스크 장치 등을 포함하여 호스트의 모든 장치를 컨테이너에 매핑하기 때문에 안전하지 않습니다.기본적으로 이를 통해 컨테이너는 호스트에서 루트를 얻을 수 있으며 일반적으로 원하는 것이 아닙니다.
방식을 사용하는 이 더 cgroups다로 합니다.
자세한 내용은 여기를 참조하십시오.--Privileged를 사용하지 않고 도커에서 USB 디바이스 액세스
붙여넣기가 조금 어렵지만 간단히 말하면 캐릭터 장치의 주요 번호를 가져와 cgroup으로 보내야 합니다.
188은 /dev/tty의 주요 숫자입니다.'ls -l'로 얻을 수 있는 USB*.사용자의 시스템과 사용자의 시스템이 다를 수 있습니다.
root@server:~# echo 'c 188:* rwm' > /sys/fs/cgroup/devices/docker/$A*/devices.allow
(A contains the docker containerID)
그런 다음 컨테이너를 다음과 같이 시작합니다.
docker run -v /dev/bus:/dev/bus:ro -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash debian:amd64
이렇게 하지 않으면 컨테이너가 시작된 후 새로 플러그를 꽂거나 재부팅하는 장치는 새 버스 ID를 얻게 되고 컨테이너에 접근할 수 없게 됩니다.
--특권 모드 없이 tty 장치에 안전하고 적절하게 액세스하는 방법
지침을 한 줄 한 줄 따라가면 모든 단계가 설명됩니다.
아이디어는 cgroup 규칙을 적절하게 구성하는 것입니다.우선 USB 장치의 cgroup 속성을 찾아보겠습니다.다음 명령 실행:
$ ls -l /dev/ | grep ttyUSB
crw-rw-rw- 1 root dialout 188, 0 Mar 1 18:23 ttyUSB0 #Example output
은 을 알 수 .188
저 같은 경우에는 그렇게 진행하겠습니다.
특정한 주 번호를 가진 다양한 디바이스에 액세스할 수 있도록 도커 이미지를 실행할 수 있습니다. 도커는 호스트 시스템에서 사용자에게 필요한 규칙을 추가합니다(이것은 분리 모드에서 도커를 실행하고 나중에 연결합니다).
docker run --device-cgroup-rule='c 188:* rmw' -itd --name my_container ubuntu
이제 USB 장치를 꽂거나 꽂을 때마다 실행되는 스크립트를 추가할 생각입니다.전달되는 논쟁에 대한 사용자 정의 규칙에 대한 설명입니다.ubuntu에서는 파일을 생성해야 합니다./etc/udev/rules.d/99-docker-tty.rules
수퍼유저로서(sudo):
ACTION=="add", SUBSYSTEM=="tty", RUN+="/usr/local/bin/docker_tty.sh 'added' '%E{DEVNAME}' '%M' '%m'"
ACTION=="remove", SUBSYSTEM=="tty", RUN+="/usr/local/bin/docker_tty.sh 'removed' '%E{DEVNAME}' '%M' '%m'"
이 으로 다음과 새합니다.합니다.마다 - tty마다 -add
또는 플러그가 꺼졌거나 -remove
제공된 스크립트를 실행하고 몇 가지 매개 변수를 전달합니다.더과 같은 을 사용하시면 됩니다udevadm info --name=<device name>
장치를 필터링할 수 있는 다른 파라미터를 찾습니다.여기서 제안하는 대로 규칙을 테스트할 수 있습니다.다음 규칙을 적용하려면:
root@~$ udevadm control --reload
에서 ./usr/local/bin/docker_tty.sh
또한 슈퍼유저(sudo)로서.이전에 만든 udev 규칙에서 실행되도록 설정된 것을 확인할 수 있습니다.
#!/usr/bin/env bash
echo "Usb event: $1 $2 $3 $4" >> /tmp/docker_tty.log
if [ ! -z "$(docker ps -qf name=env_dev)" ]
then
if [ "$1" == "added" ]
then
docker exec -u 0 env_dev mknod $2 c $3 $4
docker exec -u 0 env_dev chmod -R 777 $2
echo "Adding $2 to docker" >> /tmp/docker_tty.log
else
docker exec -u 0 env_dev rm $2
echo "Removing $2 from docker" >> /tmp/docker_tty.log
fi
fi
이 스크립트는 실행 중인 도커 컨테이너에 tty 장치를 만들거나 장치가 연결되었는지 또는 연결되었는지 여부에 따라 삭제합니다(Ubuntu 기계에서 발생하는 것과 유사 - 장치가 연결될 때마다 아래에서 볼 수 있습니다)./dev/
디렉토리(디렉토리).팁 :/tmp/docker_tty.log
호스트 시스템의 일부 디버그 출력에 대해서도 여기에 제안된 대로 debug bash 스크립트를 사용합니다.
스크립트를 실행할 수 있도록 하는 것을 잊지 마십시오.
root@~$ chmod +x /usr/local/bin/docker_tty.sh
가 합니다./dev/
시리(디렉토리):
docker exec -it my_container bash
하여 하지 않는 으로 연결된 에 대한 하고자 했습니다./dev/bus/usb
VM.boot2docker VM께 윈도우즈합니다와 때 이 설명합니다.
Windows(윈도우)에서 작업하는 경우에는 VirtualBox 관리자 내에서 Docker(도커)가 액세스할 장치에 대해 USB 규칙을 추가해야 합니다.이렇게 하려면 다음을 실행하여 VM을 중지할 수 있습니다.
host:~$ docker-machine stop default
VirtualBox Manager를 열고 필요에 따라 필터가 있는 USB 지원 기능을 추가합니다.
boot2docker VM을 시작합니다.
host:~$ docker-machine start default
USB 디바이스가 boot2docker VM에 연결되어 있으므로 해당 시스템에서 명령을 실행해야 합니다.VM으로 터미널을 열고 docker run 명령을 실행합니다.
host:~$ docker-machine ssh
docker@default:~$ docker run -it --privileged ubuntu bash
이와 같이 명령을 실행하면 이전에 연결된 USB 장치만 캡처됩니다.볼륨 플래그는 컨테이너가 시작된 후 연결된 장치에서 작동하도록 하려면 필요합니다.이 경우 다음을 사용할 수 있습니다.
docker@default:~$ docker run -it --privileged -v /dev:/dev ubuntu bash
참고로, 나는 사용해야만 했습니다./dev
/dev/bus/usb
e와 를 캡처하기 ./dev/sg2
. 다음과 같은 장치에 대해서도 동일한 내용이 적용된다고 가정할 수 밖에 없습니다./dev/ttyACM0
아니면/dev/ttyUSB0
.
도커 실행 명령은 Linux 호스트에서도 작동합니다.
도커 컨테이너가 이미 실행 중인 상태에서 연결할 수 있는 USB 장치에 동적으로 액세스하려면 /dev/video0에서 방금 연결된 USB 웹캠에 액세스하는 것과 같이 컨테이너를 시작할 때 cgroup 규칙을 추가할 수 있습니다.이 옵션은 --특권 컨테이너를 필요로 하지 않으며 특정 하드웨어 유형에만 액세스할 수 있습니다.
1단계
추가할 장치 유형의 장치 주 번호를 확인합니다.리눅스 커널 설명서에서 찾을 수 있습니다.또는 단말기에서 확인할 수도 있습니다.예를 들어 /dev/video0에 연결된 웹캠에 대한 장치 주 번호를 확인하려면 다음 작업을 수행할 수 있습니다.ls -la /dev/video0
는 다음과 결과는 다음과 같습니다.
crw-rw----+ 1 root video 81, 0 Jul 6 10:22 /dev/video0
여기서 첫 번째 번호(81)는 장치 주 번호입니다.일부 일반적인 장치 주요 번호:
- 81: usb 웹캠
- 188: usb와 직렬 변환기 연결
2단계
도커 컨테이너를 시작할 때 규칙 추가:
- 를 합니다.
--device-cgroup-rule='c major_number:* rmw'
- udev 가 usb 를 하여 도커 장치에 더 많은 수 정보에 대한 합니다.
-v /run/udev:/run/udev:ro
- /dev 를 .
-v /dev:/dev
마무리
따라서 모든 usb 웹캠과 serial2usb 장치를 도커 컨테이너에 추가하려면 다음 작업을 수행합니다.
docker run -it -v /dev:/dev --device-cgroup-rule='c 188:* rmw' --device-cgroup-rule='c 81:* rmw' ubuntu bash
또 다른 옵션은 udev를 조정하는 것인데, udev는 장치가 장착되는 방법과 어떤 권한을 가지고 있는지를 제어합니다.직렬 장치에 루트가 아닌 액세스를 허용하는 데 유용합니다.우에 가 있는 --device
선택이 최선의 방법입니다.만약 당신이 임시 사용 장치를 가지고 있다면, 제가 사용해왔던 것은 다음과 같습니다.
1. udev 규칙 설정
기본적으로 직렬 장치는 루트 사용자만 장치에 액세스할 수 있도록 마운트됩니다.루트가 아닌 사용자가 읽을 수 있도록 udev 규칙을 추가해야 합니다.
/etc/udev/rules.d/99-serial.rules라는 이름의 파일을 만듭니다.해당 파일에 다음 행을 추가합니다.
KERNEL=="ttyUSB[0-9]*",MODE="0666"
MODE="0666"은 모든 사용자에게 tty에 대한 읽기/쓰기 권한을 부여합니다.USB 장치.이 옵션은 가장 허용되는 옵션이며, 보안 요구 사항에 따라 추가로 제한할 수 있습니다.장치가 Linux 게이트웨이에 연결되었을 때 발생하는 작업을 제어하는 방법에 대해 자세히 알아보려면 udev에서 읽을 수 있습니다.
2. 호스트에서 컨테이너로 /dev 폴더 마운트
직렬 장치는 대개 덧없음(언제든지 연결 및 분리 가능)입니다.이 때문에 직접 장치나 /dev/serial 폴더에 마운트할 수 없습니다. 플러그를 뽑으면 사라질 수 있기 때문입니다.다시 플러그를 꽂고 장치가 다시 나타나도 기술적으로 장착된 파일과 다른 파일이므로 도커는 볼 수 없습니다.이러한 이유로 호스트에서 컨테이너로 전체 /dev 폴더를 마운트합니다.도커 실행 명령에 다음 volume 명령을 추가하여 이 작업을 수행할 수 있습니다.
-v /dev:/dev
장치가 영구적으로 연결되어 있는 경우 --device 옵션 또는 보다 특정 볼륨 마운트를 사용하는 것이 보안 측면에서 더 나은 옵션일 수 있습니다.
3. 권한 있는 모드로 컨테이너 실행
--device 옵션을 사용하지 않고 전체 /dev 폴더에 마운트된 경우 컨테이너 is 특권 모드를 실행해야 합니다(위에서 언급한 cgroup stuff를 확인하여 제거할 수 있는지 확인합니다).이렇게 하려면 도커 실행 명령에 다음을 추가할 수 있습니다.
--privileged
4. /dev/serial/byid 폴더에서 디바이스 액세스
장치를 꽂았다 뺐다 할 수 있는 경우 Linux에서 항상 동일한 ttyUSBxx 위치에 마운트된다는 보장이 있는 것은 아닙니다(특히 여러 장치가 있는 경우).다행히 Linux는 /dev/serial/byid 폴더에 있는 장치에 자동으로 심볼 링크를 만듭니다.이 폴더의 파일 이름은 항상 동일합니다.
이것은 간단한 개요입니다. 블로그 기사에서 좀 더 자세히 설명하고 있습니다.
우리는 특정 USB 장치를 도커 컨테이너에 묶기가 어렵습니다.보다시피, 권장되는 달성 방법은 다음과 같습니다.
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
모든 장치를 이 컨테이너에 바인딩합니다.안전하지 않습니다.모든 컨테이너는 모든 컨테이너를 작동할 수 있도록 허가를 받았습니다.
다른 방법은 장치를 devpath로 바인딩하는 것입니다.다음과 같이 보일 수:
docker run -t -i --privileged -v /dev/bus/usb/001/002:/dev/bus/usb/001/002 ubuntu bash
아니면--device
(better, no)privileged
):
docker run -t -i --device /dev/bus/usb/001/002 ubuntu bash
훨씬 안전합니다.그러나 실제로 특정 장치의 개발 경로가 무엇인지 알기가 어렵습니다.
저는 이 문제를 해결하기 위해 이 레포를 작성했습니다.
https://github.com/williamfzc/usb2container
이 서버를 배포한 후 HTTP 요청을 통해 연결된 모든 장치의 정보를 쉽게 얻을 수 있습니다.
curl 127.0.0.1:9410/api/device
다음을 가져옵니다.
{
"/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"
},
...
}
그리고 그것들을 당신의 용기에 묶습니다.예를 들어, 이 장치의 DEVNAME은/dev/bus/usb/001/120
:
docker run -t -i --device /dev/bus/usb/001/120 ubuntu bash
아마 도움이 될 겁니다.
또한 USB 장치를 사용하지 않고 공유할 수 있는 더 간단한 방법이 있습니다.--privileged
플래그를 지정합니다.
docker run ... --device=/dev/bus/usb --device=/dev/usb <container>
최신 버전의 도커를 사용하면 충분합니다.
docker run -ti --privileged ubuntu bash
예를 들어 /dev에 있는 모든 시스템 리소스에 액세스할 수 있습니다.
위의 답변에 추가하여 도커 내부에서 작동하는 외장 USB 장치(HDD, 플래시 드라이브)를 사용하고 권한 모드를 사용하지 않는 빠른 방법을 원하신다면 다음과 같이 하십시오.
호스트에서 디바이스의 devpath를 찾습니다.
sudo fdisk -l
목록에서 드라이브 용량을 쉽게 인식할 수 있습니다.이 경로를 복사합니다(다음 예의 경우)./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
이 개발 경로를 마운트(선호)/media
):
sudo mount <drive path> /media/<mount folder name>
그런 다음 이를 매개 변수로 사용하여 다음 작업을 수행할 수 있습니다.docker run
예:
docker run -it -v /media/<mount folder name>:/media/<mount folder name>
또는 볼륨 아래의 도커 작곡:
services:
whatevermyserviceis:
volumes:
- /media/<mount folder name>:/media/<mount folder name>
이제 컨테이너를 실행하고 입력하면 컨테이너 내부의 드라이브에 액세스할 수 있습니다./media/<mount folder name>
면책 사항:
- 이것은 아마도 웹캠과 같은 직렬 장치에서는 작동하지 않을 것입니다.USB 스토리지 드라이브에 대해서만 테스트를 해봤습니다.
- 장치를 정기적으로 다시 연결하고 분리해야 하는 경우 이 방법은 번거로울 뿐만 아니라 마운트 경로를 재설정하고 컨테이너를 다시 시작해야 작동할 수 있습니다.
- 도커 17.06 + 문서에 명시된 대로 사용했습니다.
언급URL : https://stackoverflow.com/questions/24225647/docker-a-way-to-give-access-to-a-host-usb-or-serial-device
'source' 카테고리의 다른 글
WordPress: 미디어 오류:형식이 지원되지 않거나 원본을 찾을 수 없습니다. (0) | 2023.10.04 |
---|---|
WooCommerce 카트 및 체크아웃에서 상품 가격 변경 (0) | 2023.10.04 |
팬더 데이터 프레임의 첫 몇 줄을 읽는 방법 (0) | 2023.10.04 |
'void*'를 해제해도 괜찮습니까? (0) | 2023.10.04 |
Linux에서 WaitForSingleObject 및 WaitForMultipleObjects equivalent? (0) | 2023.10.04 |