📘

dockerコマンドを使わずにコンテナを作る - 3

2023/03/11に公開

概要

1回目で簡単なコンテナの作り方について触れたが, overlayfsについてどのようになっているか触れてなかったのでここで触れてみる.
以下のようなDockerfileと同じような挙動をさせる.

# LAYER1
FROM alpine:latest

# LAYER2
RUN apk add --no-cache curl

ENTRYPOINT ["curl"]

やってることは参照のコンテナ技術入門と全く同じ.

実践

2回layerの重ね合わせが発生する.

layer1

まずはalpineのファイルシステムを$LAYER1/diff以下に展開するだけ.

LAYER1=$(mktemp -d)
mkdir $LAYER1/diff
CID=$(sudo docker container create alpine:latest)
sudo docker export $CID | tar -x -C $LAYER1/diff
sudo docker rm $CID

layer2

最初のlayerの重ね合わせ. $LAYER2/merged$LAYER1/diffをそのままのせる.
$LAYER2/mergedにchrootして名前空間を作り, そこでcurlをインストール.
これにより$LAYER2/mergedに変更が入るため, 差分ファイルが$LAYER2/diffに自動的に作られる.

overlayfsの挙動の説明になってしまうが, mount実行後にmerged内でファイルが追加されるとupperdirに指定したディレクトリに自動的に差分ファイルが追加される模様. (知らなかった)

$LAYER2/diffだけが必要になるのでそれ以外はお掃除.

LAYER2=$(mktemp -d)
mkdir $LAYER2/{diff,work,merged}
sudo mount -t overlay -o lowerdir=$LAYER1/diff,upperdir=$LAYER2/diff,workdir=$LAYER2/work overlay $LAYER2/merged
sudo mount --bind /etc/resolv.conf $LAYER2/merged/etc/resolv.conf
unshare -r chroot $LAYER2/merged apk add --no-cache curl
sudo umount -R $LAYER2/merged
rm -rf $LAYER2/{work,merged}

container(layer3)

2回目のlayerの重ね合わせ. これが最後になるので実質このlayerを重ね合わせてそのpath上で切られたnamespaceがコンテナとなる.
気を付けるべき点はここからlowerdirが複数になるが, 新しいlayerの方を左側に書く必要がある(この例だと$LAYER2/diff:$LAYER1/diffの順番). 同じファイルが存在した場合, 左側の方が優先されるため, 左側に新しいlayerを置いておかないと古いlayerが優先されてしまいファイルに更新があった場合も反映されなくなってしまう.

CONTAINER=$(mktemp -d)
mkdir $CONTAINER/{diff,work,merged}
ROOTFS=$CONTAINER/merged
sudo mount -t overlay -o lowerdir=$LAYER2/diff:$LAYER1/diff,upperdir=$CONTAINER/diff,workdir=$CONTAINER/work overlay $ROOTFS
sudo mount --bind /etc/resolv.conf $ROOTFS/etc/resolv.conf
ARGS="http://httpbin.org/uuid"
unshare -urprf --mount-proc chroot $ROOTFS /bin/sh -c "mount -t proc proc /proc && curl $ARGS"

参照

コンテナ技術入門

Discussion