I remember that one of the first reasons I started using Windows PowerShell is that it uses objects to represent the data, which is great when you are interacting with a object-oriented Windows ecosystem. Now that some historical borders have been crossed between Linux and Windows, and that preexisting tools have been translated to the Microsoft's OS, we, as PowerShell guys, could face a bit of a throwback in the way we use the shell.
Just have a look at Docker.
Invented in 2013 by a French guy named Solomon Hykes, this open source project aimed at automating the deployment of Linux containers has been quickly adopted by Microsoft for their last operating system and can today be run on both Windows 10 and Windows 2016.
The main drawback of adopting such a tool, is that it comes with a command line which is obsolete if you look at it in PowerShell terms: it only produces strings, which are hardly reusable, unless you feed them to ConvertFrom-String:
docker images | ConvertFrom-String -Delimiter "\s{2,}" | Format-Table P1 P2 P3 P4 P5 -- -- -- -- -- REPOSITORY TAG IMAGE ID CREATED SIZE microsoft/iis latest 211fecef1e6b 5 days ago 9.48 GB microsoft/sample-dotnet latest c14528829a37 2 weeks ago 911 MB microsoft/windowsservercore latest 93a9c37b36d0 7 weeks ago 8.68 GB microsoft/nanoserver latest e14bc0ecea12 7 weeks ago 810 MB
Now, tough ConvertFrom-String is a extremely powerful cmdlet released with PowerShell 5.0 (check my blog post on the subject), it take some time to feel easy with its syntax. In the previous example for instance I am outputting the list of the images I have pulled from the Docker Hub onto my system. The text that comes through the pipeline once I run 'docker images' has to be split whenever I find at least 2 empty spaces. To achieve that I have to use the Delimiter parameter and match a whitespace \s at least two times {2,}.
Needless to say, knowing regular expressions becomes a must.
Happily enough we have an alternative to this. Since Docker comes with a nice API, there is open source project for a module exposing PowerShell cmdlets to manage Docker images, containers and networks. Tough still in development, I heartedly suggest you start using it to maintain consistency with your existing environment.
You can find it here:
The installation is straightforward.
Register-PSRepository -Name DockerPS-Dev -SourceLocation https://ci.appveyor.com/nuget/docker-powershell-dev Install-Module Docker -Repository DockerPS-Dev -Scope CurrentUser
Here's the list of cmdlets that come with it:
Get-Command -Module Docker -CommandType Cmdlet CommandType Name Version Source ----------- ---- ------- ------ Cmdlet Add-ContainerImageTag 0.1.0.111 Docker Cmdlet ConvertTo-ContainerImage 0.1.0.111 Docker Cmdlet Copy-ContainerFile 0.1.0.111 Docker Cmdlet Enter-ContainerSession 0.1.0.111 Docker Cmdlet Export-ContainerImage 0.1.0.111 Docker Cmdlet Get-Container 0.1.0.111 Docker Cmdlet Get-ContainerDetail 0.1.0.111 Docker Cmdlet Get-ContainerImage 0.1.0.111 Docker Cmdlet Get-ContainerNet 0.1.0.111 Docker Cmdlet Get-ContainerNetDetail 0.1.0.111 Docker Cmdlet Import-ContainerImage 0.1.0.111 Docker Cmdlet Invoke-ContainerImage 0.1.0.111 Docker Cmdlet New-Container 0.1.0.111 Docker Cmdlet New-ContainerImage 0.1.0.111 Docker Cmdlet New-ContainerNet 0.1.0.111 Docker Cmdlet Remove-Container 0.1.0.111 Docker Cmdlet Remove-ContainerImage 0.1.0.111 Docker Cmdlet Remove-ContainerNet 0.1.0.111 Docker Cmdlet Request-ContainerImage 0.1.0.111 Docker Cmdlet Start-Container 0.1.0.111 Docker Cmdlet Start-ContainerProcess 0.1.0.111 Docker Cmdlet Stop-Container 0.1.0.111 Docker Cmdlet Submit-ContainerImage 0.1.0.111 Docker Cmdlet Wait-Container 0.1.0.111 DockerThis module also exposes a bunch of aliases, though I don't recommend their use since they seem confusing to me and don't add anything in terms of command line agility:
Get-Command -Module Docker -CommandType Alias | Format-Table Name,ResolvedCommandName Name ResolvedCommandName ---- ------------------- Attach-Container Enter-ContainerSession Build-ContainerImage New-ContainerImage Commit-Container ConvertTo-ContainerImage Exec-Container Start-ContainerProcess Load-ContainerImage Import-ContainerImage Pull-ContainerImage Request-ContainerImage Push-ContainerImage Submit-ContainerImage Run-ContainerImage Invoke-ContainerImage Save-ContainerImage Export-ContainerImage Tag-ContainerImage Add-ContainerImageTag
So, docker images becomes:
Get-ContainerImage RepoTags ID Created Size(MB) -------- -- ------- -------- microsoft/sample-dotnet:latest sha256:c14528829a... 25/10/2016 13:55:28 869,05 microsoft/windowsservercore:latest sha256:93a9c37b36... 22/09/2016 10:51:07 8 273,19 microsoft/nanoserver:latest sha256:e14bc0ecea... 22/09/2016 09:39:30 772,81
and the returned object is a heavily reusable ImagesListResponse object:
Get-ContainerImage | Get-Member TypeName: Docker.DotNet.Models.ImagesListResponse Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() Created Property datetime Created {get;set;} ID Property string ID {get;set;} Labels Property System.Collections.Generic.IDictionary[string,string] Labels... ParentID Property string ParentID {get;set;} RepoDigests Property System.Collections.Generic.IList[string] RepoDigests {get;set;} RepoTags Property System.Collections.Generic.IList[string] RepoTags {get;set;} Size Property long Size {get;set;} VirtualSize Property long VirtualSize {get;set;}
Same model for the list of existing containers:
Get-Container ID Image Command Created Status -- ----- ------- ------- ------ 43a05b618697033eb... microsoft/na... c:\windows\system... 14/11/2016 09:44:19 Exited... 005b51dbe002324f8... microsoft/na... --name nanoserver1 14/11/2016 09:44:04 Created e8b31c61d5f42b271... microsoft/na... --name nanoserver1 14/11/2016 09:42:12 Created 547b7dbd3b1473127... microsoft/sa... dotnet dotnetbot.dll 06/11/2016 16:11:07 Exited...
Get-Container | Get-Member TypeName: Docker.DotNet.Models.ContainerListResponse Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() Command Property string Command {get;set;} Created Property datetime Created {get;set;} ID Property string ID {get;set;} Image Property string Image {get;set;} ImageID Property string ImageID {get;set;} Labels Property System.Collections.Generic.IDictionary[string,string] Labels... Mounts Property System.Collections.Generic.IList[Docker.DotNet.Models.MountP... Names Property System.Collections.Generic.IList[string] Names {get;set;} NetworkSettings Property Docker.DotNet.Models.SummaryNetworkSettings NetworkSettings... Ports Property System.Collections.Generic.IList[Docker.DotNet.Models.Port]... SizeRootFs Property long SizeRootFs {get;set;} SizeRw Property long SizeRw {get;set;} State Property string State {get;set;} Status Property string Status {get;set;}
Now that you have this module, you have two ways to run a container. Either by using:
docker run -it microsoft\nanoserver powershell
or by using Invoke-ContainerImage (aliased as Run-ContainerImage):
Invoke-ContainerImage -ImageIdOrName microsoft/nanoserver:latest -Command powershell -Input -Terminal
which, at its best, can be shortened to:
Run-ContainerImage microsoft/nanoserver:latest powershell -In -T
None of the PowerShell syntaxes are as short as the 'legacy' one, but again, the produced object is what makes them worthy using.
I hope you have enjoyed this first post on the PowerShell module for the Docker Engine, which brings close integration between those that not so long ago were distant worlds. Stay tuned for more.
No comments:
Post a Comment