てっく・ざ・ぶろぐ!

気ままに書きます

肥大化するDockerとSSDの増設(#1)

はじめに

先日、研究室サーバーで削除されずに残った不要なDockerイメージ・コンテナが、ディスク容量をひっ迫していることに気が付きました。

対策として、SSDを増設しつつDockerのストレージディレクトリ(デフォルトは/var/lib/docker)を変更する方法を紹介します。

1. SSDの増設

サーバーマシンのOSは、Ubuntu 20.04.6 LTSです。

今回は以下のSSDを増設しました。

www.crucial.jp

また、増設にあたって以下の記事が参考になりました。

clock-up.hateblo.jp

まずはサーバーマシンの電源を落とし、電源ケーブルを抜きます。

SSDはネジでマウンタに固定してから挿入します。

SSDを購入した際にはネジは付属していなかったので、ネジのセット(例:https://amzn.asia/d/07dCVfpV)を購入しておくと安心です。今回はM 3*8サイズがピッタリでしたが、SSDやマシンによって異なる可能性があります。

1.1. ディスクのデバイス名を確認

SSDを挿入して電源を入れたら、デバイスカーネルに認識されているか確認します。

fdiskコマンドは、-lオプションで指定デバイスパーティションテーブルを表示しますが、デバイス名を指定しない場合は/proc/partitionsに書かれているデバイスを参照します。

$ fdisk -l
ディスク /dev/sda: 3.5 TiB, 3840755982336 バイト, 7501476528 セクタ
Disk model: INTEL SSDSC2KB03
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 4096 バイト
I/O サイズ (最小 / 推奨): 4096 バイト / 4096 バイト
ディスクラベルのタイプ: gpt
ディスク識別子: ****************-****-****-****-****************

デバイス     開始位置   最後から     セクタ サイズ タイプ
/dev/sda1        ****     ******     ******    *** EFI システム
# (省略)


ディスク /dev/sdb: 3.65 TiB, 4000787030016 バイト, 7814037168 セクタ
Disk model: CT4000MX500SSD1
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 4096 バイト
I/O サイズ (最小 / 推奨): 4096 バイト / 4096 バイト


ディスク /dev/sdc: 16.38 TiB, 18000207937536 バイト, 35156656128 セクタ
Disk model: WDC  WUH721818AL
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 4096 バイト
I/O サイズ (最小 / 推奨): 4096 バイト / 4096 バイト
ディスクラベルのタイプ: gpt
ディスク識別子: ****************-****-****-****-****************

デバイス   開始位置    最後から      セクタ サイズ タイプ
/dev/sdc1      **** *********** ***********  ***** Linux ファイルシステム

今回新しく挿入したSSDDisk modelや容量などから/dev/sdbだと分かりました(より詳細な識別情報が欲しい場合はhdparmコマンド-Iオプションが便利です)。

万が一デバイスが認識されない場合は、電源を落としてからSSDが正しく挿入されているか再確認する必要があります。

1.2. パーティションの作成

先ほどと同じfdiskコマンドを使用して、ディスク上に新しいパーティションを作成します。

最初は、先述の記事に従って以下のように実行してみました。

$ fdisk /dev/sdb

fdisk (util-linux 2.34) へようこそ。
ここで設定した内容は、書き込みコマンドを実行するまでメモリのみに保持されます。
書き込みコマンドを使用する際は、注意して実行してください。

デバイスには認識可能なパーティション情報が含まれていません。
このディスクのサイズは 3.7 TiB (4000787030016 バイト) です。DOS パーティションテーブル形式では 2199023255040 バイト以上のドライブには セクタサイズ 512 バイトを使用することができません。GUID パーティションテーブル (GPT) 形式を使用してください。

新しい DOS ディスクラベルを作成しました。識別子は 0x******** です。

コマンド (m でヘルプ): n
パーティションタイプ
   p   基本パーティション (0 プライマリ, 0 拡張, 4 空き)
   e   拡張領域 (論理パーティションが入ります)
選択 (既定値 p): p
パーティション番号 (1-4, 既定値 1): 1
最初のセクタ (2048-4294967295, 既定値 2048): 2048
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-4294967295, 既定値 4294967295):

新しいパーティション 1 をタイプ Linux、サイズ 2 TiB で作成しました。

残念ながら、ディスクサイズである3.7 TiBのうち2 TiBしか使用されずパーティションが作成されてしまいました。よく見ると、DOS パーティションテーブル形式では 2199023255040 バイト以上のドライブには セクタサイズ 512 バイトを使用することができません。GUID パーティションテーブル (GPT) 形式を使用してください。と説明がありました。

GPTパーティションテーブルを作成するには、gdiskコマンドpartedコマンドを使用するのが一般的なようですが、util-linux 2.23以降はfdiskコマンドでもGPTパーティションテーブルがサポートされている*1そうです。

今回はDockerのストレージディレクトリを変更することが目的であり、3.7 TiBをフル活用したいため、以下のように実行します。

# コマンド (m でヘルプ): d
# パーティション 1 を選択
# パーティション 1 を削除しました。

コマンド (m でヘルプ): g
新しい GPT ディスクラベル (GUID: *****************-****-****-****-************) を作成しました。

コマンド (m でヘルプ): n
パーティション番号 (1-128, 既定値 1):
最初のセクタ (2048-7814037134, 既定値 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-7814037134, 既定値 7814037134):

新しいパーティション 1 をタイプ Linux filesystem、サイズ 3.7 TiB で作成しました。

コマンド (m でヘルプ): w
パーティション情報が変更されました。
ioctl() を呼び出してパーティション情報を再読み込みします。
ディスクを同期しています。

1.3. ファイルシステムの作成

mkfsコマンドを使用して、作成したパーティション上にファイルシステムを構築します。

ファイルシステムの種類については、以下のドキュメントに簡単にまとめられています。

man filesystems (5): Linux のファイルシステム種別: minix, ext, ext2, ext3, ext4,

今回は、Linuxで最も広く使われているext4を採用しました。

$ cd /sbin

$ ls -1 mkfs.*
mkfs.bfs
mkfs.btrfs
mkfs.cramfs
mkfs.ext2
mkfs.ext3
mkfs.ext4
mkfs.fat
mkfs.minix
mkfs.msdos
mkfs.ntfs
mkfs.vfat
mkfs.xfs

$ mkfs -t ext4 /dev/sdb1
mke2fs 1.45.5 (07-Jan-2020)
Discarding device blocks: done
Creating filesystem with 976754385 4k blocks and 244195328 inodes
Filesystem UUID: ****-****-****-****-****-********
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
    4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
    102400000, 214990848, 512000000, 550731776, 644972544

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

1.4. ファイルシステムのマウント

最後にmountコマンドを使用して、/dev/sdb1を任意のディレクトリにマウントします。

$ mount /dev/sdb1 /mnt/ssd4tb/

$ df -h
Filesystem            Size  Used Avail Use% Mounted on
# (省略)
/dev/sdb1             3.6T   89M  3.4T   1% /mnt/ssd4tb

また、リブートしても自動でマウントされるように/etc/fstabに追記します。ファイルシステムのUUIDはlsblkコマンドで確認できます。

$ lsblk -f
NAME   FSTYPE LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINT
sda
# (省略)
sdb
└─sdb1 ext4         ********-****-****-****-************    3.4T     1% /mnt/ssd4tb
sdc
# (省略)
sr0

$ echo "UUID=********-****-****-****-************ /mnt/ssd4tb ext4 defaults 0 2" >> /etc/fstab

パラメータの設定は以下の記事が分かりやすかったです。

An introduction to the Linux /etc/fstab file | Enable Sysadmin

2. Dockerストレージディレクトリの変更

手順は、以下の素晴らしい記事の通りです。

zenn.dev

ここでは実行したコマンドとその結果のみ紹介します。

$ cd /mnt/ssd4tb
$ sudo cp -ar /var/lib/docker/ .

$ docker -v
Docker version 26.0.0, build 2ae903e
$ sudo vim /lib/systemd/system/docker.service
# `ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock`の後に` --data-root /mnt/ssd4tb/docker`を追加

$ sudo systemctl daemon-reload
$ sudo systemctl start docker
$ sudo systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2024-06-20 15:21:42 JST; 20s ago
# (省略)
$ docker info | grep "Docker Root Dir:"
 Docker Root Dir: /mnt/ssd4tb/docker

$ docker images
# (省略)
$ docker run -it --rm busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
ec562eabd705: Pull complete
Digest: sha256:9ae97d36d26566ff84e8893c64a6dc4fe8ca6d1144bf5b87b2b85a32def253c7
Status: Downloaded newer image for busybox:latest
/ # echo "Hello World"
Hello World
/ # exit

動作確認まで完了し、無事にDockerのストレージディレクトリを変更できました。

先述した記事でも言及されていますが、docker -vでバージョンを確認しているのは、Docker Engine v23.0で--graphオプションが廃止されて--data-rootオプションになった*2ためです。複数のマシンでSSD増設を行いましたが、v23.0以前のDocker Engineも混ざっていたため注意が必要でした。

まとめ

今回は、SSDを増設しつつDockerのストレージディレクトリを変更する方法について紹介しました。

パブリッククラウドを利用すれば簡単にボリュームをアタッチできる時代に、このような経験ができたことは貴重ですし、ストレージに対する理解も深まりました。

これでしばらくは、ストレージ容量が不足して困ることはなさそうです。現状不足しているのは研究の進捗のみです。