PowerShell ve Docker Konteynerlerini Genişletme


Docker kapsayıcıları hakkında bilgi almak için PowerShell komutumla uğraşmaya devam ediyorum. Docker CLI iyidir ancak çıktıyla çalışmak veya onunla çok şey yapmak çok zordur. Bu yüzden PowerShell boru hattında nesnelerin olmasını tercih ediyorum. Şu ana kadar görmezden geldiğim Docker konteyner öğelerinden biri konteyner boyutuydu. Kapların tüm güzelliği, tasarım gereği küçük olmalarıdır, öyleyse neden bu bilgiyi de almayasınız?

Konteynır boyutu

Konteyner boyutunu görüntülemek için Docker CLI'yi kullanabilirsiniz.

Anlayabildiğim kadarıyla bu, kaptaki yazılabilir katmanların boyutudur. Benim için bu her zaman 0 bayt gibi görünüyor. Yine de eninde sonunda gerçek değeri olan bir konteynerim olabilir, bu yüzden onu çıkarmak için bazı kodlara ihtiyacım var.

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

Geçen sefer tartıştığım JSON numarasını kullanarak, benim durumumda 0B olacak olan Size özelliğini çıkarabilirim. Bu dizenin yalnızca sayısal kısmını veya 0'ı elde etmek için normal bir ifade modeli kullanıyorum.

Docker Dosyalarını Alın

Her kapsayıcı ayrıca Docker program konumunda depolanan günlükler gibi bir dizi dosya içerir. Biraz PowerShell işlemi kullanarak o konumu Docker sistem bilgilerinden alabilirim.

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

Windows'ta bu C:\ProgramData\Docker olmalıdır. Her konteynerin kendi dizini vardır.

Klasör adı, nasıl alınacağını zaten bildiğim kapsayıcı kimliğidir. Buradan tüm dosyaların toplam boyutunu ölçmek basit bir meseledir.

$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 bana toplam 11977 değerini veriyor.

Docker Konteyner Birimlerini Dahil Et

Son olarak, bir konteynerin kalıcı depolama için ilişkili bir birimi olabilir.

$c = docker inspect cow1 | Convertfrom-json

Tekrar ediyorum, bunu ölçmek oldukça kolaydır.

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

Daha sonra kabın boyutuna oldukça yakın bir tahmin elde etmek için tüm değerleri bir araya getirebilirim.

Güncellenmiş PowerShell İşlevi

Bunu aklımda tutarak Get-DockerContainer fonksiyonunu güncelledim.

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
}

<#
sample usage
get-dockercontainer
get-dockercontainer | select *
get-dockercontainer -all | format-table -view stats
#>

Sınıfı boyutu içerecek şekilde güncelledim.

PowerShell Biçimlendirmesi

İşlev, Github'a da koyduğum format.ps1xml dosyasını kullanmak için kod içeriyor.

mydockercontainer.format.ps1xml:



  
    
      
      default
      
        Get-DockerContainer.myDockerContainer
      
      
        @"
$($_.ID)
   Image Tag   : $($_.image)
"@
        
      
      
        
          
            
            7
            left
          
          
            
            22
            left
          
          
            
            8
            left
          
          
            
            10
            left
          
          
            
            21
            left
          
          
            
            21
            left
          
          
            
            20
            left
          
        
        
          
            
              
                Name
               TableColumnIt
              
                Created
               TableColumnIt
              
                State
               TableColumnIt
              
                IsRunning
               TableColumnIt
              
                Started
               TableColumnIt
              
                Finished
               TableColumnIt
              
                Runtime
               TableColumnIt
            
          
        
      
    
    
      
      stats
      
        Get-DockerContainer.myDockerContainer
      
      
        
          
            
            7
            left
          
          
            
            10
            left
          
          
            
            23
            right
          
          
            
            23
            right
          
          
            
            19
            right
          
          
            
            9
            right
          
        
        
          
            
              
                Name
               TableColumnIt
              
                State
               TableColumnIt
              
                Created
               TableColumnIt
              
                (Get-Date) - $_.Created
               TableColumnIt
              
                Runtime
               TableColumnIt
              
                Size
               TableColumnIt
            
          
        
      
    
  

Varsayılan görünüm hala bir tablodur.

Ancak ayrıca istatistikler adında 2. bir tablo görünümü de ekledim.

Artık en azından Docker konteyner bilgilerini almak için çok kullanışlı PowerShell komutum var.

PowerShell'de olduğu için onu dışa aktarabilir, bir veritabanına aktarabilir, bir HTML raporu oluşturabilir veya PowerShell'de aklınıza gelebilecek herhangi bir şeyi oluşturabilirim. Söylediğim gibi Docker CLI faydalıdır ancak PowerShell kullanışlı değildir.

İlgili makaleler