qemu-debootstrapを使ってユーザモードQEMUで動くDockerイメージを作ってみる

「DockerでユーザモードQEMUによるARMエミュレーション環境を構築する」では、mazzolino/armhf-ubuntuというDockerイメージを使ってqemu-user-staticによるARM版Ubuntuのエミュレーション環境を構築した。 ここでは、qemu-debootstrapを使ってARM版DebianのDockerイメージを作成してみる。 また、作成したDockerイメージをDocker Hubに公開してみる。

環境

Ubuntu 14.04.3 LTS 64bit版、Docker 1.9.1

$ uname -a
Linux vm-ubuntu64 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:16:20 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.3 LTS
Release:        14.04
Codename:       trusty

$ sudo docker version
Client:
 Version:      1.9.1
 API version:  1.21
 Go version:   go1.4.2
 Git commit:   a34a1d5
 Built:        Fri Nov 20 13:12:04 UTC 2015
 OS/Arch:      linux/amd64

Server:
 Version:      1.9.1
 API version:  1.21
 Go version:   go1.4.2
 Git commit:   a34a1d5
 Built:        Fri Nov 20 13:12:04 UTC 2015
 OS/Arch:      linux/amd64

chroot環境の構築

まず、qemu-debootstrapコマンドでchroot環境を構築する。 qemu-debootstrapはdebootstrapのラッパーであり、qemu-user-staticの配置とbinfmtの登録を合わせて行ってくれる。

必要なパッケージを次のようにしてインストールする。

$ sudo apt-get install debootstrap qemu-user-static

qemu-debootstrapコマンドを使ってchroot環境を構築する。 コマンドラインの意味は次の通り。

  • --verbose: 詳細なログを出力する
  • --arch=armel: armelアーキテクチャ環境を作る
  • --variant=buildd: 最小限のパッケージ群であるminbaseに加えbuild-essentialsをインストールする
  • --include=gdb,vim-tiny,less: 追加でgdb、vi、lessをインストールする
  • jessie: 現在の安定板であるjessie(バージョン8)をインストールする
  • rootfs-debian-armel: 作成するディレクトリ名
  • http://ftp.jp.debian.org/debian/: Debianリポジトリ(日本のミラーサイト)を利用する
$ sudo qemu-debootstrap --verbose --arch=armel --variant=buildd --include=gdb,vim-tiny,less jessie rootfs-debian-armel http://ftp.jp.debian.org/debian/
I: Running command: debootstrap --arch armel --foreign --verbose --variant=buildd --include=gdb,vim-tiny,less jessie rootfs-debian-armel http://ftp.jp.debian.org/debian/
W: Cannot check Release signature; keyring file not available /usr/share/keyrings/debian-archive-keyring.gpg
I: Retrieving Release
I: Retrieving Packages
I: Validating Packages
I: Resolving dependencies of required packages...
I: Resolving dependencies of base packages...
I: Found additional required dependencies: acl adduser dmsetup insserv libaudit-common libaudit1 libbz2-1.0 libcap2 libcap2-bin libcryptsetup4 libdb5.3 libdebconfclient0 libdevmapper1.02.1 libgcrypt20 libgpg-error0 libkmod2 libncursesw5 libprocps3 libsemanage-common libsemanage1 libslang2 libsystemd0 libudev1 libustr-1.0-1 procps systemd systemd-sysv udev
I: Found additional base dependencies: binutils bzip2 cpp cpp-4.9 debian-archive-keyring dpkg-dev g++ g++-4.9 gcc gcc-4.9 gnupg gpgv libapt-pkg4.12 libasan1 libatomic1 libc-dev-bin libc6-dev libcloog-isl4 libdpkg-perl libexpat1 libffi6 libgcc-4.9-dev libgdbm3 libgmp10 libgomp1 libisl10 libmpc3 libmpfr4 libpython2.7 libpython2.7-minimal libpython2.7-stdlib libreadline6 libsqlite3-0 libssl1.0.0 libstdc++-4.9-dev libstdc++6 libtimedate-perl libubsan0 libusb-0.1-4 linux-libc-dev make mime-support patch perl perl-modules readline-common vim-common xz-utils
I: Checking component main on http://ftp.jp.debian.org/debian...
I: Retrieving acl 2.2.52-2
I: Validating acl 2.2.52-2
I: Retrieving libacl1 2.2.52-2
I: Validating libacl1 2.2.52-2
(snip)
I: Configuring build-essential...
I: Configuring libc-bin...
I: Base system installed successfully.

作成された環境にchrootして、ARMエミュレーションできていることを確認してみる。

$ sudo chroot rootfs-debian-armel/ uname -a
Linux vm-ubuntu64 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:16:20 UTC 2015 armv7l GNU/Linux

$ sudo chroot rootfs-debian-armel/ cat /etc/debian_version
8.2

$ sudo chroot rootfs-debian-armel/ objdump -d /bin/bash | head

/bin/bash:     file format elf32-littlearm


Disassembly of section .init:

000282fc <_init>:
   282fc:       e92d4008        push    {r3, lr}
   28300:       eb000c39        bl      2b3ec <_start+0x3c>
   28304:       e8bd4008        pop     {r3, lr}

作成された状態はapt lineが空となっており、新規パッケージのインストールができない。 そこで、sources.listにmain、updates、securityのリポジトリを追加し読み込んでおく。

$ cat <<__EOF__ >sources.list
deb http://httpredir.debian.org/debian jessie main
deb http://httpredir.debian.org/debian jessie-updates main
deb http://security.debian.org jessie/updates main
__EOF__

$ sudo mv sources.list rootfs-debian-armel/etc/apt/sources.list

$ sudo chroot rootfs-debian-armel/ apt-get update
$ sudo chroot rootfs-debian-armel/ apt-get upgrade
$ sudo chroot rootfs-debian-armel/ apt-get clean

Docker imageへの変換・インポート

Dockerイメージに変換するには、chrootするディレクトリをtarで固めてインポートすればよい。 ここでは慣習にならい、jessieの他にlatestとバージョン番号のタグも付けておく。

$ sudo tar --numeric-owner --create --directory rootfs-debian-armel/ . | sudo docker import - inaz2/debian-armel:jessie
4e878bc46c1d6813c91993d995926c5846ba7b08982d87142ca1459393df7ea2
$ sudo docker tag inaz2/debian-armel:jessie inaz2/debian-armel:latest
$ sudo docker tag inaz2/debian-armel:jessie inaz2/debian-armel:8.2

変換したイメージをもとに、コンテナの作成と起動を行ってみる。

$ sudo docker run --name debian-armel -i -t inaz2/debian-armel:jessie /bin/bash
root@5f811c822c94:/# exit

$ sudo docker start -a -i debian-armel
root@5f811c822c94:/# uname -a
Linux 5f811c822c94 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:16:20 UTC 2015 armv7l GNU/Linux
root@5f811c822c94:/# ps auxf
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  1.5  0.5 4137520 11448 ?       Ss   10:10   0:00 /usr/bin/qemu-arm-static /bin/bash
root         7  0.0  0.3 4137520 6368 ?        R+   09:51   0:00 /usr/bin/qemu-arm-static /bin/ps auxf
root@5f811c822c94:/# exit

期待した通りに動作していることが確認できる。

Docker Hubへのアップロード

このイメージを他のマシンでもダウンロードできるように、Docker Hubに公開してみる。 Webサイトからアカウントを作成した後、次のようにしてログイン、アップロードする。

$ sudo docker login
Username: inaz2
Password:
Email: [deducted]
WARNING: login credentials saved in /home/user/.docker/config.json
Login Succeeded

$ sudo docker push inaz2/debian-armel
The push refers to a repository [docker.io/inaz2/debian-armel] (len: 3)
4e878bc46c1d: Pushed
8.2: digest: sha256:9b8079649f76f38d82fe44d5cb88864d8898d670b231b4e679e9f8cc594f987b size: 1199
jessie: digest: sha256:0fd97b6b78361ade41a05f11622d7bb3f04019943e02d4998a90c3bffa557a63 size: 1202
latest: digest: sha256:1ecb4edf9feeaaadc9659fa65ddd0c3105f9ccd2fbf2f12eb7fc341144f4d989 size: 1202

Docker Hubのイメージを利用する

ここまでの内容を他のアーキテクチャに対しても行い、以下の5つのイメージを公開した(ビルドスクリプト)。 なお、これら以外のアーキテクチャmips、mipsel、ppc64el)は、qemu-debootstrap中にエラーが発生し作成できなかった。

inaz2/debian-arm64をダウンロードしてAArch64のエミュレーション環境を利用してみる。

$ sudo docker run --name debian-arm64 -i -t inaz2/debian-arm64 /bin/bash
Unable to find image 'inaz2/debian-arm64:latest' locally
latest: Pulling from inaz2/debian-arm64
df499e76b3a4: Pull complete
Digest: sha256:08589a1fd3fdb3d7ea2f53a410114d6eb63a2a304a390da43cfb7d9d12a4e5bf
Status: Downloaded newer image for inaz2/debian-arm64:latest
root@3d093a136244:/# uname -a
Linux 3d093a136244 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:16:20 UTC 2015 aarch64 GNU/Linux
root@3d093a136244:/# objdump -d /bin/bash | head

/bin/bash:     file format elf64-littleaarch64


Disassembly of section .init:

000000000041d8d8 <_init>:
  41d8d8:       a9bf7bfd        stp     x29, x30, [sp,#-16]!
  41d8dc:       910003fd        mov     x29, sp
  41d8e0:       94000c8c        bl      420b10 <_start+0x48>
root@3d093a136244:/# exit

コマンドの出力結果から、AArch64のエミュレーションができていることが確認できる。

関連リンク