📘
dockerコマンドを使わずにコンテナを作る - 3
概要
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