業務の都合で、YoctoベースのARM組込Linux環境をx86_64環境下のDockerで動かす必要があり、ARM環境のRaspbianイメージをx86上のDockerで動かすを参考にSDカードイメージからdockerイメージを作成しました。その時、手順を間違えて、うっかりqemu-arm-static
を/usr/bin
にコピーしてない状態でコンテナを起動してしまったのですが、普通に起動してしまいqemu-arm-static
をインストールしてしていないことに丸一日気がつきませんでした。
一体どういうことなのか?
気になるので、ARM版nginxの公式dockerイメージをダウンロードしてコンテナを起動し検証してみます。arm32v7/nginx:latest
だと、apt-getもpsもインストールされていないので色々困りますからarm32v7/nginx:1.15.12-perl
のイメージを起動します。
$ docker run -it -p8080:80 arm32v7/nginx:1.15.12-perl /bin/bash
# ps -ef
bash: ps: command not found
psがないなんて軽量化しすぎな気もしますが… 仕方ないのでインストールします。
# apt-get update
Get:1 http://security-cdn.debian.org/debian-security stretch/updates InRelease [94.3 kB]
Ign:2 http://cdn-fastly.deb.debian.org/debian stretch InRelease
Get:3 http://cdn-fastly.deb.debian.org/debian stretch-updates InRelease [91.0 kB]
Get:4 http://cdn-fastly.deb.debian.org/debian stretch Release [118 kB]
Get:5 http://cdn-fastly.deb.debian.org/debian stretch Release.gpg [2434 B]
Get:6 http://security-cdn.debian.org/debian-security stretch/updates/main armhf Packages [477 kB]
Get:7 http://cdn-fastly.deb.debian.org/debian stretch-updates/main armhf Packages [31.5 kB]
Get:8 http://cdn-fastly.deb.debian.org/debian stretch/main armhf Packages [6912 kB]
Fetched 7726 kB in 13s (576 kB/s)
Reading package lists... Done
# apt-get install procps
# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 12:23 pts/0 00:00:00 /usr/bin/qemu-arm /bin/bash
root 20 1 0 May16 ? 00:00:00 /bin/ps -ef
参照した記事によると、qemu-arm-static
をコンテナの/usr/bin
にコピーしないと起動しないそうです。しかし、自分の環境では起動しますし/bin/bash
は/usr/bin/qemu-arm
を経由していることになっています。
解せぬ… (ローゼマイン風味)
ちなみに、自分の環境はmacOS Mojave 10.14.4に以下のDocker for Macをインストールしています。
本当にqemu-arm-static
はインストールされていないのでしょうか?カーネル情報とともに確認してみます。
# uname -r
4.9.125-linuxkit
# find / -name qemu-arm-static
#
カーネルはlinuxKitが使われているのでこれだけではARMかどうかは分かりません。しかし、少なくともコンテナ内にqemu-arm-static
が存在していないことだけは確実です。そこで、先ほどのapt-get update
で表示されたパッケージのダウンロード元がarmhf
になっているか確認します。
Get:8 http://cdn-fastly.deb.debian.org/debian stretch/main armhf Packages [6912 kB]
armhf
がありました。ARM向けのパッケージをダウンロードしていることから、ARM環境が動作していると考えて間違い無いようです。では、nginxを起動してブラウザからアクセスしてみます。
# /etc/init.d/nginx start
qemu: Unsupported syscall: 243
2019/05/18 08:43:07 [emerg] 372#372: io_setup() failed (38: Function not implemented)
おぅふ…😱
nginxプロセスが起動しているか確認します。
# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 00:42 pts/0 00:00:00 /usr/bin/qemu-arm /bin/bash
root 667 1 0 00:54 ? 00:00:00 /usr/bin/qemu-arm /usr/sbin/nginx
nginx 669 667 0 00:54 ? 00:00:00 /usr/bin/qemu-arm /usr/sbin/nginx
root 671 1 0 00:41 ? 00:00:00 /bin/ps -ef
とりあえず起動はしているようですので、ブラウザからlocalhost:8080
にアクセスしてみます。
ちゃんとアクセスできましたが、エラーが気になります。エラー内容はqemuがサポートしていない命令が使われたということなので、ひょっとすると最新版を/usr/bin
にインストールすると改善したりするかもしれません。ということで、 multiarch/qemu-user-static から最新版(本日時点では4.0)のqemu-arm-static.tar.gz
をダウロードしてコンテナ内にインストールしてみます。
wget
もインストールされていないので、まずはそこから…
$ apt-get install wget
$ cd /usr/bin
$ wget https://github.com/multiarch/qemu-user-static/releases/download/v4.0.0/qemu-arm-static.tar.gz
$ tar zxf qemu-arm-static.tar.gz
nginxを再起動してみます。
$ /etc/init.d/nginx restart
[....] Restarting nginx: nginxqemu: Unsupported syscall: 243
2019/05/18 08:17:58 [emerg] 176#176: io_setup() failed (38: Function not implemented)
ダメか…
こちらの yumでインストールしたnginxが起動時にエラーを吐くの巻 によると、コンパイルオプションを指定してビルドし直さないと治らないようです。
ちなみに、業務で使用しているYoctoベースのARM組込Linux環境では、qemu-arm-static
を4.0にアップグレードすると発生しなくなりました。
いずれにせよ、最新のDocker for Macの下で動かすのであれば、ARM版のdockerイメージをx86_64環境下で起動し動かすためにqemu-arm-static
をインストールする必要はなく、Docker for Macそのものにマルチアーキテクチャー対応の一部としてその機能は組み込まれているようです。
ただ、このイメージをクラウド上に展開しようとするならば、dockerエンジンのバージョンに依存しなくて済むよう、qemu-arm-static
をコンテナ内にインストールしておいたほうが無難なように思います。