Linux環境では,DockerはOSのネイティブ機能を活用することで,コンテナ化されたプロセスが直接USBデバイスと通信できるようにしています.一方,WindowsおよびmacOSでは,Dockerは仮想マシン(VM)内で動作するため,Linuxのようにホストマシンのハードウェアに直接アクセスすることはできません.
一応の解決策として仮想マシンにUSBデバイスを転送し,コンテナに接続する方法がありますが,使い勝手はあまりよくないです.
そこでUSB/IPというオープンソースプロトコルを使います.これによってホストシステムにUSB/IPサーバーを建て,USBデバイスをネットワーク経由でコンテナから利用できるようになります.
注意点として,USBデバイスがホストシステムからDockerの共有コンテキストに送られるため,使用マシン上にあるすべてのコンテナがUSBデバイスに理論上アクセス可能できてしまいます.
そこでこの記事ではdevmgrコンテナを用意し,永続的なコンテキストとして機能させています.本記事は共有コンテキストのまま進めます.
(コンテキスト(Context)とは,DockerイメージをビルドするときにDockerデーモンに送信される"ファイルやディレクトリ群"を指します.Dockerfileに記述する命令では,コンテキスト内のファイルだけが対象になります.)
動作環境
- OS:Windows11
- Docker上のubuntu24.04
用意・インストールするもの
- Docker上のubuntu24.04(WSL2で動作させる)
- 最新バージョンのWSL
-
usbipd-win- usbipd-winプロジェクトの最新リリースページへ移動する
- .msi ファイルを選択し,インストーラをダウンロード
- ダウンロードした usbipd-win_x.msi インストーラファイルを実行
実行手順
1~3まではほとんどこちらのコピペです.
-
管理者モードでPowerShellを開き,次のコマンドを入力して,Windowsに接続されているすべてのUSBデバイスを一覧表示します.デバイスが一覧表示されたら,dockerにつなげたいデバイスのバスIDを選択してコピーします.
PowerShellusbipd list -
USBデバイスを接続する前に,デバイスを共有し,WSLに接続できるようにする必要があります.これには管理者特権が必要です.dockerにつなげたいUSBデバイスのバスIDを選択し,次のコマンドを実行します.
PowerShellusbipd bind -b <BUSID> -
USBデバイスを接続するには,次のコマンドを実行します.WSL2軽量VMをアクティブに保つために,WSLコマンドプロンプトを開いておきます. USB デバイスがWSLに接続されている限り,Windowsでは使用できないことに注意してください. WSLに接続すると,WSL2として実行されている任意のディストリビューションでUSBデバイスを使用できます.
PowerShellusbipd attach --wsl --busid <busid>ここまでの出力例
PowerShellPS C:\WINDOWS\system32> usbipd list Connected: BUSID VID:PID DEVICE STATE 1-1 2341:0069 USB シリアル デバイス (COM4), DFU-RT Port Not shared 1-2 413c:301a USB 入力デバイス Not shared 1-3 30c9:00a8 Integrated Camera, Integrated IR Camera, APP Mode Not shared 2-4 0489:e0d8 RZ616 Bluetooth(R) Adapter Not shared Persisted: GUID DEVICE ~~~ ~~~ PS C:\WINDOWS\system32> usbipd bind -b 1-1 PS C:\WINDOWS\system32> usbipd attach --wsl --busid 1-1 usbipd: info: Using WSL distribution 'Ubuntu' to attach; the device will be available in all WSL 2 distributions. usbipd: info: Loading vhci_hcd module. usbipd: info: Detected networking mode 'nat'. usbipd: info: Using IP address 172.25.144.1 to reach the host. PS C:\WINDOWS\system32> usbipd list Connected: BUSID VID:PID DEVICE STATE 1-1 2341:0069 USB シリアル デバイス (COM4), DFU-RT Port shared 1-2 413c:301a USB 入力デバイス Not shared 1-3 30c9:00a8 Integrated Camera, Integrated IR Camera, APP Mode Not shared 2-4 0489:e0d8 RZ616 Bluetooth(R) Adapter Not shared Persisted: GUID DEVICE ~~~ ~~~ PS C:\WINDOWS\system32> -
WSL上で以下のコマンド達によりデバイスが正常に接続されたことを確認する.
WSLlsusb ls /dev/ttyA*ここまでの出力例
WSLroot@aaa:/mnt/c/Users/aaa# lsusb Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 002: ID 2341:0069 Arduino SA UNO R4 Minima Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub root@aaa:/mnt/c/Users/aaa# ls /dev/ttyA* /dev/ttyACM0 -
本命のコンテナを起動させる.
--device "/dev/ttyACM0"が大事です.WSLdocker run --rm -it -v ${PWD}:/workdir --device "/dev/ttyACM0" -p 6080:80 --shm-size=512m tiryoh/ros2-desktop-vnc:jazzy
結果
マイコン経由でマシンに接続したロードセルの値が読みこめるか確認します.
ubuntu@4b874bd37844:~$ ls /dev/ttyA*
/dev/ttyACM0
ubuntu@4b874bd37844:~$ cat /dev/ttyACM0
0.238 [g] (0x2409)
0.344 [g] (0x2538)
0.820 [g] (0x241a)
0.598 [g] (0x2505)
1.332 [g] (0x2627)
いい感じです
参考記事
- windows環境におけるdocker
- 実際の実行手順
