🐳

【最適化・格納先変更】Docker 肥大化したext4.vhdxの対処方法

2023/05/04に公開

概要

Cドライブが枯渇してきたので、サイズが大きいファイルを調査した結果、
Dockerデータファイル「ext4.vhdx」が肥大化して約15GBとなっていました。

調べた結果、対処方法が2つあり、その方法を紹介します。

  • Dockerデータファイルの最適化
  • Dockerデータファイルの格納先(保存場所)を変更

この記事のターゲット

  • 同じ現象でお悩みの方

事象

Cドライブの容量が枯渇し、サイズの大きいファイルを調べた結果、
Dockerデータファイルの「ext4.vhdx」が肥大化していた。

環境

  • OS
    Windows 10 Pro 22H2(OSビルド 19045.2846)
  • Docker
    Docker Desktop for Windows v4.18.0

一次対応(原因を特定する作業)

Cドライブ内でサイズが大きいファイルを調べる為、PowerShellのコマンドを使用。
結果、Dockerのデータファイル「ext4.vhdx」が肥大化していることが判明する。

調査方法

  1. サイズの大きいファイルTOP30を調べるコマンドを実行
    並び順はファイルサイズ(Length)の降順。

    コピー用
    (Get-ChildItem "C:\" -recurse -force | Select-Object Fullname,Length | Sort-Object Length -descending )[0..29] 2>$null
    
    “管理者として実行”の必要あり
    PS C:\WINDOWS\system32> (Get-ChildItem "C:\" -recurse -force | Select-Object Fullname,Length | Sort-Object Length -descending )[0..29] 2>$null
    
    FullName
    --------
    C:\Users\XXXX\AppData\Local\Docker\wsl\data\ext4.vhdx
    C:\pagefile.sys
    C:\hiberfil.sys
    C:\$Windows.~WS\Sources\Windows\sources\install.esd
    C:\$GetCurrent\media\sources\install.esd
    C:\Users\XXXX\AppData\Local\Docker\wsl\data\ext4.vhdx_bk20230401
    C:\ProgramData\Microsoft\Search\Data\Applications\Windows\Windows.edb
    C:\Program Files\Docker\Docker\resources\services.iso
    C:\Program Files (x86)\Adobe\Acrobat 11.0\Setup Files\{AC76BA86-1033-FFFF-7760-000000000006}\Data1.cab
    C:\Program Files\Docker\Docker\resources\wsl\docker-wsl-cli.iso
    C:\$Windows.~WS\Sources\Windows\sources\boot.wim
    C:\$GetCurrent\media\sources\boot.wim
    C:\Users\XXXX\.minikube\cache\preloaded-tarball\preloaded-images-k8s-v18-v1.26.3-docker-overlay2-amd64.ta...
    C:\Users\XXXX\AppData\Local\Temp\docker-scout\sha256\2511e1796e7d506ef370dd6dbe8ea2208402d9a058dd2a1db04b...
    C:\ProgramData\Intel Package Cache {1CEAC85D-2590-4760-800F-8DE5E91F3700}\Setup.exe
    C:\Users\XXXX\.minikube\cache\kic\amd64\kicbase_v0.0.39@sha256_bf2d9f1e9d837d8deea073611d2605405b6be90464...
    C:\Program Files\WindowsApps\MicrosoftCorporationII.WindowsSubsystemForLinux_1.2.5.0_x64__8wekyb3d8bbwe\system.vhd
    C:\Program Files\Docker\Docker\resources\docker-desktop.iso
    C:\MSOCache\All Users\{90150000-0012-0000-0000-0000000FF1CE}-C\StdWW2.cab
    C:\Users\XXXX\AppData\Local\Temp\docker-scout\sha256\4694d02f8e611efdffe9fb83a86d9d2969ef57b4b56622388eca...
    C:\Users\XXXX\AppData\Local\SquirrelTemp\tempa\lib\net45\resources\app.asar
    C:\MSOCache\All Users\{90140000-0012-0000-0000-0000000FF1CE}-C\StdWW.cab
    C:\Windows\Installer\97bfd59.msp
    C:\Windows\Installer\16da2.msp
    C:\Windows\Installer\165ad.msp
    C:\Windows\Installer\169ce.msp
    C:\Windows\Installer\15d3b.msp
    C:\Windows\Installer\1594e.msp
    C:\Windows\Installer\16180.msp
    C:\Windows\Installer\16a14.msp
    
    
    PS C:\WINDOWS\system32>
    
  2. 一番先頭(一番ファイルサイズが大きい)のファイルを確認
    ファイルサイズが「約15GB」である事を確認

    PS C:\Users\XXXX> dir C:\Users\XXXX\AppData\Local\Docker\wsl\data
    
    
        ディレクトリ: C:\Users\XXXX\AppData\Local\Docker\wsl\data
    
    
    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    -a----        2023/04/27      9:03    15471738880 ext4.vhdx
    

参考情報

原因

コンテナーDocker)のデータファイル(ext4.vhdx)の仕様を調べた結果、
コンテナー一度確保したディスク容量をホストに返さない仕組みとなっており、
イメージデータを削除してもvhdxファイルのサイズは、自動で減らない事が判明する。

一次対応で調査した結果とコンテナー仕様により、Cドライブがひっ迫した原因は、
コンテナー作成する度に増え続けた「ext4.vhdx」が原因である事が判明した。

参考情報:Docker データファイル 一覧

Docker内のLinuxディストリビューションとOS内のデータ格納先の紐づきをコマンドで確認した結果、
下記の通りとなった。

対象 WSL NAME データファイル格納先
docker-desktop C:\Users\XXXX\AppData\Local\Docker\wsl\distro
docker-desktop-data C:\Users\XXXX\AppData\Local\Docker\wsl\data
コマンドで確認した際のエビデンス < クリックで折りたたみが開く >
コピー用
wsl -l -v
wslの一覧を確認
PS C:\Users\XXXX> wsl -l -v
  NAME                   STATE           VERSION
* docker-desktop         Running         2
  docker-desktop-data    Running         2
PS C:\Users\XXXX>
コピー用
Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss
レジストリよりデータファイルの格納先を確認
PS C:\Users\XXXX> Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss


    Hive: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss


Name                           Property
----                           --------
{1218121f-4b5e-4e51-9c17-055e1 State            : 1
a071849}                       DistributionName : docker-desktop
                               Version          : 2
                               BasePath         : \\?\C:\Users\XXXX\AppData\Local\Docker\wsl\distro
                               Flags            : 15
                               DefaultUid       : 0
{8da9c252-3687-4270-b928-775fe State            : 1
8582b02}                       DistributionName : docker-desktop-data
                               Version          : 2
                               BasePath         : \\?\C:\Users\XXXX\AppData\Local\Docker\wsl\data
                               Flags            : 15
                               DefaultUid       : 0


PS C:\Users\XXXX>

対応方法

調査により対応方法は2パターンある事がわかる。

  • Dockerデータファイル(VHDファイル)の最適化
  • Dockerデータファイルの格納先を変更(Cドライブ→Dドライブ)

私の環境では最適化してもファイルサイズの減りが少量だった為、格納先の変更も実施した。
結果、2つとも対応した。

Dockerデータファイル(VHDファイル)の最適化

最適化コマンドにより不要なデータが取り除く事でvhdxファイルが圧縮され、
ファイルサイズを減らすことができる。

Win10 Pro/Enterpriseの場合:Hyper-Vのコマンドを使用した最適化

  1. 事前にHyper-V機能の有効化

    1. Windowsの機能の有効化または無効化を開く
      コントロールパネル -> プログラム -> Windowsの機能の有効化または無効化
    2. 下記2点の機能にチェックを入れてOKボタンをクリック
      • Hyper-V -> Hyper-V プラットフォーム -> Hyper-V サービス
      • Hyper-V -> Hyper-V 管理ツール -> Windows PowerShell 用 Hyper-V モジュール
  2. 事前のファイルサイズを確認
    私の環境では約15GBのファイルサイズがある事を確認。

    コピー用
    cd $Env:LOCALAPPDATA\docker\wsl\data
    dir
    
    PS C:\WINDOWS\system32> cd $Env:LOCALAPPDATA\docker\wsl\data
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data> dir
    
    
        ディレクトリ: C:\Users\XXXX\AppData\Local\docker\wsl\data
    
    
    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    -a----        2023/04/27      9:03    15471738880 ext4.vhdx
    
    
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    
  3. Docker Desktop & WSL の停止

    1. Docker Desktopの終了
      タスクトレイのDocker Desktopを右クリックしショートカット(コンテキスト)メニューより、
      「Quit Docker Desktop」をクリックする。

    2. WSLの終了
      管理者権限でPowerShell CLIを起動し、下記のコマンドを実行。

      コピー用
      wsl --shutdown
      wsl -l -v
      
      “管理者として実行”の必要あり
      PS C:\Users\XXXX\AppData\Local\docker\wsl\data> wsl --shutdown
      PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
      PS C:\Users\XXXX\AppData\Local\docker\wsl\data> wsl -l -v
        NAME                   STATE           VERSION
      * docker-desktop         Stopped         2
        docker-desktop-data    Stopped         2
      
  4. 最適化コマンドの実行

    コピー用
    Optimize-VHD -Path .\ext4.vhdx -Mode Full
    
    “管理者として実行”の必要あり
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data> Optimize-VHD -Path .\ext4.vhdx -Mode Full
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    
  5. 事後のファイルサイズを確認
    私の環境では15GB→14GBとなり、約1GB減った。

    PS C:\Users\XXXX\AppData\Local\docker\wsl\data> dir
    
    
        ディレクトリ: C:\Users\XXXX\AppData\Local\docker\wsl\data
    
    
    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    -a----        2023/04/27      9:20    14064549888 ext4.vhdx
    
    
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    

Win10 Homeの場合:Windows標準コマンドを使用した最適化

  1. 事前のファイルサイズを確認
    私の環境では約2.4GBである事を確認できた。
    (前述している15GBの環境とは別の環境で実施)

    コピー用
    cd $Env:LOCALAPPDATA\docker\wsl\data
    dir
    
    PS C:\WINDOWS\system32> cd $Env:LOCALAPPDATA\docker\wsl\data
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data> dir
    
    
        ディレクトリ: C:\Users\XXXX\AppData\Local\docker\wsl\data
    
    
    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    -a----        2023/04/27     12:19     2429550592 ext4.vhdx
    
    
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    
  2. Docker Desktop & WSL の停止

    1. Docker Desktopの終了
      タスクトレイのDocker Desktopを右クリックしショートカット(コンテキスト)メニューより、
      「Quit Docker Desktop」をクリックする。

    2. WSLの終了
      管理者権限でPowerShell CLIを起動し下記のコマンドを実行。

      コピー用
      wsl --shutdown
      wsl -l -v
      
      “管理者として実行”の必要あり
      PS C:\Users\XXXX\AppData\Local\docker\wsl\data> wsl --shutdown
      PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
      PS C:\Users\XXXX\AppData\Local\docker\wsl\data> wsl -l -v
        NAME                   STATE           VERSION
      * docker-desktop         Stopped         2
        docker-desktop-data    Stopped         2
      
  3. 最適化コマンドの実行

    1. DISKPARTの起動

      コピー用
      diskpart
      
      PowerShellを管理者として実行している場合
      PS D:\Virtual Machines\Docker\wsl\data> diskpart
      
      Microsoft DiskPart バージョン 10.0.19041.964
      
      Copyright (C) Microsoft Corporation.
      コンピューター: XXXX
      
      DISKPART>
      
    2. 最適化対象のファイルを設定

      コピー用
      select vdisk file='C:\Users\XXXX\AppData\Local\docker\wsl\data\ext4.vhdx'
      
      ファイルのパスを設定
      DISKPART> select vdisk file='C:\Users\XXXX\AppData\Local\docker\wsl\data\ext4.vhdx'
      
      DiskPart により、仮想ディスク ファイルが選択されました。
      
      DISKPART>
      
      コピー用
      attach vdisk readonly
      
      VHDファイルを読み取り専用としてアタッチ
      DISKPART> attach vdisk readonly
      
        100% 完了しました
      
      DiskPart により、仮想ディスク ファイルがアタッチされました。
      
      DISKPART>
      
    3. 最適化の実行

      コピー用
      compact vdisk
      
      DISKPART> compact vdisk
      
        100% 完了しました
      
      DiskPart により、仮想ディスク ファイルは正常に圧縮されました。
      
      DISKPART>
      
    4. DISKPARTの終了

      コピー用
      detach vdisk
      
      VHDファイルをデタッチ
      DISKPART> detach vdisk
      
      DiskPart により、仮想ディスク ファイルがデタッチされました。
      
      DISKPART>
      
      DISKPARTの終了
      DISKPART> exit
      
      DiskPart を終了しています...
      
      PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
      
  4. 事後のファイルサイズを確認
    私の環境では2.4GB→1.6GBとなり約0.8GBほど減った。

    PS C:\Users\XXXX\AppData\Local\docker\wsl\data> dir
    
    
        ディレクトリ: C:\Users\XXXX\AppData\Local\docker\wsl\data
    
    
    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    -a----        2023/04/28     11:47     1625292800 ext4.vhdx
    
    
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    

Dockerデータファイルの格納先を変更(Cドライブ→Dドライブ)

Docker Desktop for Windowsではインストール時にインストール先を変更する事ができない仕様となる。
自動的にWindows OSのインストールドライブにインストールされる為、大半の環境ではCドライブにインストールされている。

また、私の環境ではCドライブはOSで利用する必要最低限のサイズを割り当てているので、
コンテナー何回か作成すると、すぐにディスク容量が無くなってしまう。

紹介する手順ではCドライブに配置されているDockerのデータファイルをDドライブに格納先を変更する。

GUIによる格納場所の変更 < クリックで折りたたみが開く >

Docker DesktopのSettings内にデータファイルの格納先を変更する設定項目があるが、
2023年5月現在、変更してもずっと処理中となり正常動作しなかった

  • GUIで実施した手順

    1. タスクトレイにあるDocker Desktopを右クリックしショートカット(コンテキスト)メニューを表示
    2. Settings Ctrl + カンマを選択
    3. Resources -> Advanced -> Disk image location の値を確認
      初期値のC:\Users\XXXX\AppData\Local\Docker\wslである事を確認
    4. BrowseボタンをクリックしDドライブ上の任意のパスに変更
    5. Apply & restart ボタンをクリック

    → 項番5のApply & restart ボタンをクリックの後、自動的にDocker Desktopが再起動され、
      ずっと処理中のまま(青い線が円を描きクルクル回る)となる。
      タスクトレイのDocker Desktopを右クリックしショートカット(コンテキスト)メニューより、
      「Quit Docker Desktop」をクリックする。
      その後、手動で起動するとソフトが自動的で落ちてしまい、再インストールが必要となった。

コマンドによる格納場所の変更

  1. Docker Desktop & WSL の停止

    1. Docker Desktopの終了
      タスクトレイのDocker Desktopを右クリックしショートカット(コンテキスト)メニューより、
      「Quit Docker Desktop」をクリックする。

    2. WSLの終了

      コピー用
      wsl --shutdown
      wsl -l -v
      
      “管理者として実行”の必要あり
      PS C:\WINDOWS\system32> wsl --shutdown
      PS C:\WINDOWS\system32>
      PS C:\WINDOWS\system32> wsl -l -v
        NAME                   STATE           VERSION
      * docker-desktop         Stopped         2
        docker-desktop-data    Stopped         2
      
  2. 新しい格納先を作成

    コピー用
    mkdir 'D:\Virtual Machines\Docker\wsl\data'
    
    PS C:\Users\XXXX> mkdir 'D:\Virtual Machines\Docker\wsl\data'
    
    
    	ディレクトリ: D:\Virtual Machines\Docker\wsl
    
    
    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    d-----        2023/04/27     10:17                data
    
    
    PS C:\Users\XXXX>
    
  3. Dockerのデータファイルをエクスポート

    コピー用
    cd $Env:LOCALAPPDATA\docker\wsl\data
    wsl --export docker-desktop-data 'D:\Virtual Machines\Docker\wsl\data\docker-desktop-data.tar'
    
    “管理者として実行”の必要あり
    PS C:\WINDOWS\system32> cd $Env:LOCALAPPDATA\docker\wsl\data
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data> wsl --export docker-desktop-data 'D:\Virtual Machines\Docker\wsl\data\docker-desktop-data.tar'
    エクスポートが進行中です。これには数分かかる場合があります。
    この操作を正しく終了しました。
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    
    コピー用
    dir 'D:\Virtual Machines\Docker\wsl\data'
    
    エクスポートされた事を確認
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data> dir 'D:\Virtual Machines\Docker\wsl\data'
    
    
        ディレクトリ: D:\Virtual Machines\Docker\wsl\data
    
    
    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    -a----        2023/04/27     10:17    12274206720 docker-desktop-data.tar
    
  4. Dockerのデータファイルをコピーバックアップ

    コピー用
    Copy-Item .\ext4.vhdx .\ext4.vhdx_bk20230427
    dir
    
    PS C:\Users\XXXX\AppData\Local\Docker\wsl\data> Copy-Item .\ext4.vhdx .\ext4.vhdx_bk20230427
    PS C:\Users\XXXX\AppData\Local\Docker\wsl\data>
    PS C:\Users\XXXX\AppData\Local\Docker\wsl\data> dir
    
    
        ディレクトリ: C:\Users\XXXX\AppData\Local\Docker\wsl\data
    
    
    	Mode                 LastWriteTime         Length Name
    	----                 -------------         ------ ----
    	-a----        2023/04/27      9:20    14064549888 ext4.vhdx
    	-a----        2023/04/27      9:20    14064549888 ext4.vhdx_bk20230427
    
    
    PS C:\Users\XXXX\AppData\Local\Docker\wsl\data>
    
  5. wsl上からDockerデータファイルを解除

    コピー用
    wsl --unregister docker-desktop-data
    
    “管理者として実行”の必要あり
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data> wsl --unregister docker-desktop-data
    登録解除。
    この操作を正しく終了しました。
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    
  6. Dockerデータファイルが削除&登録解除されている事を確認

    自動的にデータファイルが削除されている事を確認
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data> dir
    
    
        ディレクトリ: C:\Users\XXXX\AppData\Local\Docker\wsl\data
    
    
    	Mode                 LastWriteTime         Length Name
    	----                 -------------         ------ ----
    	-a----        2023/04/27      9:20    14064549888 ext4.vhdx_bk20230401
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    
    コピー用
    wsl -l -v
    
    登録解除されている事を確認
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data> wsl -l -v
      NAME              STATE           VERSION
    * docker-desktop    Stopped         2
    PS C:\Users\XXXX\AppData\Local\docker\wsl\data>
    
  7. 新しい格納場所でDockerデータファイルをインポート

    1. 新しい格納場所に移動

      コピー用
      cd 'D:\Virtual Machines\Docker\wsl\data\'
      dir
      
      PS C:\Users\XXXX\AppData\Local\docker\wsl\data> cd 'D:\Virtual Machines\Docker\wsl\data\'
      PS D:\Virtual Machines\Docker\wsl\data>
      PS D:\Virtual Machines\Docker\wsl\data> dir
      
      
          ディレクトリ: D:\Virtual Machines\Docker\wsl\data
      
      
      Mode                 LastWriteTime         Length Name
      ----                 -------------         ------ ----
      -a----        2023/04/27     10:17    12274206720 docker-desktop-data.tar
      
      
      PS D:\Virtual Machines\Docker\wsl\data>
      
    2. Dockerのデータファイルをインポート

      コピー用
      wsl --import docker-desktop-data "D:\Virtual Machines\Docker\wsl\data" docker-desktop-data.tar --version 2
      
      PS D:\Virtual Machines\Docker\wsl\data> wsl --import docker-desktop-data "D:\Virtual Machines\Docker\wsl\data" docker-desktop-data.tar --version 2
      インポート中です。この処理には数分かかることがあります。
      この操作を正しく終了しました。
      PS D:\Virtual Machines\Docker\wsl\data>
      
    3. 正しくインポートされたことを確認

      VHDファイルが生成されている事を確認
      PS D:\Virtual Machines\Docker\wsl\data> dir
      
      
          ディレクトリ: D:\Virtual Machines\Docker\wsl\data
      
      
      Mode                 LastWriteTime         Length Name
      ----                 -------------         ------ ----
      -a----        2023/04/27     10:17    12274206720 docker-desktop-data.tar
      -a----        2023/04/27      9:20    14064549888 ext4.vhdx
      
      
      PS D:\Virtual Machines\Docker\wsl\data>
      
      コピー用
      wsl -l -v
      
      登録されている事を確認
      PS D:\Virtual Machines\Docker\wsl\data> wsl -l -v
        NAME                   STATE           VERSION
      * docker-desktop         Stopped         2
        docker-desktop-data    Stopped         2
      PS D:\Virtual Machines\Docker\wsl\data>
      
インポートコマンド「wsl --import」でエラーが発生した場合

別の環境で同じ作業した結果、エラーが発生しました。
環境によりインポートでエラーが発生するようです。

エラー内容
PS D:\Virtual Machines\Docker\wsl\data> wsl --import docker-desktop-data "D:\Virtual Machines\Docker\wsl\data" docker-desktop-data.tar --version 2
インポート中です。この処理には数分かかることがあります。
エラーを特定できません
Error code: Wsl/Service/E_FAIL
PS D:\Virtual Machines\Docker\wsl\data>
対処方法(未検証)

インポートをtarファイルではなくVHDファイルを参照しインポートする方法で解決するもよう。
私は再インストールにより環境を初期化した為、この対象方法は未検証です。

コピー用
wsl --import docker-desktop-data "D:\Virtual Machines\Docker\wsl\data" docker-desktop-data.vhdx --version 2 --vhd
PS D:\Virtual Machines\Docker\wsl\data> wsl --import docker-desktop-data "D:\Virtual Machines\Docker\wsl\data" docker-desktop-data.vhdx --version 2 --vhd

参考記事

まとめ

  • (私の環境では)最適化した結果、少量しかファイルサイズが減らない
  • データ格納用のドライブがある場合、Dockerデータファイルの格納先を変更

格納先変更後は、様子を見て定期的に最適化を実行する流れが良いと思います。
本番運用中のコンテナーでは危険が伴う作業だと思いますが、
開発環境であれば下記方法で常にファイルサイズが最適化された状態となると思われます。

  1. コピーバックアップと最適化コマンドを実施するスクリプトを作成
  2. ジョブスケジューラによりスクリプトを定期的に実行
GitHubで編集を提案

Discussion