Edited at

Dockerコンテナ上でイメージファイルをマウントする


3行まとめ



  1. partedコマンドでバイト単位のパーティション開始位置を確認する。


  2. docker container runコマンドに--privilegedオプションを付加する。


  3. mount --options loop,offset=[オフセット値] [イメージファイル] [マウント先]でマウントする。


1. 概要

 Dockerコンテナ内でイメージファイル(例えばOSイメージ)をマウントしたいことがあります。

毎回似たようなことを調べているので、整理も兼ねて具体例をここに記しておきます。

2019年9月11日12時55分追記: mt08さんからのコメントによると、Raspbianは公式のルートファイルシステムが別途配布されているとのことです。そのため、Raspbianを対象にこれらを行うことにはほとんど意味がありませんが、他のイメージファイルでは有用かと思います。


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. 対象イメージ

 今回の対象イメージは、Raspberry Pi用のLinuxディストリビューションである「Raspbian Buster Lite」(2019-07-10版)です。

Dockerコンテナ内でダウンロードしても良いですが、試行錯誤を容易にするため、Dockerコンテナの外側でダウンロードしました。

host$ wget https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-07-12/2019-07-10-raspbian-buster-lite.zip

host$ ls -l 2019-07-10-raspbian-buster-lite.zip
-rw-rw-r-- 1 yuya yuya 426250971 Jul 10 09:23 2019-07-10-raspbian-buster-lite.zip

host$ sha256sum 2019-07-10-raspbian-buster-lite.zip
9e5cf24ce483bb96e7736ea75ca422e3560e7b455eee63dd28f66fa1825db70e 2019-07-10-raspbian-buster-lite.zip

host$ unzip 2019-07-10-raspbian-buster-lite.zip
host$ sha256sum 2019-07-10-raspbian-buster-lite.img
cce3cdaa078597d0b2181f7e121a452346c72bca9095893e56e01c82e524c276 2019-07-10-raspbian-buster-lite.img


4. Dockerコンテナ内でのマウント

 今回はUbuntu 18.04のDockerコンテナ上で作業を行いました。

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

host$ docker image pull ubuntu:18.04

18.04: Pulling from library/ubuntu
Digest: sha256:d1d454df0f579c6be4d8161d227462d69e163a8ff9d20a847533989cf0c94d90
Status: Image is up to date for ubuntu:18.04

host$ docker container run --interactive --tty --rm --privileged \
--volume $(pwd):/workspace \
ubuntu:18.04

 まず、イメージファイルに含まれるパーティションと、その位置(オフセット)を確認します。

今回のイメージには2つのパーティション(FAT32とext4)が含まれており、2つ目のパーティションが目的のパーティションです。このパーティションのStartの値(今回は276824064)を控えておきます。

 partedではなくfdiskでも確認できますが、セクタ単位で表示されるためバイト単位に換算が必要です。partedであればバイト単位で表示できます。

docker$ apt-get update && apt-get install --yes --no-install-recommends parted

docker$ parted /workspace/2019-07-10-raspbian-buster-lite.img unit B print
Model: (file)
Disk /workspace/2019-07-10-raspbian-buster-lite.img: 2197815296B
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number Start End Size Type File system Flags
1 4194304B 272630271B 268435968B primary fat32 lba
2 276824064B 2197815295B 1920991232B primary ext4

 続いて、イメージファイルをマウントします。mountコマンドのoffset=に、先ほど控えた値(パーティションの開始位置)を指定します。

マウントが成功すると、イメージファイルの内容を確認することができます。

docker$ mkdir --parents /mnt/image

docker$ mount --options loop,offset=276824064 /workspace/2019-07-10-raspbian-buster-lite.img /mnt/image

docker$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 80K 0 loop
loop1 7:1 0 80K 0 loop
loop2 7:2 0 1.8G 0 loop /mnt/image
sda 8:0 0 3.7T 0 disk
`-sda1 8:1 0 3.7T 0 part /workspace
sdb 8:16 0 232.9G 0 disk
|-sdb1 8:17 0 512M 0 part
|-sdb2 8:18 0 216.5G 0 part
`-sdb3 8:19 0 15.9G 0 part
sdc 8:32 0 2.7T 0 disk
sdd 8:48 0 489.1G 0 disk
`-sdd1 8:49 0 489G 0 part /etc/hosts
sr0 11:0 1 1024M 0 rom

docker$ ls -l /mnt/image/
total 88
drwxr-xr-x 2 root root 4096 Jul 10 00:08 bin
drwxr-xr-x 2 root root 4096 Jul 10 00:20 boot
drwxr-xr-x 4 root root 4096 Jul 10 00:03 dev
drwxr-xr-x 80 root root 4096 Jul 10 00:21 etc
drwxr-xr-x 3 root root 4096 Jul 10 00:07 home
drwxr-xr-x 16 root root 4096 Jul 10 00:09 lib
drwx------ 2 root root 16384 Jul 10 00:20 lost+found
drwxr-xr-x 2 root root 4096 Jul 10 00:03 media
drwxr-xr-x 2 root root 4096 Jul 10 00:03 mnt
drwxr-xr-x 3 root root 4096 Jul 10 00:07 opt
drwxr-xr-x 2 root root 4096 Jun 6 15:42 proc
drwx------ 2 root root 4096 Jul 10 00:03 root
drwxr-xr-x 4 root root 4096 Jul 10 00:03 run
drwxr-xr-x 2 root root 4096 Jul 10 00:09 sbin
drwxr-xr-x 2 root root 4096 Jul 10 00:03 srv
drwxr-xr-x 2 root root 4096 Jun 6 15:42 sys
drwxrwxrwt 2 root root 4096 Jul 10 00:21 tmp
drwxr-xr-x 10 root root 4096 Jul 10 00:03 usr
drwxr-xr-x 11 root root 4096 Jul 10 00:03 var


5. 補足: --privilegedオプションについて

 docker container runコマンドに--privilegedオプションを付けない場合、以下の通りmountコマンドがエラーとなります。

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

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

docker$ mount -o loop,offset=276824064 /workspace/2019-07-10-raspbian-buster-lite.img /mnt/image
mount: /mnt/image: mount failed: Operation not permitted.