Dockerならではの問題に対処したのでメモを残します。

背景と課題

RHEL / Rocky Linux 9 環境のGPUサーバーにおいて、Dockerビルド(大規模LLMモデルの生成など)を実行した際、ルートパーティション(/)の使用率が100%に達する事象が発生しました。

  • 原因: Dockerはデフォルトで /var/lib/docker(ルート配下)にイメージやビルドキャッシュを保存します。
  • 環境: ルート領域は70GB程度ですが、/home 領域には数TBの空きがります。
  • 対策: パーティションリサイズ(LVM操作)はリスクが高いため、Dockerのデータ保存先(data-root)を /home 配下へ物理的に移行して解決します。

さっくりとした手順

  1. 現状を確認し、サービスを停止します。
  2. Dockerの移行ディレクトリを作成します。
  3. rsyncを用いて安全にデータを移行します。
  4. Dockerの設定ファイルを変更します。
  5. Dockerサービスの再起動を行います。
  6. 設定変更を確認します。

現状の確認とサービスの停止

まず、現在のDocker設定とディスク使用量を確認し、Dockerサービスを停止します。

  • Dockerの保存先確認
docker info | grep "Docker Root Dir"

(デフォルトは /var/lib/docker)

  • Dockerサービスを停止します。
sudo systemctl stop docker docker.socket
  • Dockerサービスの停止を確認します。
systemctl status docker

inactive(dead)を確認します。

移行先ディレクトリを作成します。

大容量領域(今回は /home 配下)に新しい保存用ディレクトリを作成します。

  • ディレクトリ作成
sudo mkdir -p /home/docker/data

データの移行(最重要)

既存のイメージやコンテナデータを保持するため、rsync を用いてデータを同期します。
cp コマンドよりも、権限やタイムスタンプを正確に保持できる rsync を推奨します。
rsyncはRocky9に最初から入っているコマンドです。

  • /var/lib/dockerの中身を、新ディレクトリへコピー
sudo rsync -aqxP /var/lib/docker/ /home/docker/data/

-a: アーカイブモード(権限等を保持)
-x: ファイルシステム境界を越えない
注意: コピー元のパス末尾に / を付けることで、ディレクトリそのものではなく「中身」を転送先に展開します。

設定ファイルの変更 (daemon.json)

  • ファイルのバックアップを取ります。(凄く重要)

何かあったときの切り戻しのため。特に、後述するjsonの編集をミスると地獄行きの通過駅無しの特急が待っています。

sudo cp -pi /etc/docker/daemon.json /path/to/backup/directory/daemon.json.$(date +%Y%m%d)
  • ファイルのバックアップをdiffで取ります。
sudo diff -u /path/to/backup/directory/daemon.json.$(date +%Y%m%d) /etc/docker/daemon.json

一般ユーザが読み取れないディレクトリ構造も考慮して、念のためsudoをつけます。

→ エラーがなければバックアップ成功。ここでコピー元とコピー先を逆にしているのは編集後のdiffを取るためです。

  • Dockerに新しい保存先を認識させるため、/etc/docker/daemon.json を編集します。(エディタは宗教問題のため、自分の教義・信仰に沿ったものを利用してください)

変更例:
data-root オプションを追記します。
JSON形式のため、行末のカンマ(,)の有無に注意してください。

{
    "runtimes": {
        "nvidia": {
            "path": "nvidia-container-runtime",
            "runtimeArgs": []
        }
    },
    "data-root": "/home/docker/data"
}
  • 編集後の差分をdiffで確認します。
sudo diff -u /path/to/backup/directory/daemon.json.$(date +%Y%m%d) /etc/docker/daemon.json

以下のようになっていることを確認します。

-     "data-root": "/var/lib/docker"
+     "data-root": "/home/docker/data"

サービスの起動と確認

Dockerを起動し、設定が反映されているか確認します。

  • Dockerサービスを起動します。
sudo systemctl start docker
  • Dockerサービスの起動を確認します。
systemctl status docker

active(running)を確認します。

  • 設定反映の確認
docker info | grep "Docker Root Dir"

=> Docker Root Dir: /home/docker/data となっていれば成功です。

不要データの削除(任意)

動作確認後、元の /var/lib/docker を削除または退避させて、ルートパーティションの空き容量を回復させます。

安全のため、バックアップを取るか慎重に削除してください。この作業を行うときは深呼吸を3回ほど行い、飲み物を飲むなどして落ち着いてから行いましょう。

sudo rm -rf /var/lib/docker

結果

本対応により、ルートパーティションの圧迫が解消されました。

Before:

Filesystem           Size  Used Avail Use% Mounted on
/dev/mapper/rl-root   70G   70G   20K 100% /

After:

Filesystem           Size  Used Avail Use% Mounted on
/dev/mapper/rl-root   70G  6.0G   65G   9% /
/dev/mapper/rl-home  6.9T  198G  6.7T   3% /home

トラブルシューティング

  • SELinux: 起動に失敗する場合、SELinuxが非標準ディレクトリへのアクセスをブロックしている可能性があります。一時的に setenforce 0 で切り分けを行うか、適切なコンテキストを設定してください。
  • JSON構文エラー: daemon.json の記述ミス(カンマ忘れなど)があるとDockerが起動しません。編集後は慎重に確認を行いましょう。