Raspberry PI(Raspbian)開発環境をx86_64マシン上に構築する

#はじめに
2019年の年末に、年末だからという理由だけでラズパイ(Raspberry PI Zero W)を購入しました。で、冬休みにいろいろ触ってみたのですが、やっぱり動作が重たいんですよねぇ。さらに、SDカードも32GBでそれほど余裕もなく。なので、ラズパイ上に開発環境を構築してアプリを開発しようという夢は諦めて、x86_64マシンに開発環境を構築して、アプリ開発を行うことにしました。
本記事は、開発環境をx86_64マシン上に構築するための手順やその時ハマった内容などを、備忘録として記載したものです。

###開発環境概要
開発環境構築作業は、以下のホスト上で行いました。

- ホスト：Ubuntu 18.04LTS

また、開発環境はDockerを使ってコンテナ上に構築しています。コンテナを利用することで、ホストの環境を汚すことなく開発環境構築が行えます。

- Docker Version：19.03.5

ラズパイ用OSは、Raspbian Liteを使用しました。

- Raspbian Buster Lite(Minimal image based on Debian Buster)
  - Version：September 2019
  - Release date：2019-09-26
  - Kernel version：4.19

つまり、Raspbian(buster)コンテナイメージを作成し、そのイメージを使って開発環境を構築するということです。
但し、RaspbianはARM系アーキテクチャマシンで動作するバイナリですので、単純にDockerで立ち上げても動作しませんので、QEMUエミュレータを使用して動作させることになります。

#構築手順
実際の手順については、[こちら](https://qiita.com/hishi/items/61652e2d9755e17630de)の記事がわかりやすいので、そちらを参照してください。手順概要は以下です。
1. Dockerでベースコンテナの準備
　開発環境構築作業用コンテナを立ち上げます。
2. Raspbian Buster Liteのイメージファイルのマウント
　立ち上げたコンテナ内で、Raspbian Buster Liteイメージファイルをマウントします。
3. Raspbian Buster Liteのファイル群の取得(tarで固める)
　イメージをマウントすることで、OSファイルが参照出来ますので、tarで固めて取得します。
　また、QEMUを利用してARM系の実行ファイルをx86_64で動作させるため、qemu-arm-staticツールを格納しておきます。
4. 取得したファイル群で、コンテナイメージを作成
　作成したtarファイルを利用して、コンテナイメージを作成します。　
5. 作成したコンテナイメージで、コンテナを作成・起動
　作成したコンテナイメージでコンテナを立ち上げます。これで、RaspbianOSのコンテナが立ち上がります。

上記で、コンテナは問題なく立ち上がり、ラズパイ用アプリの開発は行えるのですが、ホストPCを再起動した後にコンテナを立ち上げようとすると、以下のようになって、コンテナが立ち上がらなくなります。

```container:container
$ docker start -i 8d1086983af8
standard_init_linux.go:211: exec user process caused "exec format error"
```
いろいろ調べたら、x86_64環境で他のアーキテクチャのバイナリ(コンテナ)を実行する方法について紹介されていた資料を見つけました。

- [Raspberry Pi用のコンテナをクラウドでビルドする方法](https://www.slideshare.net/ShunsukeKikuchi1/raspberry-pi-147400803)

その中で、x86_64環境で他のアーキテクチャのバイナリ(コンテナ)を実行する場合は、事前に以下のコマンドを実行する必要があるとのこと。

``` host:host
docker run --rm --privileged multiarch/qemu-user-static --reset
```

これで異なるアーキテクチャのバイナリ(コンテナ)を実行することが出来ます。

```host:host
$ docker run --rm --privileged multiarch/qemu-user-static --reset
Unable to find image 'multiarch/qemu-user-static:latest' locally
latest: Pulling from multiarch/qemu-user-static
bdbbaa22dec6: Pull complete 
42399a41a764: Pull complete 
ed8a5179ae11: Pull complete 
1ec39da9c97d: Pull complete 
df7dd9470aac: Pull complete 
Digest: sha256:25d6e8bb037094525cd70da43edc06a62122028cb9ad434605affbd4fffb3a4f
Status: Downloaded newer image for multiarch/qemu-user-static:latest
Setting /usr/bin/qemu-alpha-static as binfmt interpreter for alpha
Setting /usr/bin/qemu-arm-static as binfmt interpreter for arm
Setting /usr/bin/qemu-armeb-static as binfmt interpreter for armeb
Setting /usr/bin/qemu-sparc-static as binfmt interpreter for sparc
Setting /usr/bin/qemu-sparc32plus-static as binfmt interpreter for sparc32plus
Setting /usr/bin/qemu-sparc64-static as binfmt interpreter for sparc64
Setting /usr/bin/qemu-ppc-static as binfmt interpreter for ppc
Setting /usr/bin/qemu-ppc64-static as binfmt interpreter for ppc64
Setting /usr/bin/qemu-ppc64le-static as binfmt interpreter for ppc64le
Setting /usr/bin/qemu-m68k-static as binfmt interpreter for m68k
Setting /usr/bin/qemu-mips-static as binfmt interpreter for mips
Setting /usr/bin/qemu-mipsel-static as binfmt interpreter for mipsel
Setting /usr/bin/qemu-mipsn32-static as binfmt interpreter for mipsn32
Setting /usr/bin/qemu-mipsn32el-static as binfmt interpreter for mipsn32el
Setting /usr/bin/qemu-mips64-static as binfmt interpreter for mips64
Setting /usr/bin/qemu-mips64el-static as binfmt interpreter for mips64el
Setting /usr/bin/qemu-sh4-static as binfmt interpreter for sh4
Setting /usr/bin/qemu-sh4eb-static as binfmt interpreter for sh4eb
Setting /usr/bin/qemu-s390x-static as binfmt interpreter for s390x
Setting /usr/bin/qemu-aarch64-static as binfmt interpreter for aarch64
Setting /usr/bin/qemu-aarch64_be-static as binfmt interpreter for aarch64_be
Setting /usr/bin/qemu-hppa-static as binfmt interpreter for hppa
Setting /usr/bin/qemu-riscv32-static as binfmt interpreter for riscv32
Setting /usr/bin/qemu-riscv64-static as binfmt interpreter for riscv64
Setting /usr/bin/qemu-xtensa-static as binfmt interpreter for xtensa
Setting /usr/bin/qemu-xtensaeb-static as binfmt interpreter for xtensaeb
Setting /usr/bin/qemu-microblaze-static as binfmt interpreter for microblaze
Setting /usr/bin/qemu-microblazeel-static as binfmt interpreter for microblazeel
Setting /usr/bin/qemu-or1k-static as binfmt interpreter for or1k
fujita@Inspiron-11-3162:~$ docker start -i 8d1086983af8
root@8d1086983af8:/# 
```
makeやgccなどはすでにインストール済みなので、C言語での開発ならすぐに始めることができます。

#おまけ
マルチアーキテクチャのコンテナイメージがGitHubで公開されています。

- [qemu-user-static](https://github.com/multiarch)