# Docker auf Windows mit docker.exe und PowerShell Module for Docker
# Beispiele von Dr. Holger Schwichtenberg, www.IT-Visions.de

# Achtung: Bei Einsatz Docker in VM
# geschachtelte Virtualisierung
# auf HyperVHost: Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $false


# ################################ Beispiel-Image (Windows) von https://hub.docker.com/r/microsoft/dotnet/

# Ein Windows Image laden
Pull-ContainerImage -Repository microsoft/dotnet-samples -tag dotnetapp-nanoserver
docker pull microsoft/dotnet-samples:dotnetapp-nanoserver

Run-ContainerImage -ID microsoft/dotnet-samples -tag dotnetapp-nanoserver

# Liste der Container
Get-containerimage
docker images

# Liste der Container
get-Container 
docker ps -a 

# Start eines Containers auf Basis eines Image
Invoke-ContainerImage -id microsoft/dotnet-samples:dotnetapp-nanoserver -RemoveAutomatically
docker run --rm microsoft/dotnet-samples:dotnetapp-nanoserver 

# Start mehrerer Container
Get-ContainerImage | Where-Object RepoTags -like "*dotnetapp*" | Invoke-ContainerImage

# Container anhalten
Stop-Container -id Webserver12346

#Beenden aller Container
Get-container | Where-Object status -NotLike "*exited*" | Stop-Container 
docker stop $(docker ps -a -q)
#Entfernen aller Container (geht nur bei gestoppten Containern)
Get-container | Remove-Container
docker rm $(docker ps -a -q)

Get-container

#Entfernen aller Images (geht nur, wenn keine Container darauf basieren!)
Get-ContainerImage | Remove-ContainerImage
docker rmi $(docker images -q)

#Entfernen aller Container
Get-container | Remove-Container

#Invoke-ContainerImage -id microsoft/dotnet-samples:dotnetapp-nanoserver -Isolation:Process
#Invoke-ContainerImage : Docker API responded with status code=InternalServerError, response={"message":"Windows client operating systems only support Hyper-V containers"}

docker run -it --entrypoint=powershell microsoft/dotnet-samples:dotnetapp-nanoserver

docker inspect dockerwebdemo:dev


# ################################ Beispiel-Image (Linux)


# ========================== DEMO: Docker ASP.NET Core Start Image mit Webserver

Pull-ContainerImage -Repository microsoft/aspnetcore -tag 1.1.2-nanoserver

# Container für VS-Demo löschen
Get-container | Where-object { $_.RepoTags -NotLike "dockerwebdemo*" -and $_.status -NotLike "*exited*" } | Stop-Container 
Get-container | Where-object { $_.RepoTags -NotLike "dockerwebdemo*" } | Remove-Container 

# Start eines Container mit Port-Mapping
$image = "dockerwebdemo:latest"
$port = 12340
$containername = "Webserver$port"
Get-container | out-null # sicherstellen, dass Docker.DotNet.dll geladen!
$pb = new-object Docker.DotNet.Models.PortBinding
$pb.HostPort = $port
$hostConfig = new-object Docker.DotNet.Models.HostConfig
$hostConfig.PortBindings = [System.Collections.Generic.Dictionary[string, System.Collections.Generic.iList[Docker.DotNet.Models.PortBinding]]]::new()
$hostConfig.PortBindings.Add("80/tcp",[System.Collections.Generic.List[Docker.DotNet.Models.PortBinding]]::new([Docker.DotNet.Models.PortBinding[]]@($pb)))
# ohne Angaben
"Starte neuen Container $containername auf Basis von Image $image, Webserver erreichbar unter http://localhost:$port..."
# Run-ContainerImage -id dockerwebdemo:latest -Name "Webserver"
# return
# Interaktiv
#$c = Run-ContainerImage -id dockerwebdemo:latest -HostConfiguration $hostConfig -Terminal -Name "Webserver12344"
# Hintergrund
#$c = Run-ContainerImage -id dockerwebdemo:latest -HostConfiguration $hostConfig -Detach -Name $containername
"Anlegen eines neuen Containers $containername auf Basis von Image $image, Webserver erreichbar unter http://localhost:$port..."
$c = New-Container dockerwebdemo:latest -HostConfiguration $hostConfig -Name $containername
"Start des Containers $containername..."
$c | Start-Container
# Kontrollausgabe
(Get-ContainerDetail $c).HostConfig.PortBindings

# Interaktiv
docker run -it -p 12345:80 dockerwebdemo:latest
# Hintergrund
docker run --detach -p 12345:80 --name Webserver12346 dockerwebdemo:latest

# Container erstellen, ohne ihn zustarten
docker container create --name Webserver12347 -p 12347:80 dockerwebdemo:latest 


# ========================================== Skripte für World Wide Wings-Docker-Demo


Pull-ContainerImage -Repository microsoft/aspnet -tag latest
Get-ContainerImage
Get-Container

# Image starten
Run-ContainerImage -id wwwings.web:latest -Name "Webserver" -Detach
docker run --name Webserver2 --detach  wwwings.web:latest 
docker run --isolation=process wwwings.web:latest 

# IPConfig im Container starten
Start-ContainerProcess -id Webserver -Command @("ipconfig", "/all")
docker exec Webserver ipconfig /all

# PowerShell im Container starten
Start-ContainerProcess -id Webserver -Command powershell.exe -Terminal
Enter-PSSession -ContainerId (Get-Container Webserver).ID
docker exec -it Webserver powershell.exe

# Geänderter Entry-Point
Run-ContainerImage -id wwwings.web:latest -Name "Webserver" -Detach -Command powershell
docker run -it --entrypoint=powershell Webserver

# PowerShell.exe starten dirket beim Start
# Eigentlich
Run-ContainerImage -ID wwwings.web:latest -Terminal -Name Webserver -Command powershell.exe
docker run --name Webserver -it wwwings.web:latest powershell.exe

# Geht aber wegen EntryPoint nur so:

$config = [Docker.DotNet.Models.Config]::new()
$ep = [System.Collections.Generic.list[string]]::new()
$ep.Add("powershell.exe")
$config.Entrypoint = $ep
$config.Entrypoint
Run-ContainerImage -id wwwings.web:latest -Configuration $config -Terminal -Name "Webserver10"

docker run -it --entrypoint=powershell wwwings.web:latest

#IP-Adresse ermitteln
docker  inspect --format="{{.NetworkSettings.Networks.nat.IPAddress}}" Webserver


# Ressourcen begrenzen
$hostConfig = [Docker.DotNet.Models.HostConfig]::new()
$hostconfig.CPUPercent = 50
$hostconfig.Memory = 500MB
Run-ContainerImage -id wwwings.web:latest -Detach -HostConfiguration $hostConfig -Name "Webserver8"
docker run  --name Webserver9 -m 500M --cpu-quota 50000 --detach wwwings.web:latest

#Kontrolle:
docker inspect --format="{{.HostConfig.Memory}}" Webserver8
docker inspect --format="{{.HostConfig.Memory}}" Webserver9

#Dateien kopieren
Copy-ContainerFile -path c:\web\index.htm -Destination c:\app\ -id Webserver -ToContainer
docker cp c:\web\index.htm Webserver:c:\inetpub\wwwroot\index.htm


Copy-ContainerFile 

# Start mit Port-Mapping
docker run -detach -p 12345:80 --name Webserver3 wwwings.web:latest

# TODO: Start mit fester IP ---> geht nicht ganz --> kriegt immer dynamische IP :-(
docker network create -d transparent  --subnet 192.168.1.0/24 --gateway 192.168.1.253 LANFixedIP
get-containernet
docker network ls
docker run -d --network LANFixedIP --name Webserver --ip 192.168.1.188 wwwings.web:latest   

#Start mit DCHP-IP
docker network create -d transparent Brücke
get-containernet
docker network ls 
$hostConfig = [Docker.DotNet.Models.HostConfig]::new()
$hostConfig.NetworkMode = "Brücke"
Run-ContainerImage -Id wwwings.web:latest -Detach -HostConfiguration $hostConfig -Name Webserver
docker run -detach --network Brücke --name Webserver wwwings.web:latest 

# Neuer Container ohne zu starten
New-Container wwwings.web:latest -HostConfiguration $hostConfig -Name Webserver
docker container create --name Webserver2 --network Brücke wwwings.web:latest
Start-Container -id Webserver
docker start Webserver
Stop-Container -id Webserver 
docker stop 

# ------------------ Verbreiten

# Verbreiten eines Image via tar-Datei
Save-ContainerImage -Id wwwings.web:latest -DestinationFilePath t:\image.tar
docker save wwwings.web:latest > w:\image.tar
Load-ContainerImage \\192.168.1.60\w$\image.tar 

#Docker hub


Tag-ContainerImage -Id wwwings.web:latest -Tag v1.0 -Repository itvisions/wwwings.web
Tag-ContainerImage -Id wwwings.web:latest -Tag latest -Repository itvisions/wwwings.web
docker tag wwwings.web:latest itvisions/wwwings.web:v1.0 
docker tag wwwings.web:latest itvisions/wwwings.web:latest 


$DockerAuth = [Docker.DotNet.Models.AuthConfig]::new()
$DockerAuth.Username = 'itvisions'
$DockerAuth.Password = 'Paris123'
Push-ContainerImage -Id itvisions/wwwings.web:v1.0 -Authorization $DockerAuth

docker login -u ihrname -p geheim
docker push itvisions/wwwings.web:v1.0 

Pull-ContainerImage itvisions/wwwings.web:v1.0

# ------------------ Aufräumen

#Alle laufenden Container anhalten
Get-Container | Where-Object status -Like "Up*" | Stop-Container 
#Alle Container löschen
Get-Container | Remove-Container 

# Auch alle Images wird man schnell los, wobei man nur Images löschen kann, für die es keinen Container mehr gibt und die auch nicht Basis für andere Images sind:
Get-ContainerImage | Remove-ContainerImage 
#Get-ContainerImage microsoft/aspnet:latest | Remove-ContainerImage
Get-Containerimage | Where RepoTags -like "dockerweb*" | Remove-ContainerImage

# Lösche alle Container eines Images
Get-container | Where-object { $_.Image -eq "wwwings.web:latest" -and $_.status -Like "Up*" } | Stop-Container  
Get-container | Where-object { $_.Image -eq "wwwings.web:latest" }  | Remove-Container 
Get-container

# Image aus Container erstellen
stop-container Webserver
Get-Container Webserver | ConvertTo-ContainerImage -Repository meinwebserverimage
Get-Container Webserver | ConvertTo-ContainerImage -Repository meinwebserverimage -Tag v1.0 
docker commit Webserver meinwebserverimage:v1.0
Get-ContainerImage



# ???????????????????????? MISC

# Start eines Befehls in einem laufenden Container

docker exec -i -t MeinWebserver1 powershell  

Exec-Container -id 073698cec4ee4873384f72fc6193fc195fea7c05797d5f03d05caeaf8f72ca0c -Command powershell.exe -Terminal 
docker exec -i -t 073698cec4ee4873384f72fc6193fc195fea7c05797d5f03d05caeaf8f72ca0c powershell.exe  


docker network create -d L2Bridge  --subnet 192.168.1.0/24 --gateway 192.168.1.253 LANFixedIP3

docker exec -i -t Web1 ipconfig
#docker network create -d L2Bridge --subnet 192.168.1.0/24 --gateway 192.168.1.253 LANFixedIP # Problem: Plug-In not found: 

docker run -it -p 55555:80 --name Web3 wwwings.web:latest 

docker run -it  wwwings.web:latest

Save-ContainerImage microsoft/dotnet-samples -DestinationFilePath w:\image3.tar