CLOVER🍀

That was when it all began.

Dockerコンテナ内で、tmpfsをマウントしたい

Dockerコンテナ内で、以下のようにtmpfsをマウントしようとしても、「権限不足」として怒られてしまいます。

$ sudo mount -t tmpfs -o size=1G tmpfs /mnt/test
mount: permission denied

ホスト側からvolumeとして与えるのが筋のような感じもしますが、あくまでDockerコンテナ内でこれをクリアするには、
「docker run」時に「--privileged」を与えてあげればいいようです。

$ docker run --privileged [各種オプション] [起動するイメージ]

すると、tmpfsがマウントできるようになります。

$ sudo mount -t tmpfs -o size=1G tmpfs /mnt/test

$ df -h
Filesystem                   Size  Used Avail Use% Mounted on
none                         286G  168G  104G  62% /
tmpfs                         64M     0   64M   0% /dev
tmpfs                        4.5G     0  4.5G   0% /sys/fs/cgroup
/dev/mapper/ubuntu--vg-root  286G  168G  104G  62% /etc/hosts
shm                           64M     0   64M   0% /dev/shm
tmpfs                        1.0G     0  1.0G   0% /mnt/test

「--privileged」が強いという場合は、cap_sys_adminを与えればよいという感じにドキュメントに書かれていますが

Full container capabilities (–privileged)

実際に、「--cap-add」で「SYS_ADMIN」を追加しても

$ docker run --cap-add SYS_ADMIN [各種オプション] [起動するイメージ]

マウント時に怒られます。

$ sudo mount -t tmpfs -o size=1G tmpfs /mnt/test 
mount: tmpfs is write-protected, mounting read-only
mount: cannot mount tmpfs read-only

cap_sys_adminを加えるだけではダメで、「--security-opt apparmor:unconfined」も必要なようです。
Mount device in the container failed · Issue #18191 · moby/moby · GitHub
Unable to mount devices under container · Issue #9950 · moby/moby · GitHub

っていうか、AppArmorってなんでしたっけ?

AppArmor は Linux の LSM (Linux Security Modules) インターフェース上に設けられた強制アクセス制御 (MAC) システムです。具体的に言えば、カーネルはそれぞれのシステムコールの前にシステムコールを発行したプロセスが指定された操作に対する権限を与えられているか AppArmor に問い合わせます。このメカニズムを通じて、AppArmor はプログラムがアクセスできるリソースを制限します。

AppArmor はプログラムごとに一連の規則 (これは「プロファイル」として知られています) を適用します。カーネルは実行されたプログラムのインストール先のパスに依存してこのプロファイルを適用します。SELinux とは対照的に (第 14.5 節「SELinux の紹介」を参照してください)、このプロファイルはユーザに依存するものではありません。同じプログラムを実行したすべてのユーザは同じプロファイルを適用されます (しかしながら、伝統的なユーザパーミッションが適用されないわけではありません。このため、ユーザごとにプログラムの挙動が異なる可能性もあります!)。

https://debian-handbook.info/browse/ja-JP/stable/sect.apparmor.html

権限制御ですね。

で、「apparmor:unconfined」を選ぶということは、セキュリティプロファイルなしでコンテナを実行するということになります。
AppArmor によるコンテナの保護  |  Container-Optimized OS  |  Google Cloud

だいぶ緩い感じになるので、これはこれで覚えておきましょう…。

というわけで、こういう感じにすると

$ docker run --cap-add SYS_ADMIN --security-opt apparmor:unconfined [各種オプション] [起動するイメージ]

tmpfsがマウントできるようになりますよ、と。

$ sudo mount -t tmpfs -o size=1G tmpfs /mnt/test/

$ df -h
Filesystem                   Size  Used Avail Use% Mounted on
none                         286G  168G  104G  62% /
tmpfs                         64M     0   64M   0% /dev
tmpfs                        4.5G     0  4.5G   0% /sys/fs/cgroup
/dev/mapper/ubuntu--vg-root  286G  168G  104G  62% /etc/hosts
shm                           64M     0   64M   0% /dev/shm
tmpfs                        4.5G     0  4.5G   0% /proc/scsi
tmpfs                        4.5G     0  4.5G   0% /sys/firmware
tmpfs                        1.0G     0  1.0G   0% /mnt/test

なお、起動時に最初からtmpfsをマウントするようにしたい場合は、こちらへ。

DockerおよびDocker Composeでtmpfsを使う