Edited at

RaspbianをDockerイメージに変換する


3行まとめ


  1. Raspbianのイメージファイルからファイルシステムをtarファイルとして抽出する。


  2. docker image importtarファイルをインポートし、Dockerイメージに変換する。

  3. QEMUを用いてRaspbianのDockerイメージをx86_64環境で起動する。


1. 概要

 Raspberry Pi用のLinuxディストリビューションである「Raspbian」には公式Dockerイメージがありません。(非公式イメージであればDocker Hubにいくつかあります)

セキュリティなどの懸念もあり、業務では非公式イメージは使いづらいのが実情です。

 そこで、Raspbianのイメージファイル(*.img)からDockerイメージを作成してみました。また、ARMv7版RaspbianのDockerイメージをx86_64環境で動作させてみました。

2019年9月11日12時55分追記: mt08さんからのコメントによると、Raspbianは公式のルートファイルシステムが別途配布されているとのことです。そのため、「4. ファイルシステムの抽出」の手順は不要です。


2. 環境

 今回試した環境は以下の通りです。


  • OS: Ubuntu 16.04.5 LTS

  • Docker: 18.09.4

host$ cat /etc/lsb-release

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.5 LTS"

host$ docker version
Client:
Version: 18.09.4
API version: 1.39
Go version: go1.10.8
Git commit: d14af54
Built: Wed Mar 27 18:34:51 2019
OS/Arch: linux/amd64
Experimental: false

Server: Docker Engine - Community
Engine:
Version: 18.09.4
API version: 1.39 (minimum version 1.12)
Go version: go1.10.8
Git commit: d14af54
Built: Wed Mar 27 18:01:48 2019
OS/Arch: linux/amd64
Experimental: false


3. 対象イメージ

 今回の対象イメージは「Raspbian Stretch Lite」(2019-04-08版)です。

host$ wget https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-04-09/2019-04-08-raspbian-stretch-lite.zip

host$ ls -l 2019-04-08-raspbian-stretch-lite.zip
-rw-rw-r-- 1 yuya yuya 368729233 Apr 8 19:26 2019-04-08-raspbian-stretch-lite.zip

host$ sha256sum 2019-04-08-raspbian-stretch-lite.zip
03ec326d45c6eb6cef848cf9a1d6c7315a9410b49a276a6b28e67a40b11fdfcf 2019-04-08-raspbian-stretch-lite.zip

host$ unzip 2019-04-08-raspbian-stretch-lite.zip
host$ ls -l 2019-04-08-raspbian-stretch-lite.img
-rw-r--r-- 1 yuya yuya 1803550720 Apr 8 11:25 2019-04-08-raspbian-stretch-lite.img

host$ sha256sum 2019-04-08-raspbian-stretch-lite.img
d4e7d2caa051432a3b6f320c44939b9f65fd454d957904d1cb9fc1c1683ed716 2019-04-08-raspbian-stretch-lite.img


4. ファイルシステムの抽出

 まず、イメージファイルをマウントし、ファイルシステムを抽出します。

Dockerコンテナ上にイメージファイルをマウントする方法については別記事『Dockerコンテナ上でイメージファイルをマウントする』をご参照ください。

以下、Dockerホスト側のプロンプトをhost$、Dockerコンテナ内のプロンプトをdocker$で示します。

host$ docker container run --interactive --tty --rm --privileged \

--volume $(pwd):/workspace \
ubuntu:18.04

docker$ apt-get update && apt-get install --yes --no-install-recommends parted
docker$ parted /workspace/2019-04-08-raspbian-stretch-lite.img unit B print
Model: (file)
Disk /workspace/2019-04-08-raspbian-stretch-lite.img: 1803550720B
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number Start End Size Type File system Flags
1 4194304B 49174015B 44979712B primary fat32 lba
2 50331648B 1803550719B 1753219072B primary ext4

docker$ mkdir --parents /mnt/image
docker$ mount --options loop,offset=50331648 /workspace/2019-04-08-raspbian-stretch-lite.img /mnt/image
docker$ ls -l /mnt/image
total 88
drwxr-xr-x 2 root root 4096 Apr 8 09:51 bin
drwxr-xr-x 2 root root 4096 Apr 8 10:24 boot
drwxr-xr-x 4 root root 4096 Apr 8 09:39 dev
drwxr-xr-x 84 root root 4096 Apr 8 10:25 etc
drwxr-xr-x 3 root root 4096 Apr 8 09:48 home
drwxr-xr-x 16 root root 4096 Apr 8 09:58 lib
drwx------ 2 root root 16384 Apr 8 10:24 lost+found
drwxr-xr-x 2 root root 4096 Apr 8 09:37 media
drwxr-xr-x 2 root root 4096 Apr 8 09:37 mnt
drwxr-xr-x 3 root root 4096 Apr 8 09:48 opt
drwxr-xr-x 2 root root 4096 Feb 17 2019 proc
drwx------ 2 root root 4096 Apr 8 09:37 root
drwxr-xr-x 5 root root 4096 Apr 8 09:49 run
drwxr-xr-x 2 root root 4096 Apr 8 09:59 sbin
drwxr-xr-x 2 root root 4096 Apr 8 09:37 srv
drwxr-xr-x 2 root root 4096 Feb 17 2019 sys
drwxrwxrwt 2 root root 4096 Apr 8 10:25 tmp
drwxr-xr-x 10 root root 4096 Apr 8 09:37 usr
drwxr-xr-x 11 root root 4096 Apr 8 09:37 var

docker$ tar cfv /workspace/2019-04-08-raspbian-stretch-lite.tar -C /mnt/image .
docker$ ls -l /workspace/2019-04-08-raspbian-stretch-lite.tar
-rw-r--r-- 1 root root 856811520 Sep 10 07:38 /workspace/2019-04-08-raspbian-stretch-lite.tar

docker$ tar tfv /workspace/2019-04-08-raspbian-stretch-lite.tar | head
drwxr-xr-x root/root 0 2019-04-08 09:46 ./
drwxr-xr-x root/root 0 2019-04-08 10:24 ./boot/
drwx------ root/root 0 2019-04-08 10:24 ./lost+found/
drwxr-xr-x root/root 0 2019-02-17 15:05 ./proc/
drwxr-xr-x root/root 0 2019-04-08 09:39 ./dev/
crw------- root/tty 4,1 2019-04-08 09:39 ./dev/tty1
crw-rw---- root/audio 14,48 2019-04-08 09:39 ./dev/mixer3
crw-rw---- root/audio 35,131 2019-04-08 09:39 ./dev/smpte3
crw-rw---- root/audio 35,3 2019-04-08 09:39 ./dev/midi3
brw-rw---- root/disk 1,2 2019-04-08 09:38 ./dev/ram2

 イメージファイルの内容を2019-04-08-raspbian-stretch-lite.tarとして抽出することができました。


5. Dockerイメージへの変換

 続いて、tarファイルをDockerイメージに変換(インポート)します。

host$ docker image import 2019-04-08-raspbian-stretch-lite.tar raspbian-stretch-lite:2019-04-08

host$ docker image ls raspbian-stretch-lite
REPOSITORY TAG IMAGE ID CREATED SIZE
raspbian-stretch-lite 2019-04-08 b53519ee6f33 22 seconds ago 828MB

 tarファイルをDockerイメージとしてインポートすることができました。


6. 異なるCPUアーキテクチャのDockerイメージを実行

 上記のDockerイメージはARMv7用のDockerイメージであるため、当然ながらx86_64環境ではそのまま実行できません。

ここではCPUエミュレータである「QEMU」を使うことで、x86_64環境上でARMv7のDockerイメージを動かしてみます。

host$ sudo apt-get update && sudo apt-get install --yes --no-install-recommends qemu-user-static

host$ docker container run --interactive --tty --rm \
--volume /usr/bin/qemu-arm-static:/usr/bin/qemu-arm-static \
raspbian-stretch-lite:2019-04-08 \
/bin/bash

docker$ arch
armv7l

docker$ cat /etc/debian_version
9.8

 無事に動作しました。


6.1. エラー例: QEMUを使用しない場合

host$ docker container run --interactive --tty --rm \

raspbian-stretch-lite:2019-04-08 \
/bin/bash
standard_init_linux.go:207: exec user process caused "no such file or directory"


7. 応用: クロスビルド用のルートファイルシステムの作成

 上記のDockerイメージを活用することで「Raspbian向けクロスビルド環境のためのルートファイルシステムの作成」なども行うことができます。

OpenCVをインストールしたルートファイルシステムを作成する具体例を以下に示します。

host$ docker container run --interactive --tty \

--volume /usr/bin/qemu-arm-static:/usr/bin/qemu-arm-static \
--name raspbian_cross_build \
raspbian-stretch-lite:2019-04-08 \
/bin/bash

docker$ apt-get update && apt-get install --yes --no-install-recommends libopencv-dev
docker$ rm --recursive --force /var/lib/apt/lists/*
docker$ exit

host$ docker container export raspbian_cross_build > raspbian_cross_build.tar
host$ tar tf raspbian_cross_build.tar | sort | head
bin/
bin/bash
bin/bunzip2
bin/bzcat
bin/bzcmp
bin/bzdiff
bin/bzegrep
bin/bzexe
bin/bzfgrep
bin/bzgrep


8. 参考