[docker] Docker-호스트 USB 또는 직렬 장치에 액세스하는 방법은 무엇입니까?



답변

몇 가지 옵션이 있습니다. 모드를 --device사용하지 않고 USB 장치에 액세스하는 데 사용할 수 있는 플래그를 사용할 수 있습니다 --privileged.

docker run -t -i --device=/dev/ttyUSB0 ubuntu bash

또는의 호스트에서 작동하는 드라이버 등으로 USB 장치를 사용할 수 있다고 가정하면 권한 모드볼륨 옵션을/dev/bus/usb 사용하여 컨테이너에이 장치를 마운트 할 수 있습니다 . 예를 들면 다음과 같습니다.

docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash

이름에서 알 수 있듯이, 참고 --privileged불안 및 취급시주의해야한다.


답변

Docker의 현재 버전에서는 --device플래그를 사용하여 모든 USB 장치에 액세스하지 않고도 원하는 것을 얻을 수 있습니다.

예를 들어 /dev/ttyUSB0Docker 컨테이너 내 에서만 액세스 할 수 있도록 하려면 다음과 같이하십시오.

docker run -t -i --device=/dev/ttyUSB0 ubuntu bash


답변

--deviceUSB 장치의 플러그를 뽑았다가 다시 꽂아서 작동을 멈출 때까지 작동합니다. cgroup 장치 를 사용해야 합니다 .
그냥 사용할 수는 -v /dev:/dev있지만 원시 디스크 장치 등을 포함하여 호스트의 모든 장치를 컨테이너에 매핑하므로 안전하지 않습니다. 기본적으로 이것은 컨테이너가 호스트에서 루트를 얻도록 허용합니다. 일반적으로 원하는 것은 아닙니다.
cgroups 접근 방식을 사용하는 것이 그 점에서 더 좋으며 컨테이너가 시작된 후에 추가되는 장치에서 작동합니다.

여기에서 자세한 내용을 참조하십시오 : 액세스 USB 장치에서 고정 표시기 –privileged 사용하지 않고

붙여 넣기가 약간 어렵지만 간단히 말해서 캐릭터 장치의 주요 번호를 가져 와서 cgroup에 보내야합니다.

189는 ‘ls -l’로 얻을 수있는 / dev / ttyUSB *의 주요 수입니다. 시스템과 내 시스템이 다를 수 있습니다.

root@server:~# echo 'c 189:* 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를 가져오고 컨테이너에서 액세스 할 수 없습니다.


답변

나는 캡처되지 않은 동적으로 연결된 장치에 대한 지원 /dev/bus/usb과 boot2docker VM과 함께 Windows 호스트를 사용할 때이 작업을 수행하는 방법을 포함하기 위해 이미 주어진 답변을 확장하고 싶었습니다 .

Windows로 작업하는 경우 Docker가 VirtualBox 관리자 내에서 액세스하려는 장치에 대한 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같은 장치를 캡처하는 경우에 /dev/sg2. 난 단지 같은 같은 장치에 대해 사실이 될 것이라고 가정 할 수있다 /dev/ttyACM0/dev/ttyUSB0.

docker run 명령은 Linux 호스트에서도 작동합니다.


답변

또 다른 옵션은 udev를 조정하여 장치를 마운트하는 방법과 권한을 제어하는 ​​것입니다. 직렬 장치에 루트가 아닌 액세스를 허용하는 데 유용합니다. 영구적으로 장치를 연결 한 경우 --device옵션이 가장 좋습니다. 임시 장치가있는 경우 다음과 같이 사용합니다.

1. udev 규칙 설정

기본적으로 직렬 장치는 루트 사용자 만 장치에 액세스 할 수 있도록 마운트됩니다. 루트가 아닌 사용자가 읽을 수 있도록 udev 규칙을 추가해야합니다.

/etc/udev/rules.d/99-serial.rules라는 파일을 작성하십시오. 해당 파일에 다음 줄을 추가하십시오.

KERNEL=="ttyUSB[0-9]*",MODE="0666"

MODE = “0666”은 모든 사용자에게 ttyUSB 장치에 대한 읽기 / 쓰기 (실행은 아님) 권한을 부여합니다. 가장 허용 가능한 옵션이며 보안 요구 사항에 따라 더 제한 할 수 있습니다. 장치가 Linux 게이트웨이에 연결될 때 발생하는 상황을 제어하는 ​​방법에 대한 자세한 내용은 udev를 참조하십시오.

2. 호스트에서 컨테이너로 / dev 폴더에 마운트

직렬 장치는 종종 일시적입니다 (언제든지 연결하거나 분리 할 수 ​​있음). 이로 인해 직접 장치 또는 / dev / serial 폴더에 마운트 할 수 없습니다. 플러그를 뽑으면 사라질 수 있기 때문입니다. 다시 연결해도 장치가 다시 표시 되더라도 기술적으로 마운트 된 파일과 다른 파일이므로 Docker에서 볼 수 없습니다. 이러한 이유로 전체 / dev 폴더를 호스트에서 컨테이너로 마운트합니다. Docker run 명령에 다음 volume 명령을 추가하여이 작업을 수행 할 수 있습니다.

-v /dev:/dev

장치가 영구적으로 연결된 경우 –device 옵션 또는보다 구체적인 볼륨 마운트를 사용하는 것이 보안 측면에서 더 나은 옵션 일 수 있습니다.

3. 권한 모드에서 컨테이너를 실행

–device 옵션을 사용하지 않고 전체 / dev 폴더에 마운트 한 경우 컨테이너 권한 모드를 실행해야합니다 (위에서 언급 한 cgroup 항목을 확인하여 제거 할 수 있는지 확인합니다). ). Docker run 명령에 다음을 추가하여이를 수행 할 수 있습니다.

--privileged

4. / dev / serial / by-id 폴더에서 장치에 액세스

장치를 연결 및 분리 할 수있는 경우 Linux는 항상 동일한 ttyUSBxxx 위치 (특히 여러 장치가있는 경우)에 마운트되도록 보장하지 않습니다. 다행히 리눅스는 / dev / serial / by-id 폴더에있는 장치에 자동으로 심볼릭 링크를 만듭니다. 이 폴더의 파일 이름은 항상 동일합니다.

이것은 빠른 요약 입니다. 자세한 내용을 다루는 블로그 기사 가 있습니다.


답변

특정 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(더 나은, 아니오 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

아마 도움이 될 것입니다.


답변

최신 버전의 도커로 충분합니다.

docker run -ti --privileged ubuntu bash

모든 시스템 리소스에 액세스 할 수 있습니다 (예 : / dev)