Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

More Fun with Docker Containers and PowerShell

Posted on March 29, 2019March 29, 2019

A few days ago I shared some experiences of working with Docker containers and PowerShell. As I continue to learn Docker, I am also learning how to manage it with PowerShell. The Docker command line tools are fine but I think they are even better when drizzled with a nice PowerShell glaze. Here's a bit more of what I have been working on.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

Container ID

In my previous work, I needed the full container ID so I could use it with the PowerShell PSSession cmdlets. Thanks to people like Tim Pringle, who provided tips on better using the Docker CLI, specifically the filter option.

docker container ls -f Name=srv4

The -f could also be written as --filter.

filtering docker containers

Be careful. Container names are case-sensitive.

With this, I can combine it with a few other parameters to get the full configuration ID.

docker container ls --no-trunc -qf Name=srv4

getting a single id

Formatting Containers

It gets better. After a bit of research and experimentation, I figured out how to take advantage of the --format parameter in the Docker CLI.  This is meant to show you what formatting options are available to you using the JSON format.

docker container ls --no-trunc --format "{{json .}}"

Docker container as json

You can format using any heading preceded by a colon. In other words, you can tell Docker what properties to return from the JSON output.

docker container ls -a --no-trunc --format "{{json .Names}},{{json .ID}},{{json .Image}},{{json .Networks}},{{json .Mounts}},{{json .CreatedAt}}"

Selected properties

Hey! That is a CSV output. I can use PowerShell to turn that into objects.

docker container ls -a --no-trunc --format "{{json .Names}},{{json .ID}},{{json .Image}},{{json .Networks}},{{json .Mounts}},{{json .CreatedAt}}" |
ConvertFrom-CSV -Header "Name","ID","Image","Network","Mounts","Created"

Docker containers to PowerShell objects

That is very useful, so why not take everything? I know Docker will provide JSON output which means I can convert it and then tweak a few properties to be the of the proper type.

docker container ls -a --no-trunc --format "{{json .}}" | convertfrom-json |
Select-Object ID,@{Name="Name";Expression = {$_.names}},Image,
@{Name="Created";Expression = {($_.createdat -split "\s[-+]\d{4}.*")[0] -as [datetime]}},
Networks,Mounts

Docker PowerShell container objects

In case you're wondering I'm using a regular expression pattern to parse the CreatedAt value to that I can convert it to a proper DateTime object.

Digging Deeper

You know me. I always want to discover how far I can go. The Docker CLI has an option to inspect a container. This allows you to get all the information about a given container. The default output is a JSON document. This means I can get all container names and then inspect each one, converting the JSON output to objects in PowerShell.

$c = docker container ls -a --no-trunc --format "{{json .Names}}" | 
foreach-object { docker container inspect $_ | ConvertFrom-Json }

I get output like this:

Sample json output

With a bit of scripting, I can turn this into something a bit more manageable.

foreach ($item in $c) {
    $item | Select-object Id,
    @{Name="Name";Expression = {$_.Name.substring(1)}},
    @{Name="State";Expression = {$_.state.status}},
    @{Name="IsRunning";Expression = {$_.state.Running}},
    @{Name="Started";Expression = {$_.state.startedat -as [datetime]}},
    @{Name="Finished";Expression = {
       #this value shows the last time it finished which won't be accurate if
       #the container is running
       if ($_.state.running) {
          $null
       }
       else {
     $_.state.finishedat -as [datetime]
     }
     }},
    @{Name="Runtime";Expression = { 
    if ($_.state.running) { 
     (Get-Date) - ($_.state.startedat -as [datetime])
    } 
    else {
        ($_.state.finishedat -as [datetime]) - ($_.state.startedat -as [datetime])
    }
    }},
    Platform,Mounts,
    @{Name="Image";Expression = { (docker image inspect ($_.image -split ":")[1] --format "{{json .RepoTags}}") -replace '\[|\]|"',"" }},
    @{Name="Created";Expression ={$_.Created -as [datetime]}}
}

I can even add my own properties.

my custom container object

Toolmaking Time

Obviously, nobody wants to type that all the time. So I turned the code into a proper PowerShell function.

The function is using a nested PowerShell class to define my custom object.

Getting my custom container objects in PowerShell

I'm glad I have all of this information available, but part of PowerShell toolmaking is to take how it will be used into account. I wanted a different default view of the objects. This meant I needed a custom format ps1xml file. Fortunately, that is is easy now using the New-PSFormatXML command in my PSScriptTools module.

Get-DockerContainer | Select -first 1 | New-PSFormatXML -Properties ID,Name,Image,State,IsRunning,Created,Started,Finished,Runtime -Path c:\scripts\mydockercontainer.format.ps1xml

I edited the file to get the desired output.

<?xml version="1.0" encoding="UTF-8"?>
<!--
format type data generated 03/27/2019 17:01:10
by BOVINE320\Jeff
-->
<Configuration>
  <ViewDefinitions>
    <View>
      <!--Created 03/27/2019 17:01:10 by BOVINE320\Jeff-->
      <Name>default</Name>
      <ViewSelectedBy>
        <TypeName>Get-DockerContainer.myDockerContainer</TypeName>
      </ViewSelectedBy>
            <GroupBy>
               <ScriptBlock>@"
$($_.ID)
   Image Tag   : $($_.image)
"@</ScriptBlock>
               <Label>Container ID</Label>
       </GroupBy>
      <TableControl>
        <TableHeaders>
          <TableColumnHeader>
            <Label>Name</Label>
            <Width>7</Width>
            <Alignment>left</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>Created</Label>
            <Width>22</Width>
            <Alignment>left</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>State</Label>
            <Width>8</Width>
            <Alignment>left</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>IsRunning</Label>
            <Width>10</Width>
            <Alignment>left</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>Started</Label>
            <Width>21</Width>
            <Alignment>left</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>Finished</Label>
            <Width>21</Width>
            <Alignment>left</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>Runtime</Label>
            <Width>20</Width>
            <Alignment>left</Alignment>
          </TableColumnHeader>
        </TableHeaders>
        <TableRowEntries>
          <TableRowEntry>
            <TableColumnItems>
               <TableColumnItem>
                <PropertyName>Name</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>Created</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>State</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>IsRunning</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>Started</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>Finished</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>Runtime</PropertyName>
              </TableColumnItem>
            </TableColumnItems>
          </TableRowEntry>
        </TableRowEntries>
      </TableControl>
    </View>
  </ViewDefinitions>
</Configuration>

Before it can be used, it needs to be imported into the PowerShell session.

Update-FormatData C:\scripts\mydockercontainer.format.ps1xml

Now I get a formatted output that is easier to digest.

Formatted Docker containers objects in PowerShell

The other properties are still available if I need them.

Selecting custom PowerShell Docker container properties

I can already think of more that I want to do with this. Hopefully, you have some ideas as well. And now that I know how to get data from Docker using JSON, there is much, much more that I can do.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

1 thought on “More Fun with Docker Containers and PowerShell”

  1. Irwin Strachan says:
    March 30, 2019 at 11:38 am

    The possibilities… just replace docker cli with az cli 🙂 Never would have thought to put a class in begin {}. Thanks!

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d