删除Docker镜像后,磁盘空间仍被占用问题

67
我将一个已存在的Docker容器提交为一个新镜像,但提交后的镜像太大了(原始镜像是3+GB,加上一些额外安装的内容后,提交的镜像变成了8+GB)。
因为空间不足,我决定删除提交的镜像,但即使在删除提交的镜像后,我的磁盘空间仍然没有释放。然而,当我运行 docker system df时,它只显示应该使用原始镜像和容器的空间(我只有一个镜像和一个容器)。
是否有任何方法可以释放我确信仍被该已删除的镜像占用的空间? (供参考,我创建了镜像,然后在一个小时内删除了它,并不断监视我的可用空间,所以我很确定这是占用空间的问题,而不是其他什么问题。)
此外,我正在使用集成了WSL2的Docker Desktop for Windows,因此无法仅通过转到 /var/lib/docker 检查Docker的磁盘使用情况。

与此问题相同的情况,您可以尝试这些命令:https://dev59.com/5VgQ5IYBdhLWcg3wPxnb#43068138 - Daniel Marques
9个回答

112

我使用以下命令将桌面镜像从35GB缩减到1GB

(在Windows 10,docker版本为19.03.13)

删除未使用的镜像和其他资源

docker system prune -a

删除更多资源

docker volume rm $(docker volume ls -q -f dangling=true)

停止Docker Desktop,优化镜像

确保已启用Hyper-V

%windir%\System32\mmc.exe "%windir%\System32\virtmgmt.msc" 或在win搜索栏中输入Hyper-V

在GUI中优化磁盘>转到VM,并检查磁盘

Optimize-VHD -Path "C:\ProgramData\DockerDesktop\vm-data\DockerDesktop.vhdx" -Mode Full

启动Docker Desktop

现在我有超过34GB的可用磁盘空间

使用Docker Desktop应用程序进行清理

您可以在单击标题中的错误图标,然后单击清除/清除数据时清除数据。

enter image description here

清除/清除数据选项不会删除WSL集成。


Optimize-VHD命令正是我所需要的。非常感谢。尽管我在容器中释放了空间,但仍然被占用,这让我很烦恼。 - Kobato
感谢这些步骤,我在我的465Gb固态硬盘中恢复了260Gb的空间 :) - Santosh Karanam
1
救了我的一天。恢复了140GB的数据,我的工作日顺利完成。 - Nícolas Amarante

39

如果在尝试执行Optimize-VHD时出现错误:

Optimize-VHD : The term 'optimize-vhd' is not recognized as the name of a cmdlet

您可以使用 diskpart 替代:

wsl --shutdown
diskpart
select vdisk file="C:\Users\{YourUser}\AppData\Local\Docker\wsl\data\ext4.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
exit

访问被拒绝。我如何仍然删除vhdx文件? - drupalfan
3
请确保您以管理员身份运行用于执行这些命令的终端,@drupalfan。 - Trevor
DiskPart has encountered an error: Incorrect function. - undefined

19

这段代码可用作从提升权限的 PowerShell 会话中快速修复的方法。我必须使用pwsh,因为它可以在不使用临时文件的情况下正确地与diskpart一起工作。

docker system prune -a --volumes
net stop com.docker.service
taskkill /IM "docker.exe" /F
taskkill /IM "Docker Desktop.exe" /F
wsl --shutdown
((@"
select vdisk file="%LOCALAPPDATA%\Docker\wsl\data\ext4.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
exit
"@
)|diskpart)
net start com.docker.service
. "C:\Program Files\Docker\Docker\Docker Desktop.exe"

11

由于你正在使用Windows并在Docker Desktop中运行,因此实际上是在虚拟机中运行Docker。然后,它取决于磁盘映像大小设置,通常虚拟磁盘会扩展以填充该空间。

但是,您可以缩小磁盘映像:

  • 停止Docker Desktop

  • 打开管理员PowerShell终端

  • 运行Optimize-VHD -Path "C:\ProgramData\DockerDesktop\vm-data\DockerDesktop.vhdx" -Mode Full,其中路径是在Docker Desktop设置>资源>高级>磁盘映像位置中记录的路径。

  • 启动Docker Desktop

这样应该会缩小Docker虚拟机。


我没有“docker桌面设置>资源>高级>磁盘映像位置”菜单,你使用的是哪个docker桌面版本?我使用的是Docker Engine 19.03.13。 - Fjordo
如果即使以管理员身份运行,Optimize-VHD 仍然失败并显示“访问被拒绝”,请打开 DockerDesktop.vhdx 文件属性 > 安全 > 高级,并授予特定用户完全控制权限,然后再次尝试。 - sparrowt

6

我用以下步骤清理了 Docker 空间。

  1. 在 Windows 命令提示符中执行 "docker system prune -f"(它说要释放 45GB。但是,我只能看到 6GB)。

  2. 打开 Docker Desktop 应用程序。

  3. 导航到故障排除菜单,点击“清理/清除数据”按钮。

请注意,这将清除 Docker 中的所有数据。


2

如果您在Windows上使用Docker Desktop且使用后端Hyper-V而不是WSL2(以管理员身份在PowerShell中运行):

docker system prune -a -f
net stop com.docker.service
taskkill /F /IM "Docker Desktop.exe"
taskkill /F /IM "docker.exe"
Stop-VM -VMName "DockerDesktopVM" -Force # or -TurnOff but process may be stuck
Optimize-VHD -Path "C:\ProgramData\DockerDesktop\vm-data\DockerDesktop.vhdx" -Mode Full
net start com.docker.service
Start-Process -FilePath "C:\Program Files\Docker\Docker\Docker Desktop.exe" -Verb RunAs

我的PowerShell脚本DockerDesktopVM_cleanup.ps1每3天在本地服务器(windows 10 x64 ltsc 1809)上使用Windows任务计划程序运行。

# Run powershell with Admin privileges 
param([switch]$Elevated)

function RunAsAdmin {
    $currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
    $currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
function Get-VM-PID-By-GUID($GUID){
    return (Get-CimInstance Win32_Process -Filter "name ='vmwp.exe'" | Where-Object {$_.CommandLine  -Like "*"+$GUID+"*"} | select-object ProcessId -ErrorAction Stop).ProcessId
}

if ((RunAsAdmin) -eq $false)  {
    if ($elevated) {
        # tried to elevate, did not work, aborting
    } else {
        Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -noexit -file "{0}" -elevated' -f ($myinvocation.MyCommand.Definition))
    }
    exit
}
'running with full privileges'

docker system prune -a -f
net stop com.docker.service
taskkill /F /IM "docker.exe"
taskkill /F /IM "Docker Desktop.exe"
# update Access Control List for vm file  
$ACL = Get-ACL -Path "C:\Docker\DockerDesktop\DockerDesktop.vhdx"
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("<PUT-YOUR-ROLE>","FullControl","Allow")
$ACL.SetAccessRule($AccessRule)
$ACL | Set-Acl -Path "C:\Docker\DockerDesktop\DockerDesktop.vhdx"
(Get-ACL -Path "C:\Docker\DockerDesktop\DockerDesktop.vhdx").Access | Format-Table IdentityReference,FileSystemRights,AccessControlType,IsInherited,InheritanceFlags -AutoSize

# WARNING process may be stuck with this command: Stop-VM -VMName "DockerDesktopVM" -Force/-TurnOff 
$VMGUID = (Get-VM "DockerDesktopVM").VMId.Guid
$VMPID = Get-VM-PID-By-GUID -GUID $VMGUID
Stop-Process ($VMPID) –Force
Optimize-VHD -Path "C:\Docker\DockerDesktop\DockerDesktop.vhdx" -Mode Full
#Start-VM -VMName "DockerDesktopVM" is not needed Docker will be able to start itself
# resume docker
net start com.docker.service
Start-Process -FilePath "C:\Program Files\Docker\Docker\Docker Desktop.exe" -Verb RunAs

0
如果你使用的是Windows系统,你可能想要检查一下C:\Users\Username\AppData\Local\temp目录下是否存在一个名为"docker-scout"的文件夹。即使在卸载docker之后,这个文件夹仍然存在,并且通常会占用大量磁盘空间。

0

如果你即使以'管理员'权限启动powershell时仍看到'访问被拒绝',那么这可能意味着你当前的用户不是管理员。例如,如果你使用Microsoft账户,则你的本地管理员是一个不同的用户。因此,你需要将当前会话用户添加到vhdx文件权限中——'完全控制'。此外,你可以在这里找到有关修复与vhdx访问相关的问题的方法:https://dev59.com/elgQ5IYBdhLWcg3wLg85#73070459

然后,你就能够无问题地开始执行命令(但首先备份vhdx):

Optimize-VHD -Path C:\ProgramData\DockerDesktop\vm-data\DockerDesktop.vhdx -Mode Full

还要在需要之前优雅地停止"Docker Descktop"(即没有虚拟机正在运行或挂起在任务管理器中,如vmwp.exe)。

查看原文:Docker Image Taking up Space After Deletion

如果Optimize-VHD或压缩命令对您无效。并且您的虚拟磁盘包含Linux文件系统,并且通过df(可用空间)在此磁盘中看到一个空闲空间。那么,可能需要在压缩(Optimize-VHD或压缩)之前将空白空间清零。要进行清零,可以使用不同的方法。例如,在任何Docker容器内使用此命令(自行承担风险),因为默认情况下,容器会动态共享磁盘大小与Docker主机系统:
dd if=/dev/zero of=zerofillfile bs=1M

接着,在出现错误信息后,运行以下命令:

rm zerofilefile

http://www.netreliant.com/news/8/17/Compacting-VirtualBox-Disk-Images-Linux-Guests.html

这里有几种方法:https://www.altaro.com/hyper-v/compact-vhdx-linux-filesystem/ 或者从这里也可以适用于我:https://stackoverflow.com/a/60450188/5966911

在清零之后,您可以使用Optimize-VHD或diskpart实用程序重复“练习” https://stackoverflow.com/a/60450188/5966911


0

我在使用非常大的docker buildx缓存时遇到了这个问题,而且我不想修剪所有缓存,因为过滤器参数目前已损坏

PS> docker run -it --rm ubuntu:18.04 df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay         252G  249G    0G 100% /
tmpfs            64M     0   64M   0% /dev
tmpfs           7.9G     0  7.9G   0% /sys/fs/cgroup
shm              64M     0   64M   0% /dev/shm
/dev/sdd        252G  249G    0G 100% /etc/hosts < this is the device we have to expand

请注意哪个设备已满。这是您稍后必须调整大小的磁盘。

使用diskpart扩展虚拟磁盘

WSL2下,按照Microsoft关于扩展vdisk大小的说明,这应该允许您扩展数据/缓存挂载点。

如果您像我一样将Docker vhdxAppData/Packages移动,并且它未在Docker Desktop GUI中列出,则可以在设置中找到它:

PS> cat $env:APPDATA\Docker\settings.json | Select-String dataFolder
  
    "dataFolder": "D:\\DockerDesktop",

wsl/data 目录下找到 ext4.vhdx 文件(不是 DockerDesktop.vhdx!),使用 diskpart 扩展磁盘。

DISKPART> select vdisk file="D:\DockerDesktop\wsl\data\ext4.vhdx"

DiskPart successfully selected the virtual disk file.

DISKPART> detail vdisk

Device type ID: 0 (Unknown)
Vendor ID: {00000000-0000-0000-0000-000000000000} (Unknown)
State: Added
Virtual size:  256 GB
Physical size:  252 GB
Filename: D:\DockerDesktop\wsl\data\ext4.vhdx
Is Child: No
Parent Filename:
Associated disk#: Not found.

要扩展到512 GB,请输入以MB为单位的大小(512000),然后退出diskpart。

DISKPART> expand vdisk maximum=512000
DISKPART> exit

在WSL中扩展磁盘空间

为了允许Docker使用额外的空间,请启动您的WSL2分发版。这并不需要使用docker来完成(这是我个人最初感到有些困惑的地方)。

PS> wsl
user@WSL2:/mnt/c/Users/user$ sudo mount -t devtmpfs none /dev
user@WSL2:/mnt/c/Users/user$ mount | grep ext4

/dev/sdb on / type ext4 (rw,relatime,discard,errors=remount-ro,data=ordered)
/dev/sdd on /mnt/wsl/docker-desktop-data/isocache type ext4 (rw,relatime,discard,errors=remount-ro,data=ordered)

isocache 现在在 /dev/sdd 上(与之前整个磁盘匹配)。使用新的大小类型后缀运行 resize2fs 命令进行调整。

sudo resize2fs /dev/<DEVICE> 512000M

请检查您是否有更多的空间!

docker run -it --rm ubuntu:18.04 df -h


Filesystem      Size  Used Avail Use% Mounted on
overlay         492G  249G  220G  54% /
tmpfs            64M     0   64M   0% /dev
tmpfs           7.9G     0  7.9G   0% /sys/fs/cgroup
shm              64M     0   64M   0% /dev/shm
/dev/sdd        492G  249G  220G  54% /etc/hosts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接