Created
December 11, 2019 14:18
-
-
Save michaelsanford/7ad32a3ddea2a6156967842d3b3f8574 to your computer and use it in GitHub Desktop.
PowerShell script to execute Docker maintenance, optionally non-interactively
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.Synopsis | |
Runs periodic maintenance on Docker for Windows. | |
It must be run as an Administrator! | |
.Description | |
Intended to be run interactively or as a periodoc service, this will execute configurable docker prune | |
within the VM and then stop and compact the virtual machine hard disk before restarting Docker. | |
When run as a service, logs are sent to the Windows Event Log. Otherwise, progress is logged to the console. | |
.Parameter VHDX | |
Required. The complete path to your DockerDesktop virtual hard disk file, i.e., 'F:\Docker\DockerDesktop.vhdx' | |
.Parameter FullSystem | |
Optional. By default docker will prune unused images with 'docker image prune'. | |
Add this flag to execute 'docker system prune -f'. | |
.Parameter Pull | |
Optional (but recommended). Pull rebuilt base images from the internal HQ-DOCKER registry. | |
.Example | |
periodic-maintenance.ps1 -VHDX "F:\Docker\DockerDesktop.vhdx" -FullSystem -Pull | |
# Interactively run a full system prune, pull the latest internal base images, compact the VHDX. | |
.Example | |
periodic-maintenance.ps1 -VHDX "F:\Docker\DockerDesktop.vhdx" | |
# Run a minimal image prune and compact the VHDX. | |
#> | |
#Requires -RunAsAdministrator | |
#Requires -Modules Hyper-V | |
param( | |
[Switch]$FullSystem, | |
[Switch]$Pull, | |
[String]$VHDX | |
) | |
if ([System.Diagnostics.EventLog]::SourceExists("DockerMaintenance") -eq $False) { | |
New-EventLog -LogName Application -Source DockerMaintenance | |
} | |
function Write-ErrorLog($Message) { | |
if (!$MyInvocation.scriptname) { | |
Write-EventLog -LogName Application ` | |
-Source DockerMaintenance ` | |
-EventID 3001 ` | |
-Category 1 ` | |
-EntryType Error ` | |
-Message $Message | |
} else { | |
Write-Host -ForegroundColor Red $Message | |
} | |
} | |
function Write-InfoLog($Message) { | |
if (!$MyInvocation.scriptname) { | |
Write-EventLog -LogName Application ` | |
-Source DockerMaintenance ` | |
-EventID 3001 ` | |
-Category 1 ` | |
-EntryType Information ` | |
-Message $Message | |
} else { | |
Write-Host $Message | |
} | |
} | |
if ($null -eq $VHDX) { | |
$err = "The -VHDX parameter is missing! Please add it." | |
Write-ErrorLog $err | |
Exit -1 | |
} elseif ((![System.IO.File]::Exists("${VHDX}")) -or ($VHDX -notlike "*\DockerDesktop.vhdx")){ | |
$err = "The path provided for -VHDX ""${VHDX}"" does not point to a 'DockerDesktop.vhdx'!" | |
Write-ErrorLog $err | |
Exit -2 | |
} | |
function Invoke-Toast($Message, $Cancel) { | |
$AppId = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe' | |
$XmlString = @" | |
<toast> | |
<visual> | |
<binding template="ToastGeneric"> | |
<text hint-maxLines="1">Docker Maintenance</text> | |
<text>$Message</text> | |
</binding> | |
</visual> | |
<audio src="ms-winsoundevent:Notification.Default" /> | |
</toast> | |
"@ | |
$ToastXml = [Windows.Data.Xml.Dom.XmlDocument]::new() | |
$ToastXml.LoadXml($XmlString) | |
$Toast = [Windows.UI.Notifications.ToastNotification]::new($ToastXml) | |
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($AppId).Show($Toast) | |
} | |
function Invoke-ImagePrune() { | |
Write-InfoLog "Pruning unused and dangling images" | |
docker image prune -f | |
} | |
function Invoke-SystemPrune() { | |
Write-InfoLog "Fully pruning docker system" | |
docker system prune -f | |
} | |
function Invoke-DockerPull() { | |
Write-InfoLog "Pulling HQ docker images" | |
docker images --format "{{.Repository}}:{{.Tag}}" | Where-Object { $_ -like "hq-docker-*" } | ForEach-Object { docker pull $_ } | |
} | |
function Invoke-CompactDocker() { | |
Write-InfoLog "Compacting ${VHDX}" | |
Mount-VHD $VHDX -ReadOnly | |
Optimize-VHD $VHDX -Mode Full | |
Dismount-VHD $VHDX | |
} | |
function Stop-Docker() { | |
$docker = Get-VM | Where-Object { $_.Name -eq 'DockerDesktopVM' } | |
if ($docker.State -ne "Off") { | |
Write-InfoLog "Docker is still running. Stopping..." | |
Get-VM | Where-Object { $_.Name -eq 'DockerDesktopVM' } | Stop-VM | |
Get-Process -Name "*Docker*" | Stop-Process -Force | |
} | |
} | |
function Start-Docker() { | |
Write-InfoLog "Restarting docker" | |
Net Start "com.docker.service" | |
& "C:\Program Files\Docker\Docker\Docker Desktop.exe" | |
if ($MyInvocation.scriptname) { | |
Write-Host "Docker for Windows is now starting up. Watch for the usual Toast notification." | |
} | |
} | |
if ($MyInvocation.scriptname) { | |
Invoke-Toast "Your Docker for Windows will be temporarily shut down for maintenance in 5 MINUTES. ` | |
This process should take about 3 minutes." | |
Start-Sleep -Seconds (60*5) | |
} else { | |
Write-Host -ForegroundColor Green "Beginning maintenance in 5 seconds. Abort with [CTRL-C]." | |
Start-Sleep -Seconds 5 | |
} | |
if ($True -eq $Pull) { | |
Invoke-DockerPull | |
} | |
if ($True -eq $FullSystem) { | |
Invoke-SystemPrune | |
} else { | |
Invoke-ImagePrune | |
} | |
Stop-Docker | |
Invoke-CompactDocker | |
Write-InfoLog "Maintenance Complete, restarting Docker..." | |
Start-Docker |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is also (currently) awaiting review on Code Review.SE, please feel free to contribute comments there https://codereview.stackexchange.com/questions/233370/powershell-script-to-execute-docker-maintenance-optionally-non-interactively