前回チェックしたとき、DockerにはコンテナーにホストのシリアルポートまたはUSBポートへのアクセスを許可する手段がありませんでした。それを可能にするトリックはありますか?
前回チェックしたとき、DockerにはコンテナーにホストのシリアルポートまたはUSBポートへのアクセスを許可する手段がありませんでした。それを可能にするトリックはありますか?
回答:
いくつかのオプションがあります。--device
使用できるフラグを使用して、--privileged
モードなしでUSBデバイスにアクセスできます。
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/ttyUSB0
、Dockerコンテナー内でのみアクセスできるようにしたい場合は、次のようにします。
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
--device
フラグを使用して/dev/<device>
、特にWindowsまたはMacでDocker Quickstart Terminal(VirtualBox Host)を使用している場合、ホストマシン上の関連付けられているAndroidデバイスを特定するにはどうすればよいですか?
--device
USBデバイスのプラグが抜かれたり、抜かれたりするまで機能します。cgroup devices.allowを使用する必要があります。
そのまま使用することもできます-v /dev:/dev
が、ホストからコンテナに、ローディスクデバイスなどを含むすべてのデバイスをマッピングするため、安全ではありません。基本的にこれにより、コンテナーはホスト上でrootになることができますが、これは通常は必要ありません。
cgroupsアプローチの使用はその点でより優れており、コンテナーが起動した後に追加されるデバイスで機能します。
詳細はこちら: Dockerで--privilegedを使用せずにUSBデバイスにアクセスする
貼り付けるのは少し難しいですが、簡単に言えば、キャラクターデバイスのメジャー番号を取得してcgroupに送信する必要があります。
189は/ dev / ttyUSB *のメジャー番号で、「ls -l」で取得できます。お使いのシステムと私のシステムでは異なる場合があります。
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を取得し、コンテナへのアクセスが許可されません。
189
置き換える必要があることを明確にすることで、答えをより良くすることができます。送信する内容の説明はdevices.allow
ここで見つけることができます:kernel.org/doc/Documentation/cgroup-v1/devices.txt
既に与えられている答えを拡張して、キャプチャされない動的に接続されたデバイスのサポート/dev/bus/usb
と、boot2docker VMと一緒にWindowsホストを使用するときにこれを機能させる方法を含めたいと思いました。
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
、場合によってはの代わりにを使用する必要がありました/dev/sg2
。同じことが/dev/ttyACM0
やなどのデバイスにも当てはまると思い/dev/ttyUSB0
ます。
docker runコマンドはLinuxホストでも動作します。
もう1つのオプションは、デバイスのマウント方法と権限を制御するudevを調整することです。シリアルデバイスへの非ルートアクセスを許可するのに役立ちます。デバイスを永続的に接続している--device
場合は、このオプションが最善の方法です。エフェメラルデバイスをお持ちの場合は、以下を使用しています。
デフォルトでは、シリアルデバイスはマウントされているため、ルートユーザーのみがデバイスにアクセスできます。root以外のユーザーが読み取れるように、udevルールを追加する必要があります。
/etc/udev/rules.d/99-serial.rulesという名前のファイルを作成します。そのファイルに次の行を追加します。
KERNEL=="ttyUSB[0-9]*",MODE="0666"
MODE = "0666"は、すべてのユーザーにttyUSBデバイスへの読み取り/書き込み(実行は不可)アクセス許可を与えます。これは最も寛容なオプションであり、セキュリティ要件によってはこれをさらに制限したい場合があります。udevを読んで、デバイスがLinuxゲートウェイに接続されたときに何が起こるかを制御する方法について詳しく知ることができます。
多くの場合、シリアルデバイスは一時的なものです(いつでもプラグを差し込んだり外したりできます)。このため、直接デバイスまたは/ dev / serialフォルダーにマウントすることはできません。プラグを抜くと、それらが消える可能性があるためです。それらを再び差し込んでデバイスが再び表示されても、技術的にはマウントされたファイルとは異なるファイルであるため、Dockerはそれを認識しません。このため、ホストからコンテナに/ devフォルダ全体をマウントします。これを行うには、Docker runコマンドに次のボリュームコマンドを追加します。
-v /dev:/dev
デバイスが永続的に接続されている場合、-deviceオプションまたはより具体的なボリュームマウントを使用することは、セキュリティの観点からはおそらくより良いオプションです。
--deviceオプションを使用せず、/ devフォルダー全体にマウントした場合は、コンテナーを特権モードで実行する必要があります(上記のcgroupをチェックして、これを削除できるかどうかを確認します)。これを行うには、Docker runコマンドに次を追加します。
--privileged
デバイスを接続したり取り外したりできる場合、Linuxは常に同じttyUSBxxxの場所にマウントされることを保証しません(特に複数のデバイスがある場合)。幸い、Linuxは/ dev / serial / by-idフォルダー内のデバイスへのシンボリックリンクを自動的に作成します。このフォルダ内のファイルには常に同じ名前が付けられます。
これは簡単な要約です。詳細を説明するブログ記事があります。
特定のUSBデバイスを、これも特定のDockerコンテナーにバインドするのは困難です。ご覧のとおり、実現するための推奨方法は次のとおりです。
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
より安全です。しかし、実際には特定のデバイスのdevpathが何であるかを知ることは困難です。
私はこの問題を解決するためにこのレポを書きました。
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では、これで十分です。
docker run -ti --privileged ubuntu bash
すべてのシステムリソースへのアクセスを提供します(たとえば/ dev内)
上記の回答に加えて、Docker内ではなく、外部USBデバイス(HDD、フラッシュドライブ)をすばやく使用したい場合 Docker内で機能し、特権モードを使用せをすばやく使用したい場合:
ホスト上のデバイスへの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>
次に、これをparamとして使用して、次のdocker run
ようにします。
docker run -it -v /media/<mount folder name>:/media/<mount folder name>
またはdocker composeでボリュームの下に:
services:
whatevermyserviceis:
volumes:
- /media/<mount folder name>:/media/<mount folder name>
そして今、あなたが実行してコンテナに入るとき、あなたはコンテナ内のドライブにアクセスできるはずです /media/<mount folder name>
免責事項:
Dockerコンテナーの実行中にプラグインできるUSBデバイスに動的にアクセスする場合、たとえば/ dev / video0で接続されたばかりのUSB Webカメラにアクセスする場合は、コンテナーの起動時にcgroupルールを追加できます。このオプションは--privilegedコンテナを必要とせず、特定のタイプのハードウェアへのアクセスのみを許可します。
追加するデバイスタイプのデバイスメジャー番号を確認します。Linuxカーネルのドキュメントで調べることができます。または、デバイスで確認できます。たとえば、/ dev / video0に接続されているWebカメラのデバイスメジャー番号を確認するには、を実行しls -la /dev/video0
ます。これにより、次のような結果になります。
crw-rw----+ 1 root video 81, 0 Jul 6 10:22 /dev/video0
最初の数字(81)はデバイスのメジャー番号です。いくつかの一般的なデバイスのメジャー番号:
Dockerコンテナーを起動するときにルールを追加します。
--device-cgroup-rule='c major_number:* rmw'
アクセスするすべてのタイプのデバイスにルールをます-v /run/udev:/run/udev:ro
-v /dev:/dev
したがって、すべてのusb webcamとserial2usbデバイスをdockerコンテナーに追加するには、次のようにします。
docker run -it -v /dev:/dev --device-cgroup-rule='c 188:* rmw' --device-cgroup-rule='c 81:* rmw' ubuntu bash