Ubuntu以外のディストリビューションでarmhfなDocker imageを作成する

More than 1 year has passed since last update.


背景

Dockerで、armhfなクロス環境のコンテナができると、Raspberry piでのアプリケーション開発が捗ります。

クロスコンパイラで可能ですが、apt-get等でライブラリ等をインストールするとなると、尚更敷居が高く感じます(といいますか、やり方知らないだけです…)。また、x86で作成して、Raspbianでリビルドしても、ディストリビューションの違いから、リビルドエラーや実行時エラーがでて、その手間も馬鹿にできません。

クロス環境のコンテナを動かすには、binfmtが必要となりますが、CentOS等、提供されていないディストリビューションもあります。このような背景を受けて、他ディストリビューションでもクロス環境ができないか試行錯誤してみました。


種明かし

最初に種明かしをしておきます。binfmtの環境をホストに作るのではなく、コンテナ上で動かしてchrootします。その際のポイントとして、


  • binfmt_miscをコンテナ実行時にマウントする

  • /proc/sys/fs/binfmt_misc/registerにarmefなELFを書き込む

  • コンテナ実行時はSYS_ADMIN,SYS_CHROOTを--cap-add で追加する

で実行できます。


Dockerfile

FROM ubuntu

RUN apt-get update && apt-get -y upgrade \
&& apt-get install -y \
qemu-user-static \
binfmt-support \
vim
RUN mkdir /raspi-root \
&& mkdir /app
ADD root.tar.gz /raspi-root
ADD start.sh /
RUN chmod +x start.sh
WORKDIR /raspi-root
CMD ["/start.sh"]

qemu-user-staticとbinfmt-supportがあれば十分です。rootイメージについては、"Raspbianをdebootstrapから作る"を参考にしてください。


start.sh

cd /raspi-root

mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-static:' > /proc/sys/fs/binfmt_misc/register
mount -t sysfs sysfs sys/ && \
mount -t proc proc proc/ && \
mount -o bind /dev dev/ && \
mount -o bind /dev/pts dev/pts
exec chroot . 動かしたいもの

実行時は、chrootの一般的なmountとbinfmt_miscのmount及びELFイメージの書き込みだけです。

(※sysfs,proc,devのmountは無くても問題ないかと思います。必要に応じてでいいかと…)


コンテナ実行

docker run -it --rm \

--name コンテナ名 \
--cap-add SYS_ADMIN --cap-add SYS_CHROOT \
イメージ名

です。


その他

上記の内容でDocker for Windows(Hyper-V版)で問題なく動いてます。多分、CentOS,CoreOS等でも実行できると思います。

コンパイル速度はクロスコンパイルに比べると、かなり遅くイライラします。が、あれこれ環境を作るよりも簡単ですし、本番環境も全く同じ環境でリビルドできたりするので、トータル的には良しとしています。