TM-DockerUtility.psm1
# Write verbose messages on import if ((Get-PSCallStack)[1].Arguments -imatch 'Verbose=True') { $PSDefaultParameterValues['*:Verbose'] = $true } # Ensure we're using the primary write commands from the Microsoft.PowerShell.Utility module. Set-Alias -Name 'Write-Progress' -Value 'Microsoft.PowerShell.Utility\Write-Progress' -Scope Script Set-Alias -Name 'Write-Debug' -Value 'Microsoft.PowerShell.Utility\Write-Debug' -Scope Script Set-Alias -Name 'Write-Verbose' -Value 'Microsoft.PowerShell.Utility\Write-Verbose' -Scope Script Set-Alias -Name 'Write-Host' -Value 'Microsoft.PowerShell.Utility\Write-Host' -Scope Script Set-Alias -Name 'Write-Information' -Value 'Microsoft.PowerShell.Utility\Write-Information' -Scope Script Set-Alias -Name 'Write-Warning' -Value 'Microsoft.PowerShell.Utility\Write-Warning' -Scope Script Set-Alias -Name 'Write-Error' -Value 'Microsoft.PowerShell.Utility\Write-Error' -Scope Script if ((Test-ApplicationExistsInPath -ApplicationName 'docker') -eq $false) { Write-Verbose 'docker does not exist in the Path. Skipping the import of docker ProfileUtility commands.' # Do not export any module commands. Export-ModuleMember exit } # https://github.com/PowerShell/PowerShell/issues/17730#issuecomment-1190678484 $ExportedMembers = [List[string]]::new() class MountPoint { <# .SYNOPSIS Holds the HostPath and ContainerPath for use connecting to a given docker image. #> [string]$HostPath [string]$ContainerPath MountPoint( [string]$hostPath = (Read-Host -Prompt 'Enter the local mount path'), [string]$containerPath = (Read-Host -Prompt 'Enter the containers mount path') ) { $this.HostPath = $hostPath $this.ContainerPath = $containerPath } MountPoint() { $this.HostPath = Read-Host -Prompt 'Enter the local mount path' $this.ContainerPath = Read-Host -Prompt 'Enter the containers mount path' } [string]ToString() { return "-v ""$($this.HostPath)`:$($this.ContainerPath)"" " } } function New-MountPoint { <# .SYNOPSIS Create a new MountPoint object. .DESCRIPTION This function allows the user to create a new MountPoint object from the TM-DockerUtility module. MountPoint objects should be used with the Enter-DockerImageWithNewEntryPoint function's MountPoints parameter. .PARAMETER HostPath The path to a directory that exists on the local machine. .PARAMETER ContainerPath The path to create and mount the HostPath to inside the container. .EXAMPLE Enter-DockerImageWithNewEntryPoint -EntryPoint '/bin/bash' -DeleteDebugImage -MountPoints @( (New-MountPoint -HostPath 'C:\Path\To\Folder1' -ContainerPath '/workspace/Folder1'), (New-MountPoint -HostPath 'C:\Path\To\Folder2' -ContainerPath '/workspace/Folder2') ) #> [CmdletBinding()] param ( [Parameter(Mandatory)] [Validation.ValidatePathExists('Folder')] [string]$HostPath, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$ContainerPath ) return [MountPoint]::New($HostPath, $ContainerPath) } $ExportedMembers.Add('New-MountPoint') function Enter-DockerImageWithNewEntryPoint { <# .SYNOPSIS Enters a Docker container image with a new entry point. .DESCRIPTION This function allows you to enter a selected Docker container with a specified entry point. This can be useful if your containers default entrypoint is causing errors and the container will not stay running long enough for you to exec into it and debug the issue. .PARAMETER EntryPoint The entry point command to use with the debug image. If no EntryPoint is provided then the user will be prompt to enter an EntryPoint instead. .PARAMETER DeleteDebugImage A boolean value that indicates whether to delete the debug image after exiting the container. The default value is $true. .PARAMETER MountPoints An array of mount points to add to the Docker container. Use the New-MountPoint function to create new mountpoint objects. .EXAMPLE Enter-DockerImageWithNewEntryPoint -EntryPoint '/bin/bash' -DeleteDebugImage -MountPoints @( (New-MountPoint -HostPath 'C:\Path\To\Folder1' -ContainerPath '/workspace/Folder1'), (New-MountPoint -HostPath 'C:\Path\To\Folder2' -ContainerPath '/workspace/Folder2') ) #> [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [string]$EntryPoint = ( Read-Host -Prompt "Provide the entrypoint command to use with '$DebugName'.`nexample: /bin/bash "), [Parameter(Mandatory = $false)] [bool]$DeleteDebugImage = $true, [Parameter(Mandatory = $false)] [MountPoint[]]$MountPoints ) if (($env:OS -eq 'Windows_NT') -and ($null -eq (Get-Process -Name 'Docker Desktop' -ErrorAction Ignore))) { Write-Warning -Message 'Start Docker Desktop before trying to enter a docker image' return } $DockerPSOut = docker ps -a --format '{{json .}}' | ConvertFrom-Json -ErrorAction Ignore # Exit early if there are no containers to copy and enter. if ($null -eq $DockerPSOut) { Write-Warning 'Docker did not return any output from the ''docker ps -a'' command.' return } Write-Host 'Select a container to enter:' $Count = 0 $Container = $DockerPSOut | ForEach-Object { Select-Object -InputObject $_ -Property @{n = '#'; e = { $Count } }, ID, Names, Status, Image $Count++ } | Out-GridView -Title 'Available Containers' -OutputMode Single # Make a copy of the selected container image $ContainerImage = $Container.Image.Split('/')[-1] $DebugName = "debug/$ContainerImage" docker commit $Container.ID $DebugName | Write-Host # Create start process arguments: $dockerMount = '' foreach ($MountPoint in $MountPoints) { $dockerMount += $MountPoint.ToString() } $StartDockerRun = @{ FilePath = 'docker' PassThru = $true Wait = $true NoNewWindow = $true ArgumentList = @('run', '-it', $dockerMount, '--rm', '--entrypoint', $EntryPoint, $DebugName) } # Run the process in a try block in case something in the container sends a terminating error. try { $Process = Start-Process @StartDockerRun if ($Process.ExitCode -ne 0) { Write-Warning "Docker ExitCode is not 0. ExitCode: $($Process.ExitCode)" } } finally { # Cleanup, Don't forget to delete the debug image if requested. if ($DeleteDebugImage) { $DockerImagesOut = docker images -a --format '{{json .}}' | ConvertFrom-Json -ErrorAction Ignore $ImageName = "$DebugName".Split(':')[0] $ImageId = $DockerImagesOut | Where-Object { $_.Repository -eq $ImageName } | Select-Object -ExpandProperty ID docker.exe image rm $ImageId } } } $ExportedMembers.Add('Enter-DockerImageWithNewEntryPoint') function Remove-DockerResources { <# .SYNOPSIS Removes Docker resources, including unused containers, networks, images, and optionally volumes. .DESCRIPTION This function removes unused Docker resources such as containers, networks, images, and optionally volumes. It serves as a cleanup tool to reset the docker environment state back to the default install state. .PARAMETER IncludeVolumes A boolean value that indicates whether to include volumes in the Docker resource removal. The default value is $true. #> [Alias('Prune-DockerResources')] [CmdletBinding()] [OutputType([Void])] param ( [Parameter(Mandatory = $false)] [bool]$IncludeVolumes = $true ) [List[string]]$DockerArgs = [List[string]]::new() $DockerArgs.AddRange([string[]]@('system', 'prune', '--all', '--force')) if ($IncludeVolumes) { $DockerArgs.Add('--volumes') } docker @DockerArgs } $ExportedMembers.Add('Remove-DockerResources') Export-ModuleMember -Function $ExportedMembers.ToArray() |