into the void

ソフトウェアに関する雑多な調査日記

DockerをクロスコンパイルしてRaspberry Pi 3で動かしてみる

Dockerのソースコードをダウンロードして、ARMv7向けにクロスコンパイルしてみる。
クロスコパイル環境としてはさくらVPS上のUbuntuを使った。

まずはgithubで公開されているソースコードをダウンロード。

$ git clone https://github.com/docker/docker

make crossとするとクロスコンパイル用のDockerイメージがダウンロードされて、コンテナ上でクロスコンパイルが実行されるという仕組み。
ロスコンパイル用のツールチェーインなど用意する必要がなく非常に便利。

代わりにdocker環境は必要になるがすでにインストール済み。
今回のクロスビルドは一般ユーザでやりたいので、一般ユーザからもdockerコマンドが実行できるように、対象のユーザをdockerグループに追加していく。

$ sudo gpasswd -a <username> docker
$ make cross

x86環境のdockerバイナリをみると、依存ファイルがそこそこたくさんある。
クロスビルドした場合、これらの依存ライブラリはどういう形で提供されるのか? 考えながらmake完了を待つ。

$ ldd /usr/bin/docker
	linux-vdso.so.1 =>  (0x00007ffdd75b3000)
	libapparmor.so.1 => /usr/lib/x86_64-linux-gnu/libapparmor.so.1 (0x00007ff363654000)
	libsystemd-journal.so.0 => /lib/x86_64-linux-gnu/libsystemd-journal.so.0 (0x00007ff363439000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff36321b000)
	libdevmapper.so.1.02.1 => /lib/x86_64-linux-gnu/libdevmapper.so.1.02.1 (0x00007ff362fe2000)
	libltdl.so.7 => /usr/lib/x86_64-linux-gnu/libltdl.so.7 (0x00007ff362dd8000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff362a13000)
	libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007ff3627f0000)
	libcgmanager.so.0 => /lib/x86_64-linux-gnu/libcgmanager.so.0 (0x00007ff3625d5000)
	libnih.so.1 => /lib/x86_64-linux-gnu/libnih.so.1 (0x00007ff3623bd000)
	libnih-dbus.so.1 => /lib/x86_64-linux-gnu/libnih-dbus.so.1 (0x00007ff3621b3000)
	libdbus-1.so.3 => /lib/x86_64-linux-gnu/libdbus-1.so.3 (0x00007ff361f6e000)
	liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007ff361d4c000)
	libgcrypt.so.11 => /lib/x86_64-linux-gnu/libgcrypt.so.11 (0x00007ff361acc000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007ff3618c4000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ff363860000)
	libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007ff3616b3000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff3614af000)
	libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007ff361271000)
	libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007ff36106c000)

残念なことにメモリ不足でビルドが途中でエラー…。1GBでは足りなかったらしい。

---> Making bundle: dynbinary (in bundles/1.12.0-dev/dynbinary)
Building: bundles/1.12.0-dev/dynbinary-client/docker-1.12.0-dev
Created binary: bundles/1.12.0-dev/dynbinary-client/docker-1.12.0-dev
Building: bundles/1.12.0-dev/dynbinary-daemon/dockerd-1.12.0-dev
# github.com/docker/docker/cmd/dockerd
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: fork/exec /usr/bin/gcc: cannot allocate memory

make: *** [cross] Error 1

real	20m18.299s
user	0m4.724s
sys	0m2.415s

仕方ないのでMac用のDockerを使ってローカルでビルドしてみる。
https://docs.docker.com/docker-for-mac/

次はapt-getでエラー。IPv6でアクセスすると繋がらないサイトがあるらしい…。

E: Failed to fetch http://httpredir.debian.org/debian/pool/main/p/python-mock/python-mock_1.0.1-3_all.deb  Cannot initiate the connection to mirrors.tuna.tsinghua.edu.cn:80 (2402:f000:1:416:166:111:206:63). - connect (101: Network is unreachable) [IP: 2402:f000:1:416:166:111:206:63 80]

ルータのIPv6設定を無効化してリトライ。

...
Building: bundles/1.12.0-dev/cross/linux/386/docker-1.12.0-dev
Created binary: bundles/1.12.0-dev/cross/linux/386/docker-1.12.0-dev
Building: bundles/1.12.0-dev/cross/linux/arm/docker-1.12.0-dev
Created binary: bundles/1.12.0-dev/cross/linux/arm/docker-1.12.0-dev
...

real	29m40.215s
user	0m3.759s
sys	0m2.175s

今度は成功。様々な環境用にクロスビルドされるため、30分近くかかった…。

$ find ./bundles
./bundles
./bundles/1.12.0-dev
./bundles/1.12.0-dev/binary-client
./bundles/1.12.0-dev/binary-client/docker
./bundles/1.12.0-dev/binary-client/docker-1.12.0-dev
./bundles/1.12.0-dev/binary-client/docker-1.12.0-dev.md5
./bundles/1.12.0-dev/binary-client/docker-1.12.0-dev.sha256
./bundles/1.12.0-dev/binary-daemon
./bundles/1.12.0-dev/binary-daemon/docker-containerd
./bundles/1.12.0-dev/binary-daemon/docker-containerd-ctr
./bundles/1.12.0-dev/binary-daemon/docker-containerd-ctr.md5
./bundles/1.12.0-dev/binary-daemon/docker-containerd-ctr.sha256
./bundles/1.12.0-dev/binary-daemon/docker-containerd-shim
./bundles/1.12.0-dev/binary-daemon/docker-containerd-shim.md5
./bundles/1.12.0-dev/binary-daemon/docker-containerd-shim.sha256
./bundles/1.12.0-dev/binary-daemon/docker-containerd.md5
./bundles/1.12.0-dev/binary-daemon/docker-containerd.sha256
./bundles/1.12.0-dev/binary-daemon/docker-proxy
./bundles/1.12.0-dev/binary-daemon/docker-proxy-1.12.0-dev
./bundles/1.12.0-dev/binary-daemon/docker-proxy-1.12.0-dev.md5
./bundles/1.12.0-dev/binary-daemon/docker-proxy-1.12.0-dev.sha256
./bundles/1.12.0-dev/binary-daemon/docker-runc
./bundles/1.12.0-dev/binary-daemon/docker-runc.md5
./bundles/1.12.0-dev/binary-daemon/docker-runc.sha256
./bundles/1.12.0-dev/binary-daemon/dockerd
./bundles/1.12.0-dev/binary-daemon/dockerd-1.12.0-dev
./bundles/1.12.0-dev/binary-daemon/dockerd-1.12.0-dev.md5
./bundles/1.12.0-dev/binary-daemon/dockerd-1.12.0-dev.sha256
./bundles/1.12.0-dev/cross
./bundles/1.12.0-dev/cross/darwin
./bundles/1.12.0-dev/cross/darwin/amd64
./bundles/1.12.0-dev/cross/darwin/amd64/docker
./bundles/1.12.0-dev/cross/darwin/amd64/docker-1.12.0-dev
./bundles/1.12.0-dev/cross/darwin/amd64/docker-1.12.0-dev.md5
./bundles/1.12.0-dev/cross/darwin/amd64/docker-1.12.0-dev.sha256
./bundles/1.12.0-dev/cross/freebsd
./bundles/1.12.0-dev/cross/freebsd/386
./bundles/1.12.0-dev/cross/freebsd/386/docker
./bundles/1.12.0-dev/cross/freebsd/386/docker-1.12.0-dev
./bundles/1.12.0-dev/cross/freebsd/386/docker-1.12.0-dev.md5
./bundles/1.12.0-dev/cross/freebsd/386/docker-1.12.0-dev.sha256
./bundles/1.12.0-dev/cross/freebsd/amd64
./bundles/1.12.0-dev/cross/freebsd/amd64/docker
./bundles/1.12.0-dev/cross/freebsd/amd64/docker-1.12.0-dev
./bundles/1.12.0-dev/cross/freebsd/amd64/docker-1.12.0-dev.md5
./bundles/1.12.0-dev/cross/freebsd/amd64/docker-1.12.0-dev.sha256
./bundles/1.12.0-dev/cross/freebsd/arm
./bundles/1.12.0-dev/cross/freebsd/arm/docker
./bundles/1.12.0-dev/cross/freebsd/arm/docker-1.12.0-dev
./bundles/1.12.0-dev/cross/freebsd/arm/docker-1.12.0-dev.md5
./bundles/1.12.0-dev/cross/freebsd/arm/docker-1.12.0-dev.sha256
./bundles/1.12.0-dev/cross/linux
./bundles/1.12.0-dev/cross/linux/386
./bundles/1.12.0-dev/cross/linux/386/docker
./bundles/1.12.0-dev/cross/linux/386/docker-1.12.0-dev
./bundles/1.12.0-dev/cross/linux/386/docker-1.12.0-dev.md5
./bundles/1.12.0-dev/cross/linux/386/docker-1.12.0-dev.sha256
./bundles/1.12.0-dev/cross/linux/amd64
./bundles/1.12.0-dev/cross/linux/amd64/docker
./bundles/1.12.0-dev/cross/linux/amd64/docker-1.12.0-dev
./bundles/1.12.0-dev/cross/linux/amd64/docker-1.12.0-dev.md5
./bundles/1.12.0-dev/cross/linux/amd64/docker-1.12.0-dev.sha256
./bundles/1.12.0-dev/cross/linux/amd64/docker-containerd
./bundles/1.12.0-dev/cross/linux/amd64/docker-containerd-ctr
./bundles/1.12.0-dev/cross/linux/amd64/docker-containerd-ctr.md5
./bundles/1.12.0-dev/cross/linux/amd64/docker-containerd-ctr.sha256
./bundles/1.12.0-dev/cross/linux/amd64/docker-containerd-shim
./bundles/1.12.0-dev/cross/linux/amd64/docker-containerd-shim.md5
./bundles/1.12.0-dev/cross/linux/amd64/docker-containerd-shim.sha256
./bundles/1.12.0-dev/cross/linux/amd64/docker-containerd.md5
./bundles/1.12.0-dev/cross/linux/amd64/docker-containerd.sha256
./bundles/1.12.0-dev/cross/linux/amd64/docker-proxy
./bundles/1.12.0-dev/cross/linux/amd64/docker-proxy-1.12.0-dev
./bundles/1.12.0-dev/cross/linux/amd64/docker-proxy-1.12.0-dev.md5
./bundles/1.12.0-dev/cross/linux/amd64/docker-proxy-1.12.0-dev.sha256
./bundles/1.12.0-dev/cross/linux/amd64/docker-runc
./bundles/1.12.0-dev/cross/linux/amd64/docker-runc.md5
./bundles/1.12.0-dev/cross/linux/amd64/docker-runc.sha256
./bundles/1.12.0-dev/cross/linux/amd64/dockerd
./bundles/1.12.0-dev/cross/linux/amd64/dockerd-1.12.0-dev
./bundles/1.12.0-dev/cross/linux/amd64/dockerd-1.12.0-dev.md5
./bundles/1.12.0-dev/cross/linux/amd64/dockerd-1.12.0-dev.sha256
./bundles/1.12.0-dev/cross/linux/arm
./bundles/1.12.0-dev/cross/linux/arm/docker
./bundles/1.12.0-dev/cross/linux/arm/docker-1.12.0-dev
./bundles/1.12.0-dev/cross/linux/arm/docker-1.12.0-dev.md5
./bundles/1.12.0-dev/cross/linux/arm/docker-1.12.0-dev.sha256
./bundles/1.12.0-dev/cross/windows
./bundles/1.12.0-dev/cross/windows/386
./bundles/1.12.0-dev/cross/windows/386/docker-1.12.0-dev.exe
./bundles/1.12.0-dev/cross/windows/386/docker-1.12.0-dev.exe.md5
./bundles/1.12.0-dev/cross/windows/386/docker-1.12.0-dev.exe.sha256
./bundles/1.12.0-dev/cross/windows/386/docker.exe
./bundles/1.12.0-dev/cross/windows/amd64
./bundles/1.12.0-dev/cross/windows/amd64/docker-1.12.0-dev.exe
./bundles/1.12.0-dev/cross/windows/amd64/docker-1.12.0-dev.exe.md5
./bundles/1.12.0-dev/cross/windows/amd64/docker-1.12.0-dev.exe.sha256
./bundles/1.12.0-dev/cross/windows/amd64/docker-proxy-1.12.0-dev.exe
./bundles/1.12.0-dev/cross/windows/amd64/docker-proxy-1.12.0-dev.exe.md5
./bundles/1.12.0-dev/cross/windows/amd64/docker-proxy-1.12.0-dev.exe.sha256
./bundles/1.12.0-dev/cross/windows/amd64/docker-proxy.exe
./bundles/1.12.0-dev/cross/windows/amd64/docker.exe
./bundles/1.12.0-dev/cross/windows/amd64/dockerd-1.12.0-dev.exe
./bundles/1.12.0-dev/cross/windows/amd64/dockerd-1.12.0-dev.exe.md5
./bundles/1.12.0-dev/cross/windows/amd64/dockerd-1.12.0-dev.exe.sha256
./bundles/1.12.0-dev/cross/windows/amd64/dockerd.exe
./bundles/1.12.0-dev/dynbinary
./bundles/1.12.0-dev/dynbinary-client
./bundles/1.12.0-dev/dynbinary-client/docker
./bundles/1.12.0-dev/dynbinary-client/docker-1.12.0-dev
./bundles/1.12.0-dev/dynbinary-client/docker-1.12.0-dev.md5
./bundles/1.12.0-dev/dynbinary-client/docker-1.12.0-dev.sha256
./bundles/1.12.0-dev/dynbinary-daemon
./bundles/1.12.0-dev/dynbinary-daemon/docker-proxy
./bundles/1.12.0-dev/dynbinary-daemon/docker-proxy-1.12.0-dev
./bundles/1.12.0-dev/dynbinary-daemon/docker-proxy-1.12.0-dev.md5
./bundles/1.12.0-dev/dynbinary-daemon/docker-proxy-1.12.0-dev.sha256
./bundles/1.12.0-dev/dynbinary-daemon/dockerd
./bundles/1.12.0-dev/dynbinary-daemon/dockerd-1.12.0-dev
./bundles/1.12.0-dev/dynbinary-daemon/dockerd-1.12.0-dev.md5
./bundles/1.12.0-dev/dynbinary-daemon/dockerd-1.12.0-dev.sha256
./bundles/latest

目的のファイルはdocker-1.12.0-dev。大きな一つの実行可能バイナリになっている様子。

$ ls -al ./bundles/latest/cross/linux/arm/
total 22440
drwxr-xr-x  6 shizuku  staff       204  7  8 23:42 .
drwxr-xr-x  5 shizuku  staff       170  7  8 23:41 ..
lrwxrwxrwx  1 shizuku  staff        17  7  8 23:42 docker -> docker-1.12.0-dev
-rwxr-xr-x  1 shizuku  staff  11475574  7  8 23:42 docker-1.12.0-dev
-rw-r--r--  1 shizuku  staff        52  7  8 23:42 docker-1.12.0-dev.md5
-rw-r--r--  1 shizuku  staff        84  7  8 23:42 docker-1.12.0-dev.sha256

docker-1.12.0-devをraspberry pi 3上に持って行ってdaemonオプション付きで実行してみたが、下記のエラーが発生。

pi@raspberrypi:~ $ ./docker-1.12.0-dev daemon
`docker daemon` is not supported on Linux. Please run `dockerd` directly

dockerdなんてバイナリファイルはビルドされていない…。

debパッケージにもできるらしいのでやってみる。

Mac上のDockerではなぜか失敗。

仮想マシン上のUbuntu 14.04で再トライしたが失敗。

仕方がないので、ビルド済みのdebパッケージをダウンロードしてきてdpkgでインストール。
http://blog.hypriot.com/downloads/

動いた!

$ ps axuw | grep docker
root      1293 23.3  3.8 894328 36180 ?        Ssl  23:29   1:51 /usr/bin/docker daemon -H fd:// --storage-driver=overlay -D

イメージはarmhf用のものを指定する必要がある。ふつうにdocker run hello-worldとやるとx86用のhello-worldイメージが落ちてきてexec format errorとなる。

$ sudo docker search armhf
NAME                                       DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
armv7/armhf-ubuntu                         'official' Ubuntu Docker images for the AR...   31                   
container4armhf/armhf-alpine               Automatically built base images of Alpine ...   22                   [OK]
ioft/armhf-ubuntu                          [ABR] Ubuntu Docker images for the ARMv7(a...   14                   [OK]
armhf/ubuntu                               Ubuntu is a Debian-based Linux operating s...   5                    
armhf/debian                               Debian is a Linux distribution that's comp...   3                    
moul/armhf-busybox                                                                         2                    [OK]
werwolfby/armhf-alpine-transmission        Minimal alpine docker image for transmissi...   2                    [OK]
cburki/armhf-dev                           Armhf (Raspberry Pi) cross development wit...   2                    [OK]
ioft/armhf-debian                          Debian Docker images for the ARMv7(armhf) ...   1                    [OK]
werwolfby/armhf-alpine-gogs                ARM hf compatible Docker Image with a mini...   1                    [OK]
werwolfby/armhf-alpine-nginx               ARM hf compatible Docker Image with a mini...   1                    [OK]
msvb/armhf-iotempire                       Collection of software packages to accompa...   0                    [OK]
lalyos/armhf-syncthing                     http://docs.syncthing.net in a container f...   0                    [OK]
sheenhx/armhf-concentrator                 CC3200 serial concentrator for Beagle Bone...   0                    [OK]
ctarwater/armhf-alpine-rpi-glibc-builder   Docker container to build an Alpine glibc ...   0                    [OK]
ijoijo/armhf-alpine                        Alpine Linux image for armhf devices (like...   0                    [OK]
cricketeerone/armhf-logspout               A fork of gliderlabs/logspout using armhfb...   0                    [OK]
armv7/armhf-ubuntu_automated-build         This repo has moved to https://registry.hu...   0                    [OK]
kennethlimcp/armhf-ghost                   The awesome Ghost blog, on armhf                0                    [OK]
wontfix/gecko-armhf-dev                    Linux/armhf cross build environment for Gecko   0                    [OK]
mathewpeterson/armhf-php7                  This image extends the official armhf php ...   0                    [OK]
cailloumajor/debian-armhf-qemu             Debian armhf image with qemu-user-static        0                    [OK]
container4armhf/armhf-busybox              Automated build of Busybox for armhf devic...   0                    [OK]
fish/alpine-armhf-dumb-init                alpine-armhf-docker image with "dumb-init"...   0                    [OK]
mjschultz/ubuntu-armhf                                                                     0                    [OK]

登録されているイメージはあんまりない。

とりあえずUbuntuの公式イメージを動かしてみる。

pi@raspberrypi:~ $ sudo docker run -it armv7/armhf-ubuntu bash
root@1f7f91e7e990:/# uname -a
Linux 1f7f91e7e990 4.4.7-v7+ #1 SMP Thu Apr 21 02:16:07 JST 2016 armv7l armv7l armv7l GNU/Linux

Ubuntu動いた!

次はdebでいれたdockerバイナリを自分でビルドしたdockerバイナリと入れ替えてみる。

pi@raspberrypi:~ $ cd /usr/bin
pi@raspberrypi:/usr/bin $ which docker
/usr/bin/docker
pi@raspberrypi:/usr/bin $ sudo mv docker docker.org
pi@raspberrypi:/usr/bin $ sudo cp ~/docker-1.12.0-dev docker
pi@raspberrypi:/usr/bin $ docker -v
Docker version 1.12.0-dev, build dd1a27c

pi@raspberrypi:/usr/bin $ sudo service docker restart
Job for docker.service failed. See 'systemctl status docker.service' and 'journalctl -xn' for details.

起動失敗。

自分でビルドしたバイナリを使うのはあきらめた…。