ロボット向けアプリケーションをDockerコンテナで動かす


最近は[Docker](https://www.docker.com/)コンテナでサーバアプリケーションを動かしたりしていますが、ロボットのアプリケーションにも適用できるんじゃないかと思ってやってみたら意外に便利でしたので、事例を紹介します。

# Dockerについて

![68747470733a2f2f692e696d6775722e636f6d2f365033666d6c442e706e672532303d35323078.png](https://qiita-image-store.s3.amazonaws.com/0/33935/edb7d2cb-2828-9096-7ff1-9844dd1fe429.png "68747470733a2f2f692e696d6775722e636f6d2f365033666d6c442e706e672532303d35323078.png")

そもそもロボットは、音声認識やROSなどLinux上で複数のソフトウェアを統合したりソースコードを引っ張ってこないといけなかったりと、環境構築、ローカル環境との同期がことさらめんどくさいです。

そこで、Linuxコンテナ（LXC）を活用するためのツールである[Docker](https://www.docker.com/)を使うことで、コンテナ内部で動かすアプリケーション環境の管理が簡単になります。

Dockerを使うメリットとしては

- よくあるインストール手順書とかは必要なく、同じ構成の環境を一発でどこでも構築可能
- 構成が大きく変わるロボット内のソフトウェア・アップデートも簡単にできる

一方、デメリットは

- RaspberryPiなどのARM系のチップではDockerを動かすのは厳しい
- コンテナなので、性能はちょっと落ちる(?)

という感じでしょうか。

---

Dockerではイメージの構成を[Dockerfile](https://docs.docker.com/engine/reference/builder/)というインストールコマンドが書かれたbashスクリプトのようなもので記述します。

また、複数のサーバを内部で動かす場合は、[Docker Compose](https://docs.docker.com/compose/)で構成を管理することができます。

Dockerの環境を構築する場合は、[Docker Machine](https://github.com/docker/machine)を利用するか、ローカル環境の場合は[Docker Toolbox](https://www.docker.com/docker-toolbox)を利用すると、Dockerの環境構築が楽にできます。

Dockerには[deviceパラメータ](https://docs.docker.com/engine/reference/commandline/run/#add-host-device-to-container-device)、Docker Composeには[devices](https://docs.docker.com/compose/compose-file/#devices)というコンフィグレーションがあり、USBデバイスやサウンドデバイスをホストからコンテナにマッピングすることができます。しかし、1コンテナしかそのデバイスを使うことができないので、複数コンテナで運用する場合はどのコンテナでデバイスを触るかをちゃんと計画しないといけません。

# 試しにロボット聴覚HARKをDockerで動かす
[HARK](http://www.hark.jp/)という、音声認識や音源定位、音源分離などを行えるオープンソースなソフトウェアがあります。私も触り始めたところなのですが、まずインストールが面倒なのでDocker化してしまいましょう。

https://github.com/SociableThings/docker-lumiere に、以下で紹介しているDockerfileの他に、起動スクリプトなど実際に動作する状態で置いています。

ロボット上でDockerなどをインストールしてから、Docker ComposeでDockerコンテナを立ち上げます。

まずはHARKのコンテナを定義する `Dockerfile` から。[HARK Installation Instructions](http://www.hark.jp/wiki.cgi?page=HARK+Installation+Instructions)を参考にして書いていきます。

```Dockerfile
FROM ubuntu:14.04

ENV HOME /root
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update && apt-get install -yq --no-install-recommends wget software-properties-common

# Add HARK repository
RUN echo "deb http://winnie.kuis.kyoto-u.ac.jp/HARK/harkrepos trusty non-free\ndeb-src http://winnie.kuis.kyoto-u.ac.jp/HARK/harkrepos trusty non-free" > \
    /etc/apt/sources.list.d/hark.list
RUN wget -q -O - http://winnie.kuis.kyoto-u.ac.jp/HARK/harkrepos/public.gpg | sudo apt-key add -
RUN add-apt-repository ppa:chris-lea/node.js

RUN apt-get update
RUN apt-get install -yq --no-install-recommends supervisor
RUN apt-get install -yq --no-install-recommends vim-tiny alsa-utils
RUN apt-get install -yq --no-install-recommends xfce4 xfce4-goodies
RUN apt-get install -yq --no-install-recommends x11vnc xvfb
RUN apt-get install -yq nodejs harkfd hark-binaural hark-designer julius-4.2.3-hark-plugin harktool4
RUN apt-get autoclean \
    && apt-get autoremove \
    && rm -rf /var/lib/apt/lists/*

# Change hark setting
#RUN sed -i 's/sudo\ forever\ start\ app\.js/sudo\ forever\ start\ app\.js\ allowremote/g' /usr/bin/hark_designer

RUN cd /usr/bin/hark-designer && npm install

WORKDIR /usr/share/hark-designer/userdata/networks

ADD scripts/startup.sh /root/startup.sh
ADD config/supervisord.conf /root/supervisord.conf
ADD config/.vimrc /root/.vimrc
ADD config/julius /root/julius

EXPOSE 5900
EXPOSE 3000

VOLUME /usr/share/hark-designer/userdata/networks

ENTRYPOINT ["bash", "/root/startup.sh"]
```

HARK本体とHARK Designer、音声認識用のJulius、X-Windowのxfceを入れてます。（本当はJuliusなどを別コンテナにしたら良いんだと思うんですが、今回は1つのイメージにまとめます）

そして、このDockerfileをビルドしたりdevicesのマッピングを定義した`docker-compose.yml`は以下となります。

```docker-compose.yml

hark:
  build: .
  ports:
    - "5900:5900"
    - "3000:3000"
  volumes:
    - networks:/usr/share/hark-designer/userdata/networks
  devices:
    - "/dev/snd:/dev/snd"
```

サウンドデバイスをそのままHARKのコンテナにマッピングしています。

最後に、コンテナを立ち上げます。

```ロボット上のターミナル
$ docker-compose build
$ docker-compose up
```

HARKはHARK DesignerというHARKの構成をブラウザ上で記述することができるようになっています。

さきほどのコンテナのポート3000番にアクセスすると、そのHARK Desginerが立ち上がります。ローカルのPCからアクセスしてみましょう。

```ローカルのターミナル
$ open http://{RobotのIP}:3000
```

![スクリーンショット 2015-09-06 20.01.23.png](https://qiita-image-store.s3.amazonaws.com/0/33935/fb640f7a-a0db-31a0-8e50-7b05d1381dd0.png "スクリーンショット 2015-09-06 20.01.23.png")

開いた！やった！

Dockerだとロボットのソフトウェアのデプロイも簡単にできてすごく良いですね！