はじめに
Dockerゲスト(コンテナ)OSにLinuxを利用したい場合、DockerホストOSはLinuxでなければならない。その為、Docker for MacではmacOS上に仮想マシンを用意し、その上に軽量のLinuxOSを動作させる。
しかしデフォルトで用意されているハイパーバイザ(HyperKit)はホストOS(macOS/Windows)で認識しているUSBデバイスを認識させることができない。Dockerはこのハイパーバイザを変更することができるため、ホストOSのUSBデバイスを認識できるハイパーバイザであるVirtualBoxを利用してDockerコンテナにUSBデバイスを認識させる。
環境
以下の環境で検証した。
% vboxmanage --version
6.0.8r130520
% docker --version
Docker version 18.09.2, build 6247962
% docker-machine --version
docker-machine version 0.16.1, build cce350d7
概要
以下の手順でDockerコンテナにUSB機器を認識させる。
- VirtualBox+拡張パックインストール
- DockerホストOS用仮想マシン(DockerVM)作成
- DockerVMにUSBを認識させる為の設定追加
- DockerホストOSでUSBを認識していることを確認
- DockerコンテナOSで認識できていることを確認
1. VirtualBox+拡張パックインストール
以下のURLにアクセスし、最新のバイナリを取得、インストールする。
Downloads – Oracle VM VirtualBox
2019-06-12現在の最新は以下が最新。
- VirtualBox 6.0.8 platform packages
- VirtualBox 6.0.8 Oracle VM VirtualBox Extension Pack
2. DockerホストOS用仮想マシン(DockerVM)作成
DockerホストOS用仮想マシンをdocker-machineコマンドで作成する。
% docker-machine create -d virtualbox docker-host-default
3. DockerVMにUSBを認識させる為の設定追加
このセクションでは、手順を汎用的かつ簡略化するために、設定の1つである「USB Device Filter」に条件が空のフィルターを登録している。
このフィルターを登録することで、DockerホストOS側で全てのUSB機器を認識できる。
但し、使用しているPCで複数のUSBデバイスを利用している場合、USB機器を抜き差ししたタイミングなどでDockerホストOSに権限を奪われてしまうため、意図せずホストOS側でUSB機器が利用できなくなる。よって、環境に応じてフィルタは適切に設定することを推奨する。
フィルタに条件に設定する場合は、USB機器の情報(例えばVendorIdやProductId)を % vboxmanage list usbhost
で確認する。macOSであれば % system_profiler SPUSBDataType
でも確認できる。
vboxmanageコマンド (CLI) で設定
% docker-machine stop docker-host-default
Stopping "docker-host-default"...
Machine "docker-host-default" was stopped.
% vboxmanage modifyvm docker-host-default --usb on
% vboxmanage modifyvm docker-host-default --usbehci on
% vboxmanage usbfilter add 0 --target docker-host-default --name 'All Devices'
% docker-machine start docker-host-default
VirtualBox Manager (GUI) で設定
- docker-machineコマンドでVMを停止する。
- VM(docker-host-default) > Settings > Ports > USB の設定画面で以下のチェックボックスを有効にする。
- Enable USB Controller
- USB 2.0 (EHCI) Controller
- 同画面の「USB Device Filters」の右の新規作成アイコンを押下し、条件が空のフィルターを作成する。
- フィルタが作成されたら、当該デバイスフィルタをダブルクリックし、名前を「All Devices」に変更する。
- docker-machineコマンドでVMを起動する。
4. DockerホストOSでUSBを認識していることを確認
% docker-machine ssh docker-host-default
( '>')
/) TC (/ Core is distributed with ABSOLUTELY NO WARRANTY.
(/-_--_-/) www.tinycorelinux.net
docker@docker-host-default:~$ udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent
※機器をPCに接続すると以下のようなメッセージが出力されることを確認する。
※例として接続したデバイスはUSBシリアル通信機器。
…
KERNEL[4332.894758] add /devices/pci0000:00/0000:00:06.0/usb2/2-1/2-1:1.0/ttyUSB0 (usb-serial)
…
UDEV [4332.897138] add /devices/pci0000:00/0000:00:06.0/usb2/2-1/2-1:1.0/ttyUSB0 (usb-serial)
…
KERNEL[4332.910588] bind /devices/pci0000:00/0000:00:06.0/usb2/2-1/2-1:1.0/ttyUSB0 (usb-serial)
…
UDEV [4332.914260] bind /devices/pci0000:00/0000:00:06.0/usb2/2-1/2-1:1.0/ttyUSB0 (usb-serial)
…
^C (確認できたらCtrl+Cでモニタリング終了)
接続が確認できたら、対応するデバイスファイルが存在することも確認し、ログアウトする。
複数のUSBシリアルデバイスを接続している場合は、ttyUSBXのXの部分の数字が異なる場合があるため注意する。
docker@docker-host-default:~$ ls -l /dev/ttyUSB0
crw-rw---- 1 root staff 188, 0 Jun 12 06:32 /dev/ttyUSB0
docker@docker-host-default:~$ exit
logout
%
5. DockerコンテナOSで認識できていることを確認
まずはじめに、dockerコマンドが先ほど作成したDockerVMを利用できるようにするために環境設定を行う。
DockerイメージやコンテナはDockerVM毎に別々に管理されているため、
このコマンドを忘れるとデフォルトのHyperkitを利用したDockerコンテナを起動することになるので注意する。
% eval $(docker-machine env docker-host-default)
続いて、DockerコンテナOSで確認するために適当なLinuxOSイメージを取得する。
% docker pull debian:9.9-slim
9.9-slim: Pulling from library/debian
fc7181108d40: Pull complete
Digest: sha256:9490c476443a3869e39c2897fa66c91daf5dcbbfca53c976dac7bbdc45775b28
Status: Downloaded newer image for debian:9.9-slim
USB機器を接続し、コンテナを起動する。
その際 --device
でDockerホストOSが認識しているデバイスファイルをDockerコンテナOS上で読み書き可能にする。
% docker run --rm --device /dev/ttyUSB0 -it debian:9.9-slim /bin/bash
root@2a8988dafd77:/# ls -l /dev/ttyUSB0
crw-rw---- 1 root staff 188, 0 Jun 12 05:46 /dev/ttyUSB0
root@2a8988dafd77:/# exit
exit
USB機器を接続していない場合は以下のようにエラーが出力される。
% docker run --rm --device /dev/ttyUSB0 -it debian:9.9-slim /bin/bash
docker: Error response from daemon: linux runtime spec devices: error gathering device information while adding custom device "/dev/ttyUSB0": no such file or directory.
ERRO[0000] error waiting for container: context canceled
おわりに
USB Device Fileterの設定を検証している際、ホストOS側で認識していたUSB機器を抜き差しすることでホストOS側から機器が利用できなくなったり、フィルタの設定を変更しても、DockerホストOSが起動しているVMを再起動しないとそれが反映されなかったりと、設定の影響を確認するのに手間取った。
また記事に直接関係ないが、DockerホストOSでシステムの情報を確認しようとすると、OSがTinycorelinuxだったり、基本的なコマンドがGNU版ではなくBusyBoxだったりして、少し戸惑った。BusyBoxは調べてみると歴史は古いようで、Linuxの奥深さに触れるいい機会になった。
macOSでしか検証していないけど、おそらくWindowsでも同じ手順で認識させることができそう。