当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 扩展 PowerShell 和 Docker 容器

作者:精品下载站 日期:2024-12-14 07:54:59 浏览:14 分类:玩电脑

扩展 PowerShell 和 Docker 容器


我一直在继续修改我的 PowerShell 命令来获取有关 Docker 容器的信息。 Docker CLI 很好,但处理输出或用它做很多事情非常困难。这就是为什么我更喜欢在 PowerShell 管道中包含对象。到目前为止我忽略的 Docker 容器元素之一是容器大小。容器的全部优点在于它们的设计很小,所以为什么不获取这些信息呢?

集装箱尺寸

您可以使用 Docker CLI 显示容器大小。

[玩转系统] 扩展 PowerShell 和 Docker 容器

据我所知,这是容器中可写层的大小。对我来说这似乎总是 0 字节。尽管如此,最终我可能会拥有一个具有实际值的容器,因此我需要一些代码来提取它。

$name = "cow1"
$sz = docker ps -asf "name=$name" --format "{{json .}}" | Convertfrom-json | Select -expandproperty size
[regex]$rx = "\d+"
$szbytes = $rx.match($sz).value

使用我上次讨论的 JSON 技巧,我可以提取 Size 属性,在我的例子中该属性为 0B。我使用正则表达式模式来获取该字符串的数字部分,即 0。

获取 Docker 文件

每个容器还包含一组文件,例如日志,这些文件存储在 Docker 程序位置。使用一点 PowerShell 处理,我可以从 Docker 系统信息中获取该位置。

$dockpath = ((docker system info | select-string "docker root dir") -split ": ")[1]

在 Windows 中,这应该是 C:\ProgramData\Docker。每个容器都有自己的目录。

[玩转系统] 扩展 PowerShell 和 Docker 容器

文件夹名称是我已经知道如何获取的容器ID。从这里开始,测量所有文件的总大小就很简单了。

$name = "cow1"
$ID = (docker inspect $name --format "{{json .ID}}") -replace '"',''
$stat = Get-Childitem (join-path $dockpath "containers$ID") -file -recurse | 
Measure-Object -Property length -sum

$Stat 给出的总和值为 11977。

包括 Docker 容器卷

最后,容器可能具有用于持久存储的关联卷。

$c = docker inspect cow1 | Convertfrom-json

[玩转系统] 扩展 PowerShell 和 Docker 容器

同样,这很容易衡量。

$m = $c.mounts | foreach { get-childitem -path $_.source -file -recurse } | 
measure-object length -sum

然后我可以将所有值加在一起以获得容器大小的非常接近的近似值。

更新了PowerShell功能

考虑到这一点,我更新了 Get-DockerContainer 函数。

Get-DockerContainer.ps1:

#requires -version 5.1

Function Get-DockerContainer {
    [cmdletbinding(DefaultParameterSetName = "name")]
    [alias("gdc")]
    [OutputType("Get-DockerContainer.myDockerContainer")]

    Param(
        [Parameter(Position = 0, HelpMessage = "Enter a docker container name. The default is all running containers.", ParameterSetName = "name")]
        [ValidateNotNullorEmpty()]
        [string[]]$Name,
        [Parameter(HelpMessage = "Get all containers, not just those that are running.", ParameterSetName = "all")]
        [switch]$All
    )

    Begin {
        Write-Verbose "[BEGIN  ] Starting: $($MyInvocation.Mycommand)"

        #define a class for my docker container objects
        Class myDockerContainer {

            [string]$ID
            [string]$Name
            [datetime]$Created
            [string]$State
            [Boolean]$IsRunning
            [datetime]$Started
            #define Finished as a generic object so it can be null or a datetime
            [object]$Finished
            [timespan]$Runtime
            [string]$Image
            [object[]]$Mount
            [string]$Platform
            [int]$Size
            [string]$Path

            #methods
            [timespan] GetRuntime([datetime]$Start, [datetime]$End) {
                return ($end - $start)
            }
            [string] GetImageName([string]$image) {
                $val = (docker image inspect ($image -split ":")[1] --format "{{json .RepoTags}}") -replace '\[|\]|"', ""
                return $val
            }
            [int] GetContainerSize() {

                $stat = Get-Childitem $this.path -file -recurse | Measure-Object length -sum

                $sz = docker ps -asf "name=$($this.name)" --format "{{json .}}" | ConvertFrom-Json | Select-Object -expandproperty size
                [regex]$rx = "\d+"
                [int]$szbytes = $rx.match($sz).value
                if ($this.mount) {
                    [int]$mnt = ($this.mount |
                            ForEach-Object { Get-ChildItem -path $_.source -file -recurse } |
                            Measure-Object length -sum).sum
                }
                else {
                    $mnt = 0
                }

                $totalsz = $stat.sum + $szbytes + $mnt

                return $totalsz
            }
            #the constructor
            myDockerContainer ($Name) {
                #get the docker installation directory
                $dockpath = ((docker system info | Select-String "docker root dir") -split ": ")[1]
                $json = docker container inspect $Name | ConvertFrom-Json

                $this.Name = $Name.replace('"', '')
                $this.Created = $json.Created
                $this.ID = $json.ID
                $this.IsRunning = $json.state.Running
                #adjust date to localtime because PowerShell Core converts it differently than Windows PowerShell
                $this.Started = ($json.state.startedat -as [datetime]).toLocalTime()
                $this.Finished = if ($this.IsRunning) { $null } else {$json.state.finishedat -as [datetime]}
                $this.Runtime = if ($this.IsRunning) { $this.GetRuntime($this.started, (Get-Date) )} else {$this.GetRuntime($this.started, $this.finished )   }
                $this.State = $json.state.status
                $this.image = $this.GetImageName($json.image)
                $this.platform = $json.platform
                $this.mount = $json.mounts
                $this.Path = Join-Path -path $dockpath -childpath "containers$($this.ID)"
                $this.Size = $this.GetContainerSize()
            }
        } #close class

    } #begin
    Process {
        if ($all) {
            Write-Verbose "[PROCESS] Getting all containers"
            $names = docker container ls -a --no-trunc --format "{{json .Names}}"
        }
        elseif ($Name) {
            Write-Verbose "[PROCESS] Getting container $name"
            $names = $Name
        }
        else {
            Write-Verbose "[PROCESS] Getting running containers"
            $names = docker container ls --no-trunc --format "{{json .Names}}"
        }

        if ($names) {
            foreach ($name in $names) {
                Write-Verbose "[PROCESS] Processing $name"
                if (docker container ls -qaf Name=$name) {
                    [myDockerContainer]::new($name)
                }
                else {
                    Write-Warning "Failed to find a container named $name"
                }
            } #foreach $Name
        } #if $name
        else {
            Write-Warning "No containers found"
        }
    } #process
    End {
        Write-Verbose "[END    ] Ending: $($MyInvocation.Mycommand)"
    } #end
} #close function

#import a format file if found
# https://gist.github.com/jdhitsolutions/74e52f89471720fb29b7fbaed279e183
$fmt = "C:\scripts\mydockercontainer.format.ps1xml"
if (Test-Path -path $fmt) {
    Update-FormatData $fmt
}


我更新了课程以包括尺寸。

[玩转系统] 扩展 PowerShell 和 Docker 容器

PowerShell 格式化

该函数包含使用 format.ps1xml 文件的代码,我也将其发布在 Github 上。

mydockercontainer.format.ps1xml:



  
    
      
      default
      
        Get-DockerContainer.myDockerContainer
      
      
        


[玩转系统] 扩展 PowerShell 和 Docker 容器

因为它位于 PowerShell 中,所以我可以将其导出、转储到数据库、创建 HTML 报告或您在 PowerShell 中能想到的任何其他内容。正如我所说,Docker CLI 很有用,但 PowerShell 没有用。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯