💡

Dockerのtmpfs内で実行ファイルを実行する方法

2023/07/04に公開

docker run のオプションで --tmpfs を使うと、コンテナに tmpfsのボリュームをマウントすることができます。

$ docker run --rm -it --tmpfs /tmpfs ubuntu bash

ところがデフォルトだと、この tmpfs領域に置いた実行ファイルを実行することができません。

root@b1be696bd550:/# cat <<EOF > /tmpfs/a.sh
> #!/bin/bash
> echo hello
> EOF
root@b1be696bd550:/# chmod 0755 /tmpfs/a.sh
root@b1be696bd550:/#  /tmpfs/a.sh
bash: /tmpfs/a.sh: Permission denied

これはなぜでしょうか。mountコマンドでマウント状態を調べてみましょう。

root@b1be696bd550:/# mount | grep /tmpfs
tmpfs on /tmpfs type tmpfs (rw,nosuid,nodev,noexec,relatime)

"noexec" という、いかにもそれっぽい単語が見えます。
Linuxマニュアルによるとお、

https://linuxjm.osdn.jp/html/util-linux/man8/mount.8.html

noexec
マウントされたファイルシステム上の任意のバイナリの直接実行を禁止する。

ということで、デフォルトでは実行禁止になっているんですね。まあセキュリティ的にはその方が安心ですね。
一方でコンパイラ開発などをしていると、コンパイラが tmpfs に吐いた大きめのバイナリをすぐ実行してテストしたいということがよくあります。

試行錯誤したら、下記のように exec オプションをつけると実行できるようになりました。

$ docker run --rm -it --tmpfs /tmpfs:exec ubuntu bash
root@c15f0207a000:/# cat <<EOF >/tmpfs/a.sh
> #!/bin/bash
> echo hello
> EOF
root@c15f0207a000:/# chmod 0755 /tmpfs/a.sh
root@c15f0207a000:/#  /tmpfs/a.sh
hello

mount状況を見てみると、noexec の文字が消えています。

root@c15f0207a000:/# mount | grep /tmpfs
tmpfs on /tmpfs type tmpfs (rw,nosuid,nodev,relatime)

めでたしめでたし。

sizeやmodeを同時に指定するときはこう書きます。

$ docker run --rm -it --tmpfs /tmpfs:rw,exec,size=500m,mode=1777 ubuntu bash

ちなみにこの exec オプションはなんとdockerの公式マニュアルにも載っていないのです。

https://docs.docker.com/storage/tmpfs/

どうやって知ったのかというと、なんとなく勘でつけてみたら成功したという。

Discussion