Docker tmpfsマウント入門:I/Oの高速化とRAM上での機密データ保護

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

I/Oボトルネックとディスクへのデータ漏洩リスク

ffmpegによる動画変換、数GBのtarアーカイブ展開、並列テストの実行など、負荷の高いファイル処理を行うコンテナを運用した経験があれば、サーバーのSSDが瞬く間にIOPSの限界に達する現象に直面したことがあるはずです。ライフサイクルがわずか数秒の一時ファイルを大量に書き込み続けると、他のサービスを遅延させるだけでなく、SSDのTBW(総書き込み保証量)を激しく消耗させてしまいます。

もう一つの深刻な問題がセキュリティです。アプリケーションがセッショントークン、一時的な秘密鍵、復号されたばかりのPDFファイルなどをコンテナレイヤーに書き込むと、それらはホストのブロックデバイス上にそのまま残存します。たとえ docker rm -f でコンテナを削除したとしても、生データはディスク上に残るため、ホストのroot権限を持つユーザーであれば容易に復元できてしまいます。

こうした課題を鮮やかに解決するのがDocker tmpfsマウントです。すべての一時ファイルをRAM上に展開します。

Docker tmpfsマウントの仕組み

Dockerには現在、主に3つのデータマウント方式があります。

  • Volumes: Dockerが /var/lib/docker/volumes/ 配下で管理し、コンテナを破棄してもデータは維持されます。
  • Bind mounts: ホスト上の指定ディレクトリをコンテナ内に直接マウントします。ホストのディレクトリ構成に依存します。
  • tmpfs mount: LinuxホストのRAM上に仮想ファイルシステムを作成して直接マウントします。データはディスクに書き込まれず、コンテナ停止時に完全に自動消去されます。

VolumeおよびBind Mountとの比較

物理メモリ上に直接配置されるため、tmpfsには明確な強みがあります。

  • 圧倒的な帯域幅: DDR4/DDR5 RAMの読み書き速度はマイクロ秒単位のレイテンシで20〜50 GB/sに達し、NVMe Gen4 SSDの3〜7 GB/sをはるかに凌駕します。
  • セキュアな自動消去: コンテナ停止と同時にRAM領域が解放されます。フォレンジック調査やデータ復元を行っても、ディスク上には一切痕跡が残りません。
  • コンテナレイヤーの肥大化防止: 数十GBの一時ファイルを書き込んでもrootfsを圧迫せず、/var/lib/docker パーティションの容量枯渇を防ぎます。

実践:Docker tmpfsマウントの設定と使い方

1. 基本的な –tmpfs フラグによるクイック実行

最も手軽なのは --tmpfs フラグを使う方法です:

docker run -d \
  --name redis-test \
  --tmpfs /tmp \
  redis:7-alpine

これでコンテナの /tmp 配下に生成されるファイルはすべてRAM上に保持されます。ただし、この方法には「RAM使用量の上限を指定できない」という重大な欠点があります。

2. –mount 構文による容量制限とパーミッション設定

コンテナ内の不具合でファイル書き込みの無限ループが発生した場合、デフォルトの --tmpfs フラグではホストのRAMを食い尽くし、LinuxのOOM Killerが発動してサーバー全体がダウンする恐れがあります。安全に運用するためには --mount 構文を使用します:

docker run -d \
  --name secure-app \
  --mount type=tmpfs,destination=/app/cache,tmpfs-size=512m,tmpfs-mode=1770 \
  nginx:alpine

各パラメータの役割:

  • destination=/app/cache: RAM上にマウントするコンテナ内のターゲットディレクトリです。
  • tmpfs-size=512m: 容量上限を512MBに制限します(k、m、g単位をサポート)。上限を超えた場合、ホストを巻き込むことなく No space left on device エラーを返します。
  • tmpfs-mode=1770: Linuxのファイルパーミッション(8進数表記)です。ここでの 1770 は、所有者およびグループへの読み取り/書き込み権限とStickyビットの付与を意味します。

3. Docker Composeでの設定

実務では docker-compose.yml に宣言して管理することが多いでしょう。短縮記法の配列構文を使用できます:

version: '3.8'
services:
  worker:
    image: python:3.11-slim
    command: python app.py
    volumes:
      - ./src:/app
    tmpfs:
      - /app/scratch:size=256m,mode=0755
      - /tmp:size=128m

あるいは、volumes ブロック配下でロングシンタックスを用いて、より明示的に記述することも可能です:

services:
  api:
    image: node:20-alpine
    volumes:
      - type: tmpfs
        target: /app/temp_tokens
        tmpfs:
          size: 64M
          mode: 0700

4. 確認とデバッグ

対象ディレクトリが実際にRAM上で動作しているか確認するには、コンテナ内で df -h コマンドを実行します:

docker exec -it secure-app df -h /app/cache

出力結果にファイルシステムタイプ tmpfs、サイズ 512M が表示されます。

ホスト側からコンテナのマウント構成を詳細に確認したい場合:

docker inspect secure-app --format '{{ json .Mounts }}'

inspectから返されるJSON文字列は長く可読性が低いため、サーバーへSSH接続中で拡張機能が使えない環境では、toolcraft.app/ja/tools/developer/json-formatter などに貼り付けて手早くフォーマットすると便利です。

適用すべきケースと避けるべきケース

RAMは高速ですが、容量単価が高く揮発性があるため、適切なユースケースの選択が不可欠です:

  • 推奨ユースケース: 動画・画像レンダリング用バッファ、一時セッション、ダウンロードファイルの解凍先、CI/CDランナー(GitLab RunnerやGitHub Actions Runnerなど)のコードビルドディレクトリ、実行時に一時復号する秘密鍵の保存場所。
  • 非推奨ユースケース: データベースエンジン(PostgreSQL、MySQL、MongoDBなど)をはじめ、再起動後も永続化が必要なデータ。データの永続性が必要な場合は、必ずDocker Volumeを選択してください。
  • プラットフォームに関する注意点: tmpfsマウントはLinux環境でネイティブに動作します。macOSやWindowsでは、Docker Desktopが内部で起動しているLinux VM内でコンテナが実行されるため、I/O性能はそのVMに割り当てられたリソースの制約を受けます。

まとめ

tmpfsマウントはシンプルでありながら、一時データによるI/Oボトルネックを根本から解消できる強力な手法です。永続データはVolumeに分離し、一時処理はRAMに逃がす構成をとることで、アプリケーションの応答性向上、ストレージの摩耗防止、コンテナスケーリング時のセキュリティ向上を同時に実現できます。

Share: