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.
起動失敗。
自分でビルドしたバイナリを使うのはあきらめた…。