吉方位確認サービス「楽方位」α版を公開しました。

Raspberry Pi 3 + Raspbian Stretch に、クロスコンパイルした MongoDB 3.2 をインストール

Sponsored Links

はじめに

Raspberry Pi Foundation の公式 OS である Debian ベースの Raspbian を使用します。使用した Raspbian の情報は以下の通りです。

  • Version: April 2019
  • Release date: 2019-04-08
  • Kernel version: 4.14

APT でインストールできる MongoDB のバージョンを調べてみます。

apt search mongodb

結果です。2.4 です。

mongodb/stable 1:2.4.14-4 armhf
  object/document-oriented database (metapackage)

2019-05-11 時点で、MongoDB の最新バージョンは 4.0 であり、2.4 はちょっと古いため (Spring Boot 2 の Spring Data MongoDB でもサポートされていない)、自分でビルドしてインストールしてみます。

自力でビルドしてインストールできたバージョンは 3.2

結論から先に書くと、Stable なバージョンで、自力でビルドに成功した最新のバージョンは 3.2 でした。

バージョン 4.0, 3.6, 3.4 はビルド中にエラーとなったり、ビルドに成功してもバイナリの実行時にエラーとなったりでした。

Raspberry Pi 3 で、最新のバージョンを使いたい場合

Raspbian は後方互換とイメージの管理コストを重要視しているように見受けられ、Raspbian の 64bit 版がリリースされる気配はありません。

https://www.raspberrypi.org/blog/raspbian-stretch/

No – 64-bit code will not run on Pi 0 or Pi 1, and we don’t at this stage want to support multiple images.

We will not be forking our Raspbian releases into 32-bit and 64-bit versions in the foreseeable future.

一方で、MongoDB は以前より 32bit のサポートをしていません。

Supported Platforms
Changed in version 3.4: MongoDB no longer supports 32-bit x86 platforms.

https://docs.mongodb.com/manual/installation/

少なくとも、3.4 では x86 のサポートが無くなりました。ARM 32bit については言及がありませんが、このタイミングでサポートが無くなったとみられます。実際、前述の通り、私の環境では 3.4 以上のバージョンを Raspbian で動かすことができませんでした。

よって、Raspberry Pi 3 で MongoDB の最新バージョンを使いたい場合は、Raspberry Pi 3 向けの 64bit OS をインストールし、MongoDB をビルドしてインストールするのが良いでしょう。

実際に Debian 10 Buster のプレビューイメージを Raspberry Pi 3 にインストールし、MongoDB 4.0 が動作することを確認しました。それについてはまた別途。

クロスコンパイル環境の構築

Raspberry Pi 3 上で MongoDB をソースコードからビルドするのは非常に時間がかかるとみられるため、Linux PC 上でクロスコンパイルします。

Ubuntu 18.04.2 で、crosstool-NG の Raspberry Pi 3 用のツールチェーンを使用してクロスコンパイル環境を構築したメモです。注意点としては、下記のメモ中にもあるように、glibc のバージョンを Raspbian Stretch に合わせて 2.24 に設定する必要があります。

ビルドの公式ドキュメント

https://github.com/mongodb/mongo/wiki/Build-Mongodb-From-Source

ビルド

pip のインストール

sudo apt-get -y install python-pip

ソースコードのダウンロード

mkdir ~/mongodbbuild
cd ~/mongodbbuild
git clone https://github.com/mongodb/mongo

必要なパッケージのダウンロード

cd mongo
pip install --user -r etc/pip/dev-requirements.txt

下記のようなメッセージが出力されましたが無視しました。

Collecting pylint==2.3.1 (from -r etc/pip/components/lint.req (line 3))
  Could not find a version that satisfies the requirement pylint==2.3.1 (from -r etc/pip/components/lint.req (line 3)) (from versions: 0.15.2, 0.16.0, 0.18.0, 0.18.1, 0.19.0, 0.20.0, 0.21.0, 0.21.1, 0.21.2, 0.21.3, 0.22.0, 0.23.0, 0.24.0, 0.25.0, 0.25.1, 0.25.2, 0.26.0, 0.27.0, 0.28.0, 1.0.0, 1.1.0, 1.2.0, 1.2.1, 1.3.0, 1.3.1, 1.4.0, 1.4.1, 1.4.2, 1.4.3, 1.4.4, 1.4.5, 1.5.0, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.5, 1.5.6, 1.6.0, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.6.5, 1.7.0, 1.7.1, 1.7.2, 1.7.3, 1.7.4, 1.7.5, 1.7.6, 1.8.0, 1.8.1, 1.8.2, 1.8.3, 1.8.4, 1.9.0, 1.9.1, 1.9.2, 1.9.3, 1.9.4)
No matching distribution found for pylint==2.3.1 (from -r etc/pip/components/lint.req (line 3))

実行

バージョン 3.2 の最新のタグ r3.2.22 に移動します。

そして、無検証の強引なやり方ですが、mozjs の arm64 向けソースを arm 用に丸ごとコピーします。これをしないと、クライアントである mongo のビルドが通りません。mongo バイナリが必要なければこのコピーは必要ありません。

scons.py の引数として core と設定すると、mongod, mongos, mongo の 3 つのバイナリのみが生成されます。

git checkout refs/tags/r3.2.22
cp -r src/third_party/mozjs-38/platform/arm64 src/third_party/mozjs-38/platform/arm
buildscripts/scons.py core \
  CC=/home/$USER/x-tools/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-gcc \
  CXX=/home/$USER/x-tools/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-g++ \
  --disable-warnings-as-errors \
  --js-engine=mozjs \
  --wiredtiger=off \
  --mmapv1=on \
  -j$(nproc)

Core i3-4170 の Linux PC 上で、数十分程かかりました。

下記の 3 つのバイナリが生成されます。

  • mongo
  • mongod
  • mongos

Raspbian での動作確認

Linux PC から SCP 等で Raspberry Pi 3 (Raspbian) に MongoDB のバイナリと MongoDB の設定ファイルと Systemd 用のファイルを転送します。

scp mongod mongos mongo ./debian/mongod.conf ./debian/mongod.service pi@192.168.xxx.yyy:/home/pi/

以降は、Raspberry Pi 3 (Raspbian) 上での作業の一例です。

MongoDB を実行するユーザーを作成してみます。

sudo useradd -M -s /bin/false mongodb

MongoDB 用のディレクトリを作成し、権限の設定を行います。

sudo mkdir /var/lib/mongodb
sudo chown mongodb:mongodb /var/lib/mongodb

sudo mkdir /var/log/mongodb
sudo chown mongodb:mongodb /var/log/mongodb

sudo mkdir /var/run/mongodb
sudo chown mongodb:mongodb /var/run/mongodb

バイナリを適当なディレクトリに配置させます。

sudo mv mongod /usr/bin/
sudo mv mongos /usr/bin/
sudo mv mongo /usr/bin/

MongoDB の設定ファイルを適当なディレクトリに配置させます。

sudo mv mongod.conf /etc/

その際、Storage Engine の設定を MMAPv1 にしておきます。

(snip)

storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true
  engine: mmapv1

(snip)

一通り作業が済めば、まずは手動で MongoDB を起動してみます。

sudo -u mongodb /usr/bin/mongod --config /etc/mongod.conf

/bin/mongo で接続確認してみるのも良いでしょう。

$ mongo
MongoDB shell version: 3.2.22
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
	http://docs.mongodb.org/
Questions? Try the support group
	http://groups.google.com/group/mongodb-user
Server has startup warnings: 
2019-05-10T19:41:09.580+0100 I CONTROL  [initandlisten] 
2019-05-10T19:41:09.580+0100 I CONTROL  [initandlisten] ** WARNING: This 32-bit MongoDB binary is deprecated
2019-05-10T19:41:09.580+0100 I CONTROL  [initandlisten] 
2019-05-10T19:41:09.580+0100 I CONTROL  [initandlisten] 
2019-05-10T19:41:09.581+0100 I CONTROL  [initandlisten] ** NOTE: This is a 32 bit MongoDB binary.
2019-05-10T19:41:09.581+0100 I CONTROL  [initandlisten] **       32 bit builds are limited to less than 2GB of data (or less with --journal).
2019-05-10T19:41:09.581+0100 I CONTROL  [initandlisten] **       See http://dochub.mongodb.org/core/32bit
2019-05-10T19:41:09.581+0100 I CONTROL  [initandlisten] 
>

問題なく動作すれば、いったん MondoDB を終了させます。

最後に Systemd の設定ファイルを配置させ、MongoDB を起動します。

sudo mv mongod.service /etc/systemd/system/
sudo systemctl enable mongod
sudo systemctl start mongod

Raspbian で MongoDB 4.0 が動かない理由

MongoDB 4.0 の Storage Engine には 3 つの選択肢があります。

https://docs.mongodb.com/manual/core/storage-engines/
  1. WiredTiger Storage Engine (Default)
  2. In-Memory Storage Engine
  3. MMAPv1 Storage Engine (Deprecated as of MongoDB 4.0)

しかし、いずれの Storage Engine も ARM 32bit をサポートしていません。

もしかすると私自身の理解が及ばず、実は Raspbian でも MongoDB 4.0 を動かす方法があるかもしれませんが。

WiredTiger

WiredTiger は、64bit のみのサポートとみられます。2018-12-12 時点の MongoDB の master ブランチの

https://github.com/wiredtiger/wiredtiger/blob/master/src/include/gcc.h

には、aarch64 についての記述はありますが、arm (32bit) についての記述がありません。実際、buildscripts/scons.py のオプションで、

--wiredtiger=on

の状態では、クロスコンパイルでエラーとなりました。

In-Memory

MongoDB Enterprise のみでサポートされているようです。

https://docs.mongodb.com/manual/core/storage-engines/

In-Memory Storage Engine is available in MongoDB Enterprise. Rather than storing documents on-disk, it retains them in-memory for more predictable data latencies.

MMAPv1

MongoDB 4.0 では、ARM 32bit をサポートしていません。

https://docs.mongodb.com/manual/core/mmapv1/

MMAPv1 is supported on 64-bit Intel architectures (x86_64) only. MongoDB returns an error when starting a mongod using MMAPv1 on an unsupported architecture.

実際、buildscripts/scons.py のオプションで、

--wiredtiger=off --mmapv1=on

と設定すると、ビルドは成功し、mongod のバイナリも生成されますが、Raspbian での実行時にエラーとなり起動しませんでした。

メモ

curl のクロスコンパイル

MongoDB 4.0 をビルドする際に curl のヘッダファイルと libcurl が必要だったため。

mkdir ~/temp/curl
cd ~/temp/curl
curl -O https://curl.haxx.se/download/curl-7.62.0.tar.gz
tar zxvf curl-7.62.0.tar.gz
cd curl-7.62.0
./configure CC=/home/$USER/x-tools/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-gcc \
  --host=armv8-rpi3-linux-gnueabihf
make -j$(nproc)

make 実行後に、lib/.libs 下に libcurl が生成されます。

libcurl.so -> libcurl.so.4.5.0
libcurl.so.4 -> libcurl.so.4.5.0
libcurl.so.4.5.0

gperftools のクロスコンパイル

結局ビルド時に無効化した gperftools

mkdir ~/temp/gperftools
cd ~/temp/gperftools
git clone https://github.com/gperftools/gperftools
cd gperftools
./autogen.sh
./configure CC=/home/$USER/x-tools/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-gcc \
  --host=armv8-rpi3-linux-gnueabihf

config.h を third-party の build_linux_arm に。

build

buildscripts/scons.py mongod mongo mongos \
  CC=/home/$USER/x-tools/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-gcc \
  CXX=/home/$USER/x-tools/armv8-rpi3-linux-gnueabihf/bin/armv8-rpi3-linux-gnueabihf-g++ \
  --ssl=off \
  CPPPATH=/home/$USER/temp/curl/curl-7.62.0/include \
  LIBPATH=/home/$USER/temp/curl/curl-7.62.0/lib/.libs \
  --disable-warnings-as-errors \
  --js-engine=none \
  --wiredtiger=off \
  --mmapv1=on \
  --allocator=system \
  --use-system-tcmalloc \
  -j$(nproc)