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


답변:


194

몇 가지 옵션이 있습니다. 모드를 --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불안 및 취급시주의해야한다.


4
-v-권한이 필요하지 않음은 이미 모든 장치에 대한 액세스를 의미합니다.
Art

12
Windows 도커 클라이언트에 이와 같은 메커니즘이 있습니까?
Pascal

이 솔루션을 사용하면 도커 컨테이너의 장치가 표시되지 않습니다 ... 여기 내 문제에 대한 세부 정보 stackoverflow.com/questions/37213812 도움을 주셔서 감사합니다! 감사.
kashesandr

1
Docker가 이미 실행 된 후 USB 장치가 연결되어 있으면 여전히 작동하지 않습니다.
Franklin Dattein

lsusb가 장치를 나열 할 수 있음에도 불구하고 / tty / USBX 아래에 장치를 매핑하지 않습니다.
Franklin Dattein

78

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

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

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

3
장치는 현재 심볼릭 링크가 될 수 없습니다. github.com/docker/docker/issues/13840
wligtenberg

6
--device플래그를 사용하여 /dev/<device>특히 Windows 또는 Mac 용 Docker Quickstart Terminal (VirtualBox Host)을 사용할 때 호스트 시스템의 관련 Android 장치를 어떻게 결정 합니까?
DanCat

1
장치 이름이 절대 변경되지 않으면 잘 작동합니다. 그러나 / dev / bus / usb 내에서 장치를 사용하는 동적을 사용하는 경우 장치를 연결하거나 분리 할 때 장치 이름이 변경되므로 작동하지 않습니다. 대신 위의 -v (볼륨) 솔루션이 필요합니다.
Brad Grissom

1
udev 규칙은 보장 할 수 @DanCat 그 정적 경로 장치 마운트
C. 리드

1
왜 하나의 USB 장치에 액세스하는 데 관심이 있습니까? USB 장치는 qnd 연결이 끊어졌으며 앱 런타임 중에 수행해야합니다. USB는 SATA가 아니며 무언가가 항상있을 것으로 기대할 수는 없습니다 ... 그리고 사람들이 단일 실행을 위해 도커를 통해 응용 프로그램을 시작하고 USB 장치가 분리되는 즉시 종료한다고 생각하지 않습니다. 나는 단일 실행 항아리가 아닌 서비스 유형 앱과 같은 것을 상상할 수 있습니다 ... 그러나 감사합니다. 그것은 매우 제한된 시나리오가 적합한 일부를 도울 수 있습니다
Arturas M

17

--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를 가져오고 컨테이너에서 액세스 할 수 없습니다.


7
이것을 -1 한 사람들에게, 개선하고 싶은 것을 도와주고 말하십시오. 이 페이지를 작성하여 문제를 겪은 다른 사람들을 돕기 위해 작성했습니다. 나는 다시 공유하고
Marc Merlin

내 대답을 읽으면 볼륨 '-v / dev : / dev'를 추가하면 동적으로 연결된 장치에 액세스 할 수 있습니다.
rrpilot

5
rrpilot : -v / dev : / dev는 / dev / sda와 컨테이너의 루트 사용자에게 노출시키고 싶지 않은 다른 것들을 포함하여 모든 / dev를 제공합니다. 즉, 솔루션이 작동하지만 안전하지 않습니다. 내 문제가 해결됩니다. 나는 그것을 지적하기 위해 대답을 편집 할 것입니다.
마크 멀린

1
주요 번호를 얻는 방법을 보여주고 189교체해야 할 것을 명확히하면 더 나은 답을 얻을 수 있습니다. 보낼 내용에 대한 설명은 devices.allow여기에서 찾을 수 있습니다 : kernel.org/doc/Documentation/cgroup-v1/devices.txt
Craig Younkins

1
이 약간 간단하게 도커의 새로운 틱 기능이있다 : "--device - cgroup의 규칙"( docs.docker.com/engine/reference/commandline/create/... )
tianon

14

나는 캡처되지 않은 동적으로 연결된 장치에 대한 지원 /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 호스트에서도 작동합니다.


대신 / dev : / dev를 마운트하는 것이 좋습니다. 이는 다른 장치를 캡처하는 측면에서 더 많은 유연성을 제공하고 동적 요소를 지원합니다.
kotakotakota

또한 호스트 시스템의 보안 및 격리를 손상시킵니다.
Exadra37

@ Exadra37 그것은 ... 응용 프로그램에서 중요하다면 이것을 사용해서는 안됩니다. 그러나 관심을 가지지 않고 격리를 위해 도커를 사용하지 않는 일부 응용 프로그램이 있습니다. 필자의 경우 Windows에서 패키지 Linux 응용 프로그램을 실행할 수 있습니다.
rrpilot

3

또 다른 옵션은 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 폴더에있는 장치에 자동으로 심볼릭 링크를 만듭니다. 이 폴더의 파일 이름은 항상 동일합니다.

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


2

특정 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

아마 도움이 될 것입니다.


0

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

docker run -ti --privileged ubuntu bash

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


2
priviledged는 보안에도 사용할 수있는 끔찍한 옵션입니다.
Marc Merlin

2
아두 이노 관련 물건 같은 물건을 프로그래밍을 사용하는 경우이 솔루션은 좋은
호세 카브레라 주니

0

고정 모드를 사용 하지 않고 도커 내부에서 작동하는 외부 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

이 devpath를 마운트하십시오 ( /media).

sudo mount <drive path> /media/<mount folder name>

그런 다음 이것을 원하는 매개 변수로 사용할 수 있습니다 docker run.

docker run -it -v /media/<mount folder name>:/media/<mount folder name>

또는 docker에서 볼륨 아래로 작성하십시오.

services:
  whatevermyserviceis:
    volumes:
      - /media/<mount folder name>:/media/<mount folder name>

이제 컨테이너를 실행하고 들어가면 컨테이너 내부의 드라이브에 액세스 할 수 있어야합니다. /media/<mount folder name>

부인 성명:

  1. 웹캠 등의 직렬 장치에서는 작동하지 않을 수 있습니다. USB 저장 장치 드라이브에 대해서만 테스트했습니다.
  2. 장치를 정기적으로 다시 연결하고 연결을 끊어야하는 경우이 방법은 성가 시며 마운트 경로를 재설정하고 컨테이너를 다시 시작하지 않으면 작동하지 않습니다.
  3. 문서에 처방 된대로 docker 17.06 +를 사용했습니다.

0

도커 컨테이너가 이미 실행중인 동안 연결할 수있는 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'액세스하려는 모든 유형의 장치에 대한 규칙 추가
  • 도커 컨테이너가 USB 장치에 대한 자세한 정보를 얻을 수 있도록 udev 정보에 대한 액세스를 추가하십시오. -v /run/udev:/run/udev:ro
  • / dev 볼륨을 도커 컨테이너에 매핑하십시오. -v /dev:/dev

마무리

따라서 모든 USB 웹캠 및 serial2usb 장치를 docker 컨테이너에 추가하려면 다음을 수행하십시오.

docker run -it -v /dev:/dev --device-cgroup-rule='c 188:* rmw' --device-cgroup-rule='c 81:* rmw' ubuntu bash
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.