Help us understand the problem. What is going on with this article?

Dockerのoverlayfsをコンテナと関係なくアクセスする

概要

Dockerコンテナー内のファイルを操作するには、docker execでbashを使用するのが一般的です。
ただし、コンテナが実行されていない限り、このメソッドは操作できません。
したがって、docker inspectの出力内容に基づいて、overlayfsディレクトリをコンテナとは別にマウントし、Dockerを使用せずにファイル操作を実行する方法を検討しました。

環境

・・・
 Server Version: 19.03.4
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
・・・
 Kernel Version: 4.15.0-70-generic
 Operating System: Ubuntu 18.04.3 LTS
 OSType: linux
 Architecture: x86_64
・・・

マウントのしくみ

「LowerDir」はイメージなどコンテナ上で新たに作られたファイルより下層を保持します。1読み取り専用。2
「WorkDir」はUpperdir内のファイルが原子性(ファイルが不完全ではない)ことを保つためのキャッシュ的な領域です。3
「Upperdir」はコンテナ作成以後の変更点が記録され、コンテナ独自のデータが保管されます。1
「マウントポイントまたは"MergedDir"」は上記3つのフォルダを統合し、ファイル操作の拠点となります。ここではファイルシステムを意識せずに純粋に読み書きができます。1

マウントのコマンドは以下のようにすれば問題ありません。4

sudo mount -t overlay -o lowerdir="LowerDir"」,upperdir="UpperDir"」
,workdir="WorkDir"」 overlay 「マウントポイントまたは"MergedDir"

Dockerのoverlayfsの上記4つのディレクトリの位置はdocker inspectコマンドで判明します。

docker inspect コンテナ
・・・
            "CpusetCpus": "",
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/1109be508e00968c34c73a5cd2c787ad6d3c4951f7b387700ace2b12daae8ec8-init/diff:/var/lib/docker/overlay2/35d8c38f712194bd9d57b9a433955c1141c1974c2b07bfb86b44bee0feb1f0d4/diff:/var/lib/docker/overlay2/018ec8b5d317fddd6fdb9634bf01d869bfd03f9122477a853317efb8d8ff2d86/diff:/var/lib/docker/overlay2/f7671e8be670d1ab91d5a63166374862d2c972448d7b1c4037cee15e1a7628da/diff:/var/lib/docker/overlay2/4fea42daa23e6120c2956ca1d2397d3829fdb8e9f03336ed2b4bd36c895fa53e/diff:/var/lib/docker/overlay2/a15984dba40e4afa1df1c5088b6d3a366e91c74c04ef9a19f7a9e061e6e59bea/diff:/var/lib/docker/overlay2/6f61ebd10ebd7fd6e07b0226b0ac71602d3152a8f9a09744c774998e3c0fdc47/diff:/var/lib/docker/overlay2/ae7ad5c9ce4f3051ad28d3fdc8270c8f7b2d11f63a1446156485e5aa1e9adb64/diff:/var/lib/docker/overlay2/8242e55feaed0c250e9919273671ff051b136853ce2b0e7cf4a499f68388e588/diff:/var/lib/docker/overlay2/fcfb7edf288d40aa1673e09955b1affc748561f5c4d55f01ea9dc3d4fdd418ab/diff",
                "MergedDir": "/var/lib/docker/overlay2/1109be508e00968c34c73a5cd2c787ad6d3c4951f7b387700ace2b12daae8ec8/merged",
                "UpperDir": "/var/lib/docker/overlay2/1109be508e00968c34c73a5cd2c787ad6d3c4951f7b387700ace2b12daae8ec8/diff",
                "WorkDir": "/var/lib/docker/overlay2/1109be508e00968c34c73a5cd2c787ad6d3c4951f7b387700ace2b12daae8ec8/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/smx/docker_minecraft_res",
                "Destination": "/minecraft/resources",
                "Mode": "",
                "RW": false,
                "Propagation": "rprivate"
            }

・・・

マウント方法

マウント

「マウントのしくみ」の章のように、マウントポイントを私たちは利用したいのです。

下記がコマンド実行例です。
/mnt/test にマウントされます。

mount -t overlay overlay -o lowerdir="/var/lib/docker/overlay2/1109be508e00968c34c73a5cd2c787ad6d3c4951f7b387700ace2b12daae8ec8-init/diff:/var/lib/docker/overlay2/35d8c38f712194bd9d57b9a433955c1141c1974c2b07bfb86b44bee0feb1f0d4/diff:/var/lib/docker/overlay2/018ec8b5d317fddd6fdb9634bf01d869bfd03f9122477a853317efb8d8ff2d86/diff:/var/lib/docker/overlay2/f7671e8be670d1ab91d5a63166374862d2c972448d7b1c4037cee15e1a7628da/diff:/var/lib/docker/overlay2/4fea42daa23e6120c2956ca1d2397d3829fdb8e9f03336ed2b4bd36c895fa53e/diff:/var/lib/docker/overlay2/a15984dba40e4afa1df1c5088b6d3a366e91c74c04ef9a19f7a9e061e6e59bea/diff:/var/lib/docker/overlay2/6f61ebd10ebd7fd6e07b0226b0ac71602d3152a8f9a09744c774998e3c0fdc47/diff:/var/lib/docker/overlay2/ae7ad5c9ce4f3051ad28d3fdc8270c8f7b2d11f63a1446156485e5aa1e9adb64/diff:/var/lib/docker/overlay2/8242e55feaed0c250e9919273671ff051b136853ce2b0e7cf4a499f68388e588/diff:/var/lib/docker/overlay2/fcfb7edf288d40aa1673e09955b1affc748561f5c4d55f01ea9dc3d4fdd418ab/diff",upperdir="/var/lib/docker/overlay2/1109be508e00968c34c73a5cd2c787ad6d3c4951f7b387700ace2b12daae8ec8/diff",workdir= "/var/lib/docker/overlay2/1109be508e00968c34c73a5cd2c787ad6d3c4951f7b387700ace2b12daae8ec8/work" /mnt/test

いちいちディレクトリをコピペしたくないのでスクリプトを作りましょう。
あるいは、下記のシェルスクリプトのようにまとめればわかりやすくマウントできます。

test.sh
#!/bin/sh
CONTAINERNAME=コンテナ名
DOCKERHOST=unix:///var/run/docker.sock(各自で確認すること)
LOWERDIR=`docker -H ${DOCKERHOST} inspect --format='{{ .GraphDriver.Data.LowerDir }}' ${CONTAINERNAME}`
UPPERDIR=`docker -H ${DOCKERHOST} inspect --format='{{ .GraphDriver.Data.UpperDir}}' ${CONTAINERNAME}`
WORKDIR=`docker -H ${DOCKERHOST} inspect --format='{{ .GraphDriver.Data.WorkDir}}' ${CONTAINERNAME}`
MOUNTPOINT=/mnt/test


sudo mount -t overlay -o lowerdir=${LOWERDIR},upperdir=${UPPERDIR},workdir=${WORKDIR} overlay ${MOUNTPOINT}

実行結果

# umount /mnt/test
# ls /mnt/test
# ./test.sh
# ls /mnt/test
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  minecraft  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

アンマウント

簡単です。マウントポイントを指定します。

umount /mnt/test

まとめ

これまで、Dockerコンテナが起動に失敗すると、そのコンテナを回復することは非常に困難でした。ですが、この方法を使用すると、コンテナーの起動状態に関係なく操作を実行できます。
MiRmの開発に戻ります。。。

メモ

  • Docker起動中にDocker側でのファイル編集はマウントポイントに反映されます
  • storage-optのコンテナ毎の容量制限はマウントポイント内でも機能しています
  • Dockerのオンオフは無視して問題なく、Docker内のmergedと同一の内容になります。

Ref

https://github.com/thomasweaver/docker-scanner/blob/e822bd8873b7225ce5c46f38226d232ea94f8124/scanner/Scanner/Mount.py
https://github.com/b00kwrm/tddd/blob/29edb508cf47c19872aa43a6b1558ad609205c69/tools/get-docker-fs.py
https://github.com/att/docker-forensics/blob/944db5600bc9e7126f1d20e10499b4724bce4740/docker-mount.py
https://github.com/docker-forensics-toolkit/toolkit/blob/3fa4e46dbce7aef871ac2eec90caeed6cd921263/src/dof/model/container.py
https://qiita.com/awakia/items/af9b46c322905cdce1d7
https://qiita.com/ryuichi1208/items/0bd0284dcf8a09299504

面白そうな記事

https://my1cdlinux.eksd.jp/createbootablelivecd_cdrommountandoverlayfs.html

脚注

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away