CLOVER🍀

That was when it all began.

DockerおよびDocker Composeでtmpfsを使う

これは、なにをしたくて書いたもの?

Dockerではtmpfsをマウントすることができます。

前に似たようなエントリーを書いたことがあるのですが、なぜか「(起動後の)Dockerコンテナ内でマウントする」で終わっていました…。

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

今回は、コンテナ起動時に最初からtmpfsをマウントするようにしてみたいと思います。

Dockerコンテナでtmpfsをマウントする

Dockerのtmpfsに関するドキュメントはこちら。

tmpfs mounts | Docker Docs

Dockerコンテナでホスト側とストレージを共有するにはvolumeを使います。

Volumes | Docker Docs

volumeは主にコンテナ内のデータの永続化目的で使いますが、tmpfsでマウントした先に書き込んだ内容はホスト側のメモリーにのみ
保持され、コンテナが停止すると削除されます。

用途としては、メモリーにのみ保持しておきたい機密情報や、ディスクの代わりにメモリーを書き込み先によるパフォーマンスの向上目的
あたりが考えられます。

また、tmpfsマウントの制限は以下です。

  • コンテナ間でマウントを共有することはできない
  • Linux上でDockerを使用している場合のみ利用可能
  • tmpfsに権限を設定すると、コンテナの再起動後に権限がリセットされることがある

tmpfs mounts / Limitations of tmpfs mounts

tmpfsをマウントする方法は2つあります。

  • --tmpfsオプションでマウントする … 簡単に使用可能だが、tmpfsのオプションの指定が不可
  • --mountオプションでマウントする … 冗長な表現になるが、tmpfsのオプションの指定が可能

ここでいうtmpfsのオプションとは、以下の2つです。

  • tmpfs-size … マウントするtmpfsのサイズをバイト単位で指定。デフォルトでは無制限
  • tmpfs-mode … 8進数で表現されるtmpfsのファイルモード。700や0770で指定し、デフォルトは1777(誰でも書き込み可能)

tmpfs mounts / Use a tmpfs mount in a container / Specify tmpfs options

Docker Composeで使う場合は、こちらでの指定になります。

ここまで見たところで、試してみましょう。

環境

今回の環境はこちら。

$ docker version
Client: Docker Engine - Community
 Version:           25.0.1
 API version:       1.44
 Go version:        go1.21.6
 Git commit:        29cf629
 Built:             Tue Jan 23 23:09:23 2024
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          25.0.1
  API version:      1.44 (minimum version 1.24)
  Go version:       go1.21.6
  Git commit:       71fa3ab
  Built:            Tue Jan 23 23:09:23 2024
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.27
  GitCommit:        a1496014c916f9e62104b33d1bb5bd03b0858e59
 runc:
  Version:          1.1.11
  GitCommit:        v1.1.11-0-g4bccb38
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Docker Compose。

$ docker compose version
Docker Compose version v2.24.2

Ubuntu Linux 22.04 LTS上のDockerです。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.3 LTS
Release:        22.04
Codename:       jammy


$ uname -srvmpio
Linux 5.15.0-92-generic #102-Ubuntu SMP Wed Jan 10 09:33:48 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

tmpfsを使ってDockerコンテナを起動してみる

では、tmpfsを使ってDockerコンテナを起動してみましょう。

--tmpfsオプションを使用する場合。/appディレクトリにtmpfsをマウントしてみました。

$ docker container run -it --rm --name ubuntu --tmpfs /app ubuntu:22.04

dfで見ると、/appがtmpfsとしてマウントされていることが確認できます。

# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay         xxxG  xxxG   xxxG  xxx% /
tmpfs            64M     0   64M   0% /dev
shm              64M     0   64M   0% /dev/shm
tmpfs           7.8G     0  7.8G   0% /app
/dev/sda8       xxxG  xxxG   xxxG  xxx% /etc/hosts
tmpfs           7.8G     0  7.8G   0% /proc/asound
tmpfs           7.8G     0  7.8G   0% /proc/acpi
tmpfs           7.8G     0  7.8G   0% /proc/scsi
tmpfs           7.8G     0  7.8G   0% /sys/firmware
tmpfs           7.8G     0  7.8G   0% /sys/devices/virtual/powercap

次に、--mountオプションでtmpfsをマウントしてみます。

$ docker container run -it --rm --name ubuntu --mount type=tmpfs,destination=/app ubuntu:22.04

特にオプションを指定していないので、結果は同じです。

# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay         xxxG  xxxG   xxxG  xxx% /
tmpfs            64M     0   64M   0% /dev
shm              64M     0   64M   0% /dev/shm
tmpfs           7.8G     0  7.8G   0% /app
/dev/sda8       xxxG  xxxG   xxxG  xxx% /etc/hosts
tmpfs           7.8G     0  7.8G   0% /proc/asound
tmpfs           7.8G     0  7.8G   0% /proc/acpi
tmpfs           7.8G     0  7.8G   0% /proc/scsi
tmpfs           7.8G     0  7.8G   0% /sys/firmware
tmpfs           7.8G     0  7.8G   0% /sys/devices/virtual/powercap

では、オプションを指定してみましょう。今回はtmpfs-sizeを指定して、マウントするtmpfsを100Mにしてみます。

$ docker container run -it --rm --name ubuntu --mount type=tmpfs,destination=/app,tmpfs-size=100M ubuntu:22.04

df -hで見ると、/appにマウントされているのが100Mになっていることが確認できます。

# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay         xxxG  xxxG   xxxG  xxx% /
tmpfs            64M     0   64M   0% /dev
shm              64M     0   64M   0% /dev/shm
tmpfs           100M     0  100M   0% /app
/dev/sda8       xxxG  xxxG   xxxG  xxx% /etc/hosts
tmpfs           7.8G     0  7.8G   0% /proc/asound
tmpfs           7.8G     0  7.8G   0% /proc/acpi
tmpfs           7.8G     0  7.8G   0% /proc/scsi
tmpfs           7.8G     0  7.8G   0% /sys/firmware
tmpfs           7.8G     0  7.8G   0% /sys/devices/virtual/powercap

試してみましょう。

50Mのファイルの作成。

# dd if=/dev/zero of=/app/file bs=1M count=50
50+0 records in
50+0 records out
52428800 bytes (52 MB, 50 MiB) copied, 0.020767 s, 2.5 GB/s


# ll -h /app/file
-rw-r--r-- 1 root root 50M Jan 28 11:35 /app/file

200Mのファイルの作成。

# dd if=/dev/zero of=/app/file bs=1M count=200
dd: error writing '/app/file': No space left on device
1+0 records in
0+0 records out
0 bytes copied, 0.000457989 s, 0.0 kB/s


# ll -h /app/file
-rw-r--r-- 1 root root 100M Jan 28 11:36 /app/file

こちらは容量が足りずに失敗することが確認できました。

OKですね。

実際の使い方としては、メモリーで扱える範囲になりますがMySQLのようなデータベースのストレージをtmpfsにして速度を上げると
いったこともあるのではないでしょうか。

$ docker container run -it --rm --name mysql --tmpfs /var/lib/mysql -e MYSQL_ROOT_PASSWORD=password mysql:8.0.36

Docker Composeでtmpfsを使う

最後は、Docker Composeでtmpfsを使ってみましょう。

こんな感じで指定します。

compose.yaml

services:
  mysql:
    image: mysql:8.0.36
    environment:
      MYSQL_ROOT_PASSWORD: password
    tmpfs: /var/lib/mysql

起動はふつうに。

$ docker compose up

確認してみましょう。

$ docker compose exec mysql bash
# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay         xxxG  xxxG   xxxG  xxx% /
tmpfs            64M     0   64M   0% /dev
shm              64M     0   64M   0% /dev/shm
/dev/sda8       xxxG  xxxG   xxxG  xxx% /etc/hosts
tmpfs           7.8G  201M  7.6G   3% /var/lib/mysql
tmpfs           7.8G     0  7.8G   0% /proc/asound
tmpfs           7.8G     0  7.8G   0% /proc/acpi
tmpfs           7.8G     0  7.8G   0% /proc/scsi
tmpfs           7.8G     0  7.8G   0% /sys/firmware
tmpfs           7.8G     0  7.8G   0% /sys/devices/virtual/powercap

OKですね。

以下のように、リスト形式で複数の指定もOKです。

services:
  mysql:
    image: mysql:8.0.36
    environment:
      MYSQL_ROOT_PASSWORD: password
    tmpfs:
      - /var/lib/mysql

volumesで指定する場合は、こうなるようです。

compose.yaml

services:
  mysql:
    image: mysql:8.0.36
    environment:
      MYSQL_ROOT_PASSWORD: password
    volumes:
      - type: tmpfs
        target: /var/lib/mysql
        tmpfs:
          size: 2G

tmpfs-sizeの指定方法が最初わからなかったのですが、この記述でうまくいきました。

# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay         xxxG  xxxG   xxxG  xxx% /
tmpfs            64M     0   64M   0% /dev
shm              64M     0   64M   0% /dev/shm
/dev/sda8       xxxG  xxxG   xxxG  xxx% /etc/hosts
tmpfs           2.0G  189M  1.9G  10% /var/lib/mysql
tmpfs           7.8G     0  7.8G   0% /proc/asound
tmpfs           7.8G     0  7.8G   0% /proc/acpi
tmpfs           7.8G     0  7.8G   0% /proc/scsi
tmpfs           7.8G     0  7.8G   0% /sys/firmware
tmpfs           7.8G     0  7.8G   0% /sys/devices/virtual/powercap

これは、Composeファイルのバージョン3のリファレンスに記述がありました。

Compose file version 3 reference / Service configuration reference / tmpfs

現在のバージョンのドキュメントにはこの記述がないので、あまり使わない方がいいのかもしれません…。

tmpfs-modeについては記載がないですし…。

おわりに

Dockerでtmpfsをマウントするようにしてみました。

これができることをコロッと忘れていたりするのと、そもそもこのブログでも書いたのが通常使うであろう状況と全然違うものだったので、
あらためてまとめなおした感じですね。

ちゃんとドキュメントを見る機会にもなって良かったです。