• IoT

コンテナに入れてみる

こんにちは、宇野です。
今回は毛色を変えて、コンテナ話です。

Dockerコンテナを触るようになると、だんだんと『如何にしてローカルの環境を汚さずに目的を達成するか』とか考えだすと思います。

せっかく最小構成でOSをインストールしても、あれやこれやのために色々とインストールして、その影響が別のソフトに出たりとか面倒なので、Docker環境だけ作って他は全てコンテナに閉じ込めたいわけです。今回は別の検証で使っている環境に、余計な影響を与えずにWifiアクセスポイントの機能を追加したかったのです。また、せっかくなので別の環境でも利用出来るようにもしたいと考えました。

※ 執筆時点では時間の都合まだDockerfile化していないので、中に入って操作しています。

環境情報

今回使用した環境は以下の通りです。

Wifiがハードウェアに付属していなかったので、USBの物を使用する事としました。

ハードウェア:Rock64 ※WifiやBluetoothのモジュールが無いシングルボードコンピュータ。なお、どのハードウェアでもおそらく同じとなります

  • OS: Ubuntu 18.04.1 LTS
  • USB-Wifi: 無線LAN子機 [無線11n/g/b 150Mbps・USB2.0・Win] 親機・子機同時モード対応  WLI-UC-GNM2S
  • Docker version 18.09.1, build 4c52b90
  • 使用したDockerイメージ: ubuntu:18.04

アクセスポイントを構築するうえで必要となるソフトウェアは以下の通りです。

これらはコンテナに対してインストールします。

  • hostapd
    アクセスポイントのソフトウェア。最新は2.7ですが、リポジトリから入手可能な2.6で確認できました
  • isc-dhcp-server
    DHCPサーバのソフトウェア。接続してきた機器に対してIPアドレスやその他ネットワーク関連の設定を提供します
  • net-tools
    ifconfigが入ったソフトウェア。isc-dhcp-serverの起動時にWifiのInterfaceにIPアドレスが振られている必要があるので、使用します。
  • wireless-tools
    無線LAN関連のドライバ等が詰まったツール群

構築方法

さて、以下にアクセスポイントコンテナの構築方法を紹介します。なお、『元の環境に手を入れない』事を目標にしていましたが、いきなり挫折することになりました。

Network-Managerが起動しているとhostapdがドライバを操作できなくて起動しない

ここがわからなくて、延々とハマったのですが、残念ながらUbuntu18.04は最小構成でもNetwork-Manager動いてました・・・orz

なので、構築にあたってまずは以下を実行してNetwork-Managerを止めておきます。大丈夫。なくてもちゃんと動きます。・・・きっと・・・

sudo systemctl stop network-manager
sudo systemctl disable network-manager

コンテナの起動

コンテナを起動するにあたって、ホストとなるサーバにあれこれアクセスできる権限が必要となってきます。そのため、以下オプションを付けます。セキュリティホールにもなりうるのであまり積極的には使いたくないオプションですが、必要になるのでしょうがない。

  • –net=host
    ホストのネットワークを直接コンテナ内に見えるようにするオプションです。
  • –privileged
    管理者権限を与えて、ホストとなるコンピュータをコンテナ内から操作できるようにします

また、いろんな環境で使えるようにしたいので、IPアドレスやInterface名など変わる可能性がある部分を可変にします。そういった事をするときは環境変数を使用する事が多いので、環境変数を設定するオプションを使用します。

  • -e
    コンテナ起動時に環境変数を設定するオプション。コンテナ起動の際に変数として使用する事がある

その他、お決まりのオプションをつけておきます。

  • –name
    ホストでコンテナを管理するにあたってわかりやすいラベルをつけます
  • -d
    バックグラウンド起動を許可します
  • -ti
    ターミナル接続して、画面表示を伴った操作が可能

これらを用いて以下のようなコマンドを実行することになります。ubuntuのコンテナイメージがダウンロードされ、起動します。

sudo docker run -e INTERFACE="wlx84afec53b98e" -e SSID="testwifiap" -e WPA_PASSPHRASE="password_for_ap" -e CHANNEL="3" -e SUBNET="192.168.100.0" -e AP_ADDR="192.168.100.1" -e RANGE_FROM="192.168.100.2" -e RANGE_TO="192.168.100.254" -e NETMASK="255.255.255.0" -e NAMESERVERS="8.8.8.8,192.168.0.22" -e BROADCAST="192.168.100.255" --name mywifiap -ti -d --privileged --net=host ubuntu:18.04 /bin/bash

起動が完了したら、起動したコンテナに接続します。

sudo docker exec -ti mywifiap /bin/bash

ソフトウェアの導入

前述のソフトウェアをインストールします。全てaptで入手可能です。

コンテナ内でのコマンド実行に関して、できるだけ1行にまとめることが望ましくなりますので、&&で繋いで実行します。Dockerコンテナは1行につき1つレイヤ(バックアップのような物)が作られてしまうため、たくさんコマンドを実行すればするほどリソースを要することになってしまうからです。

apt update && apt upgrade -y && apt install hostapd isc-dhcp-server net-tools wireless-tools -y && apt autoremove

hostapdの設定

環境変数を使用してhostapdの設定ファイルを作成します。vimのようなサービスに使用しない余計なものがインストールされていないのでechoコマンドで頑張ります。ここでもできる限り1行で編集を行います。

echoは-eオプションを使用する事で改行が表示できます。\\nと記載することで、出力時に改行に置き換えてくれます。${}の部分で環境変数に設定した値をとってきています。

echo -e interface=${INTERFACE}\\ndriver=nl80211\\nssid=${SSID}\\nhw_mode=g\\nchannel=${CHANNEL}\\nmacaddr_acl=0\\nauth_algs=1\\nignore_broadcast_ssid=0\\nwpa=3\\nwpa_passphrase=${WPA_PASSPHRASE}\\nwpa_key_mgmt=WPA-PSK\\nwpa_pairwise=TKIP\\nrsn_pairwise=CCMP > /etc/hostapd/hostapd.conf
echo DAEMON_CONF="/etc/hostapd/hostapd.conf" >> /etc/default/hostapd

isc-dhcp-serverの設定

接続してきた機器にIPアドレスを付与するためにisc-dhcp-serverの設定変更を行います。ここでもecho・・・と行きたいところですが、すでに設定ファイルが存在していてそれを書き換えたほうが早そうなのでやsedで正規表現を使って文字列を置き換えて編集することにします。

sedは s/置き換える文字/置き換え後/ という使い方をします。コメントアウト、コメントアウト解除は()を使用する事でマッチした部分が¥1で表せることを利用して行います。

sed -i -r 's/(option domain-name "example.org";)/#\1/' /etc/dhcp/dhcpd.conf&&sed -i -r 's/(option domain-name-servers ns1.example.org, ns2.example.org;)/#\1/' /etc/dhcp/dhcpd.conf&&sed -i -r 's/#(authoritative;)/\1/' /etc/dhcp/dhcpd.conf
echo -e ping-check true\;\\nsubnet ${SUBNET} netmask ${NETMASK} \{\\n option routers ${AP_ADDR}\;\\n option broadcast-address ${BROADCAST}\;\\n option subnet-mask ${NETMASK}\;\\n option domain-name "local"\;\\n option domain-name-servers ${NAMESERVERS}\;\\n range ${RANGE_FROM} ${RANGE_TO}\;\\n\} >> /etc/dhcp/dhcpd.conf
sed -i -r "s/INTERFACESv4=\"\"/INTERFACESv4\=\"${INTERFACE}\"/" /etc/default/isc-dhcp-server&&sed -i -r 's/(INTERFACESv6="")/#\1/' /etc/default/isc-dhcp-server

起動

設定が完了したら起動します。ここでifconfigを使用して手動でUSB WifiのInterfaceにIPアドレスを付与しておくことを忘れないようにします。isc-dhcp-serverの起動にあたって必要な手順です。

ifconfig ${INTERFACE} ${AP_ADDR} netmask ${NETMASK} up
/etc/init.d/isc-dhcp-server start
hostapd /etc/hostapd/hostapd.conf

以下のような表示が出たらアクセスポイントとして起動できているので、SSIDが見えるようになっているはずです。

Configuration file: /etc/hostapd/hostapd.conf
Using interface wlx84afec53b98e with hwaddr 84:af:ec:53:b9:8e and ssid "rock-ub-kap"
wlx84afec53b98e: interface state UNINITIALIZED->ENABLED
wlx84afec53b98e: AP-ENABLED

Ctrl+Cで終了してコンソールに戻ることになります。終了するとInterfaceに割り振ったIPも消えてしまっているので、再度起動する際にifconfigで設定をすることをお忘れなく。

最後のhostapdをバックグラウンドで起動するなりして起動しっぱなしにしておけば常にコンテナにアクセスしておかなくてもOKとなります。

おわりに

ここまで確認できたものをCommitしてリポジトリにでもUpしておけば、環境を汚さずあちこちで利用できるアクセスポイントコンテナの完成です。元の環境にhostapdとか色々入れなくてよいので、変なトラブルを心配しなくてよくて安心できます。またいらなくなったら止めて捨てればOKなのでお手軽です。

今回はアクセスポイントみたいにマニアックな部分をコンテナ化しましたが、同じように色々な環境をコンテナに入れることが出来ます。IoTのデバイスを操作するための開発環境とか入れておくと結構便利です。皆様もオリジナルコンテナ構築に挑戦してみてはいかがでしょうか?

関連記事

  1. M5Stack(マイコン)+絶対圧センサーで応援してくれるエクササイズ…

  2. IoT奮闘記 ~なめこから始まるIoTシステム構築~

  3. RPAによるゲームの自動化 ~とあるギルドマスターの挑戦

  4. Nature Remoを使って憧れのスマートホーム化!

  5. ランニングコストゼロで作るスマートホームコントロール(ラズパイとNod…

  6. 金曜日に届いたFitbit Inspire HRで週末2つアプリを作っ…

  7. M5StickC(マイコン)で格ゲーをつくる

  8. 娘に渡すIoTデバイス(Wio LTE+GPSセンサー)

PAGE TOP