ヒスねこTechBlog

日々の気になる技術をまとめてます。

DockerイメージをOverlayFSでマウントする

前回記事で、Dockerイメージ内に含まれるmanifest.jsonがレイヤ構成を教えてくれることがわかりました。 このレイヤ構成の情報を使用して、OverlayFSでマウントしてみます。

techblog.hys-neko-lab.com

今回やることの概要

OverlayFSでDockerイメージをマウントします。必要な作業としては、

  1. イメージのtarを展開する
  2. マウントするディレクトリ(lowerdir, upperdir, workdir, mergeddir)を準備する
  3. manifest.jsonからレイヤ情報を抜き出す
  4. 抜き出した情報をもとに、順番にレイヤをlowerdirへ展開する
  5. 2で作成したディレクトリをOverlayFSでマウントする

となるかと思います。

Dockerイメージに含まれていたレイヤは、lowerdirとしてマウントします。mergeddirが、実際に私たちが見て、ファイルの追加/変更/削除を行うことになるディレクトリです。upperdirはmergeddirに施した変更が反映されるディレクトリになります。workdirはシステムの内部作業用とのことで、ディレクトリの用意は必要ですが、基本的に気にする必要はなさそうです。

OverlayFSでのマウント

jsonの解析のため、jqを導入してみました。まだまだ使いこなせていないですが、慣れたら便利そう。

sudo apt install jq

イメージのtarをOverlayFSでマウントするシェルスクリプト(mount.sh)を書いてみました。lowerdirはレイヤごとに分けて作成するようにしています。 最後のmountコマンドのlowerdir引数には、上のレイヤから指定する必要があります。したがって、本スクリプトでも上のレイヤから順に展開しています。

#!/bin/bash
#[Usage] ./mount.sh yourImageName.tar
LOWERDIR=""

# イメージのtarを展開
EXTRACT_DIR=${1%.*}
mkdir -p $EXTRACT_DIR
tar xvf $1 -C $EXTRACT_DIR

# レイヤ数の取得
LOWER_LAYER_NUM=$(cat $EXTRACT_DIR/manifest.json | jq -r '.[].Layers | length')
i=$(expr $LOWER_LAYER_NUM - 1)

while [ $i -ge 0 ]
do
    # 各レイヤのtarをlowerNディレクトリに展開
    mkdir -p lower$i
    QUERY=".[].Layers | .[$i]"
    LOWER_LAYER_TAR=$(cat $EXTRACT_DIR/manifest.json | jq -r "$QUERY")
    tar xvf $EXTRACT_DIR/$LOWER_LAYER_TAR -C lower$i

    # マウント時の引数(lowerdir)を作成
    LOWERDIR+="lower$i:"

    i=$(expr $i - 1)
done

# マウント用にディレクトリ作成
mkdir -p {upper,work,merged}

# OverlayFSでマウント
# (lowerdirは上のレイヤから指定することに注意)
sudo mount \
    -t overlay overlay \
    -o lowerdir=${LOWERDIR/%?/},upperdir=upper,workdir=work merged

スクリプトを実行してmergedディレクトリの中身を見ると、前回作成したファイル(hello.txt, hoge.txt)が確認できます。

$ chmod +x mount.sh
$ ./mount.sh testimage2.tar
$ ls merged
hello.txt hoge.txt
# マウントを解除する場合は以下を実行
$ sudo umount merged

次回はマウント先をルートディレクトリとしてプロセス実行し、コンテナっぽいことをさせてみようと思います。