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.