PT3 地デジ・BS録画環境を Docker コンテナ内に押し込める

ご存知 PT3 による地デジ・BSの録画環境を私も重宝しているのですが、いかんせん環境設定が面倒で、OS の入れ替えを躊躇しがちに。その一因として、関連ツール類がパッケージ化されておらず、ソースを一つ一つ取得してきてインストールせざるを得ないことが挙げられると思います。

それって Docker イメージに押し込んじゃえばいいんじゃね? というわけで始めてみました。なお、録画サーバである EPGREC(トップページ - 録画予約システムepgrec)とそのバックで動く MySQL の設定については、Docker の設定としては極々オーソドックスですので、ここでは触れません(気が向いたら追記するかも)。

なお、下記の手順で、ホストでの PT3 録画環境 → Docker の PT3 録画環境への移行期間中は、ホスト側と Docker 側とで、一枚の B-CAS カードを共用して、同時に録画ができています(ホストが地デジ 3 チューナ、BS 3 チューナで、Docker コンテナは地デジ 1 チューナ・BS 1 チューナを使用)。

全体の構成

ホスト OS 側では PT3 ドライバと PC カードリーダのサーバを動かし、特権モードの Docker コンテナ側からは、PT3 へはデバイスファイルを通じて、カードリーダへは UNIX ドメインソケットを通じて利用するようにします。

Docker ホスト側のセットアップ

そのようなわけで、Docker ホスト環境の側では、以下のように、仮想環境のホストと、ハードウェアの管理だけをしてもらいましょう。とっても今風ですね、ステキ。

  • Docker のホスト
  • PT3 ドライバ
  • PC カードリーダのサーバ
  • (各 web サービスへのリバースプロキシとして nginx)

Docker のホスト

ホストの OS としては Ubuntu 14.04 ですので、Docker は「docker.io」の 1.0 系なのですが、このところ Docker は開発が活発すぎるので、下記で「lxc-docker」の最新版(今日時点で 1.3.1)を入れます。右記も参照。 ∥ Ubuntu - Docker Documentation

$ curl --silent --show-error --location https://get.docker.io/ | sh

それでも docker exec の動作とか、若干変な気もします。後で見てみるか。

追記(Nov 21 2014): どうやら Ubuntu 14.04 の標準 Docker のストレージエンジンのデフォルトは devicemapper(設定ファイルで指定)なのですが、lxc-docker の標準が aufs(設定ファイルに無指定なので)になっているようです。aufs はマイナーな機能が足りていないので、後々痛い目にあわないように、最初に、/etc/default/docker にストレージエンジンを指定してから docker サービスを再起動しておいた方が良いと思われます。多くのケースでは、CentOS で yum(8) を動かす際にハマると思われます。

DOCKER_OPTS="-s devicemapper"

参考:

早く btrfs にしたーい!

PT3 ドライバ

Git でソースをいただいてきて、DKMS(Dell - Dell | Linux - Projects - DKMS)でドライバをインストールします。今どき、DKMS が必要な局面というのも減りましたけれどね。下記のような Chef レシピにまとめて実行しています。

package "dkms"

git "#{Chef::Config[:file_cache_path]}/pt3" do
  repository "git://github.com/m-tsudo/pt3.git"
  reference "master"
  action :sync
  notifies :run, "bash[pt3 installation]"
end

bash "pt3 installation" do
  only_if ". #{Chef::Config[:file_cache_path]}/pt3/dkms.conf; test -z \"$(dkms status -m $PACKAGE_NAME -v $PACKAGE_VERSION)\""
  cwd "#{Chef::Config[:file_cache_path]}/pt3"
  code <<-EOH
. dkms.conf;
rm -fr /usr/src/$PACKAGE_NAME-$PACKAGE_VERSION
mkdir -p /usr/src/$PACKAGE_NAME-$PACKAGE_VERSION
git archive master | sudo tar -x -C /usr/src/$PACKAGE_NAME-$PACKAGE_VERSION
dkms add -m $PACKAGE_NAME -v $PACKAGE_VERSION
dkms build -m $PACKAGE_NAME -v $PACKAGE_VERSION
dkms install -m $PACKAGE_NAME -v $PACKAGE_VERSION
lsmod | grep pt3_drv || modprobe pt3_drv
  EOH
end

bash "pt3 boot time module loading" do
  not_if "grep pt3_drv /etc/modules"
  code <<-EOC
    echo pt3_drv >> /etc/modules
  EOC
end

追記(Tue May 26 2015): 最近は Ansible(Ansible Documentation — Ansible Documentation)に乗り換えました。決め手は、ノードをまたいでオーケストレーションが出来ることと、設定の可読性が高いことでした。

---

- name: DKMS がインストールされていること
  apt: name=dkms state=present

- name: pt3 ドライバのソースが git clone されていること
  git:
    repo: git://github.com/m-tsudo/pt3.git
    dest: /root/pt3
    accept_hostkey: true

- name: pt3 ドライバの DKMS ステータスを取得する
  args:
    executable: /bin/bash
    chdir: /root/pt3
  shell: |
    . dkms.conf
    dkms status -m $PACKAGE_NAME -v $PACKAGE_VERSION
  register: pt3_driver_status
  always_run: true
  changed_when: false

# - debug: var=pt3_driver_status

- name: pt3 ビルドの要否を取得する
  set_fact:
    pt3_build_required: force_build or (not pt3_driver_status.stdout)

- name: pt3 ドライバをインストールする
  when: pt3_build_required
  args:
    executable: /bin/bash
    chdir: /root/pt3
  shell: |
    . dkms.conf
    rm -fr /usr/src/$PACKAGE_NAME-$PACKAGE_VERSION
    mkdir -p /usr/src/$PACKAGE_NAME-$PACKAGE_VERSION
    git archive master | tar -x -C /usr/src/$PACKAGE_NAME-$PACKAGE_VERSION
    dkms add -m $PACKAGE_NAME -v $PACKAGE_VERSION
    dkms build -m $PACKAGE_NAME -v $PACKAGE_VERSION
    dkms install -m $PACKAGE_NAME -v $PACKAGE_VERSION
    lsmod | grep pt3_drv || modprobe pt3_drv

# modules-load.d http://www.freedesktop.org/software/systemd/man/modules-load.d.html
- name: 起動時の pt3 ドライバロード設定が存在すること
  copy:
    content: |
      pt3_drv
    dest: /etc/modules-load.d/pt3.conf

- name: 標準のドライバを入れないようになっていること
  copy:
  content: |
    blacklist earth-pt1
    blacklist earth-pt3
  dest: /etc/modprobe.d/blacklist-ath_pci.conf

# To remove:
#   # dkms remove $PACKAGE_NAME/$PACKAGE_VERSION --all

...

PC カードリーダのサーバ

B-CAS カードを差すカードリーダードライバ(PCSClite project)の、サーバ側(「pcscd」)だけを動かします。クライアント(「pcsc-tools」)は、動作確認のために入れても構いませんが、ホスト側では必須ではありません。

$ sudo aptitude install pcscd

Docker コンテナ

とりあえずは Dockerfile をさらします。

# Use phusion/baseimage as base image. To make your builds reproducible, make
# sure you lock down to a specific version, not to `latest`!
# See https://github.com/phusion/baseimage-docker/blob/master/Changelog.md for
# a list of version numbers.
FROM phusion/baseimage:latest

MAINTAINER Kiichiro NAKA <knaka@ayutaya.com>

# Set correct environment variables.
ENV HOME /root

# Regenerate SSH host keys. baseimage-docker does not contain any, so you
# have to do that yourself. You may also comment out this instruction; the
# init system will auto-generate one during boot.
RUN /etc/my_init.d/00_regen_ssh_host_keys.sh

# Use baseimage-docker's init system.
CMD ["/sbin/my_init"]

# --------------------------------------------------------------------

RUN echo "Asia/Tokyo" > /etc/timezone && dpkg-reconfigure --frontend noninteractive tzdata

RUN apt-get update
RUN apt-get install -y software-properties-common

RUN apt-get install -y wget unzip git
RUN apt-get install -y pkg-config autoconf build-essential

# Card reader
RUN apt-get install -y pcsc-tools

# ARIB library
RUN wget http://hg.honeyplanet.jp/pt1/archive/ec7c87854f2f.zip
RUN unzip ec7c87854f2f.zip
RUN apt-get install -y libpcsclite-dev
RUN cd pt1-ec7c87854f2f/arib25/src/ && make && make install

# recpt1
RUN git clone https://github.com/stz2012/recpt1
RUN cd recpt1/recpt1/ && ./autogen.sh && ./configure --enable-b25 && make && make install

# --------------------------------------------------------------------

# Clean up APT when done.
RUN apt-get clean && rm -fr /var/lib/apt/lists/* /tmp/* /var/tmp/*

頭の部分と尻の部分は Docker baseimage(phusion/baseimage-docker)の定形ですのでどうでも良いとして、肝心なのは中間部分の、各種ツールをインストールしているところです。

要点としては、pcsc-tools は入れているが pcscd は入れていないところでしょうか。この理由については後述します。

その他のツールについては、私のところではこのツール&バージョンの組み合わせが良好だったというところですので、何とも言えません。肝心なのは、Docker イメージとしては OS のバージョンも含めて固定&塩漬けにできるため、ホスト OS のバージョンアップに影響されないというメリットが得られることです。この安心感は大きい。

コンテナからの、PT3 ドライバや PC カードリーダーサーバへのアクセス

問題は、Docker コンテナ側からどうやって PT3 と PC カードリーダーサーバへアクセスするかです。下記は、最終的な Docker コンテナの起動コマンドです。

docker run -d --name epgrec \
 --privileged \
 --volume /dev/:/dev/ \
 --volume /var/run/pcscd/pcscd.comm:/var/run/pcscd/pcscd.comm \
 --volume $PWD/config.xml:/var/www/html/settings/config.xml \
 -p 127.0.0.1:1026:80 --link mysql-epgrec:mysql \
 knaka/epgrec:latest

EPGREC のための設定ファイルや DB 設定も盛り込まれているのでゴチャゴチャしていますが、ここでの要点は、まずは --privileged オプションです。これによって Docker コンテナは特権モードで動作するので、デバイスファイル(ここでは /dev/pt3video*)に自由にアクセスすることができるようになります。

さて、そのデバイスファイルはホスト OS 上で udev によって動的に管理されていますので、--volume /dev/:/dev/ としてデバイスファイル群をゴッソリと共有してやります。

次に PC カードリーダーなのですが、PCSC は UNIX ドメインソケットを用いたクライアント・サーバモデルのソフトウェアですので、--volume /var/run/pcscd/pcscd.comm:/var/run/pcscd/pcscd.comm のようにソケットファイルだけを共有してやれば、あっさり pcsc-tools が、Docker コンテナ上で動作します。

なお、最初の予定では USB のデバイスファイルを共有して pcscd をコンテナ内でも動かそうとしたのですが、そうするとホストの pcscd と Docker コンテナ内の pcscd が先勝ちにリーダーデバイスを取り合ってしまって、ホストと Docker での同時動作ができませんでした。

EPG 抽出ツールと EPGREC の設定

EPGREC のバックエンドである MySQL は別コンテナにしました。一サービス一 DB にすると、分かりやすくて良いですね。特に MySQL は、PostgreSQL などと違って、DB インスタンスを複数ポコスカ起動するように作られていないので。

さて

何か見落としはありませんでしょうか。コメント請う