Konfiguration des Docker-Desktops programmgesteuert festlegen

Konfiguration des Docker-Desktops programmgesteuert festlegen

Ich bin wieder da. Mal sehen, ob Sie mir helfen können ...

Normalerweise sind bei der Installation von Docker-Desktop von 0 einige Konfigurationsdateien wie folgt eingestellt:

C:\Benutzer\AppData\Roaming\Docker\setting.json

Fast immer sind manuelle Schritte notwendig: Anwendung öffnen, Umfrage durchführen, dann Änderungen an den Einstellungen vornehmen, speichern und anwenden, dann schließen… und erneut anmelden.

Ich verwende Docker-Desktop lieber vom Terminal aus. Normalerweise führe ich die Befehle aus, um das Netzwerk zu erstellen und die Container basierend aufdocker-compose

Das Problem oder vielmehr die Hilfe, die ich suche, ist, ob Sie mir beim programmgesteuerten Teil der Aktualisierung der Einstellungen und beim Schließen und erneuten Öffnen der Desktopanwendung helfen können: docker-desktop.

Ich habe versucht, etwas in C# zu tun, bevor ich hierher kam, aber es stellte sich als instabil heraus:

https://stackoverflow.com/questions/78048247/check-wait-for-the-invoked-application-to-be-open

Ich bin sicher, dass dies mit PowerShell erreicht werden könnte, aber ich weiß nicht viel darüber.

Zum Docker-Forum gehörende Beiträge:https://forums.docker.com/t/programmatic-manipulation-and-management-of-docker-desktop/140018

In Powershell habe ich Folgendes getan:

# Defines the configuration dictionary
$settingsToReplace = @{
    '"exposeDockerAPIOnTCP2375": false,' = '"exposeDockerAPIOnTCP2375": true,'
    '"updateHostsFile": false,' = '"updateHostsFile": true,'
    '"licenseTermsVersion": 0,' = '"licenseTermsVersion": 2,'
}

# Defines the path to the configuration file
$settingsPath = "$env:APPDATA\Docker\settings.json"

# Read the contents of the configuration file
$settingsContent = Get-Content $settingsPath -Raw

# Replaces the values in the file content
foreach ($key in $settingsToReplace.Keys) {
    $settingsContent = $settingsContent -replace [regex]::Escape($key), $settingsToReplace[$key]
}

# Write the modified content back to the file
$settingsContent | Set-Content $settingsPath

# Close Docker Desktop
Stop-Process -Name "Docker Desktop*" -ErrorAction SilentlyContinue

# Wait until Docker Desktop has completely closed
$timeout = 60  # seconds
$processName = "Docker Desktop"
$timeoutReached = $false
$startTime = Get-Date

# Wait until Docker Desktop has completely closed or the timeout has been reached
while ((Get-Process -Name $processName -ErrorAction SilentlyContinue) -and (-not $timeoutReached)) {
    # Verifica si el proceso de Docker Desktop se ha cerrado
    if (-not (Get-Process -Name $processName -ErrorAction SilentlyContinue)) {
        Write-Host "Docker Desktop has closed before the time limit was reached."
        break
    }

    # Check if the time limit has been reached
    if ((Get-Date) - $startTime -ge [TimeSpan]::FromSeconds($timeout)) {
        $timeoutReached = $true
    }

    # Wait 1 second before checking again
    Start-Sleep -Seconds 1
}

# Check if the timeout has been reached
if ($timeoutReached) {
    Write-Host "Docker Desktop did not close properly. Please manually close the application and run the script again."
} else {
    Write-Host "Docker Desktop has closed successfully. Continuing..."
}

# Open Docker Desktop

$docker = [System.Environment]::GetEnvironmentVariable('ProgramFiles') + '\Docker\Docker\Docker Desktop.exe'
Start-Process -FilePath $docker

# Wait until Docker Desktop has fully opened
$processName = "Docker Desktop"
while (-not (Get-Process -Name $processName -ErrorAction SilentlyContinue)) {
    Start-Sleep -Seconds 1
}

Write-Host "continue"

Aber ich stelle fest, dass Docker-Desktop wieder instabil wird … und die Einstellung zum Aktualisieren der Hosts-Datei wird auf setting.json angewendet, aber nicht auf Docker-Desktop geändert.

Aktualisieren:

Was sind die genauen Symptome einer „Instabilität“?

Antwort:Beim Öffnen von Docker-Desktop mithilfe des Skripts wird die Benutzeroberfläche von Docker-Desktop langsam so langsam, dass sie blockiert ist und nicht mehr auf Mausklicks reagiert.

Was und wie testen Sie, ob die Änderungen nach dem Neustart des Docker-Desktops übernommen wurden?

Antwort:Die Registerkarte „Einstellungen“ wird im Docker-Desktop geöffnet und es wird so fortgefahren, als wären die Änderungen nicht vorgenommen worden. Die Änderungen werden jedoch in der Datei „setting.json“ widergespiegelt.

Aktualisierung Nr. 2

Fassen wir zusammen, was ich mache. Ich habe C# beiseite gelassen, um zu untersuchen, was Docker Desktop instabil macht. Dies ist das vollständige Powershell-Skript, das ich bereitstelle, mit den Änderungen, die ich in setting.json brauche. Das Skript funktioniert korrekt, aber sobald sich die Docker-Desktop-Benutzeroberfläche nach 30 Sekunden öffnet, ist sie völlig instabil bzw. es flackert etwas, wenn ich versuche, auf ein beliebiges UI-Steuerelement zu klicken:

$ErrorActionPreference = 'Continue'
Set-Service -Name "com.docker.service" -StartupType Automatic -ErrorAction SilentlyContinue
Stop-Service -Name "com.docker.service" -ErrorAction SilentlyContinue
Get-Process 'Docker Desktop' -ErrorAction Ignore | Stop-Process -Force -ErrorAction Stop
Wait-Process -Name 'Docker Desktop' -ErrorAction SilentlyContinue
$settingsToUpdate = @{
    exposeDockerAPIOnTCP2375 = $true
    updateHostsFile = $true
    licenseTermsVersion = 2
    noWindowsContainers = $true
    runWinServiceInWslMode = $false
    useResourceSaver = $false
}

$settingsPath = "$env:APPDATA\Docker\settings.json"
$settingsContent = Get-Content $settingsPath -Raw 
$settingsObject  = $settingsContent | ConvertFrom-Json

$trackUpdates = 0
foreach ($update in $settingsToUpdate.GetEnumerator()) {
    if ($target = $settingsObject.psobject.Properties.Match($update.Key)) {
        if ($target.Value -ne $update.Value) {
            Add-Member -InputObject $settingsObject -MemberType NoteProperty -Name $update.Key -Value $update.Value -Force
            $trackUpdates++
        }
    }
}

if ($trackUpdates -eq 0) {
    Write-Host "No new settings applied"
} else {
    $settingsObject | ConvertTo-Json | Set-Content $settingsPath
    Write-Host "Settings updated and saved successfully"
}

Start-Service -Name "com.docker.service" -ErrorAction SilentlyContinue

while ((Get-Service -Name "com.docker.service").Status -ne "Running") {
    Write-Host (Get-Service -Name "com.docker.service").Status
    Start-Sleep -Seconds 1
}

if((Get-Service -Name "com.docker.service").Status -eq "Running"){
    Write-Host (Get-Service -Name "com.docker.service").Status
}

$dockerDesktopFilePath = $env:ProgramFiles | Join-Path -ChildPath 'Docker\Docker\Docker Desktop.exe'; Start-Process -FilePath $dockerDesktopFilePath

$ipcTimeout = New-TimeSpan -Seconds 20
$waitUntil = [datetime]::Now.Add($ipcTimeout)
$pipeOpen = $false
Write-Host 'Probing docker engine I/O pipe'
do {
  Start-Sleep -Milliseconds 100
  $pipeOpen = Test-Path -LiteralPath \\.\pipe\docker_engine
} until ($pipeOpen -or ($waitUntil -le [datetime]::Now))

if (-not $pipeOpen) {
  Write-Warning "Failed to observe named IPC pipe docker_engine within timeout"
  return
}

$responseTimeout = New-TimeSpan -Seconds 5
$waitUntil = [datetime]::Now.Add($responseTimeout)

Write-Host 'Querying docker server info'
do {
  Start-Sleep -Milliseconds 500
  $dockerInfoOutput = docker info 2>&1 
  $dockerInfoSuccess = $?
} until ($dockerInfoSuccess -or ($waitUntil -le [datetime]::Now))

if (-not $dockerInfoSuccess) {
  Write-Warning "docker info failed within timeout"
  return
}

Write-Host 'Docker Desktop Is Runing Now'

Aktualisierung Nr. 3

Das Problem ist also nicht, wie die Anwendung geöffnet wird, sondern wie sie geschlossen wird …

ein Freund versucht, dieses Skript auszuführen:

$ServiceName = "com.docker.service"
$ProcessName = "Docker Desktop"

$arrService = Get-Service -Name $ServiceName
if ($arrService.Status -ne 'Running') {
    Stop-Service -Name $ServiceName
}


if (Get-Process $ProcessName -ErrorAction SilentlyContinue) {  
  Stop-Process -Name $ProcessName
  Wait-Process -Name $ProcessName
}

In meinem Fall würde der Dienst nicht laufen, daher ist der obere Teil des Codes egal. Im Taskmanager konnte ich sehen, dass in Bezug auf Docker Desktop 4 bzw. 6 Prozesse laufen. So dass der Stop-Process Befehl den Prozess „Docker Desktop“ sofort beendet hat. Aber 2 Prozesse „Docker Desktop Backend“ und „Docker Desktop Extensions“ laufen noch. Ich habe Docker Desktop per Doppelklick auf eine Verknüpfung gestartet und konnte dann sehen, dass die Docker Engine pausiert war und die Anwendung nicht stabil lief. Ich habe dann alle Prozesse beendet und konnte Docker Desktop wieder problemlos öffnen. Ab hier muss man alles Weitere selbst herausfinden.

mir ist nicht klar, wie viele Prozesse beim Schließen von Docker-Desktop geschlossen werden müssen. Es scheint, dass zum Schließen ein Platzhalterzeichen erforderlich ist: "Docker-Desktop*"„oder“ "Docker Desktop*"oder „ "*Docker*", aber dies kann dazu führen, dass Prozesse geschlossen werden, die weiterlaufen sollten.

Andererseits habe ich gestern Abend etwas Merkwürdiges festgestellt, als ich die Installation Nr. 64 von 0 aus durchgeführt habe.

Es stellt sich heraus, dass, wenn Sie Docker ausführen und zum ersten Mal zu den Einstellungen gehen und die Option zum Aktualisieren der Hosts-Datei aktivieren, die Eigenschaft updateHostsFile nicht die einzige ist, die sich ändert; diese beiden anderen ändern sich ebenfalls: noWindowsContainers, runWinServiceInWslMode und bringen die allgemeine Docker-Konfiguration durcheinander, wenn Sie Windows 11/10 Home verwenden, da diese Optionen nur aktiviert werden sollten, wenn Sie die PRO-Version mit Hiper-V verwenden.

Aus diesem Grund hat es keine Auswirkung, wenn Sie updateHostsFile programmgesteuert aktivieren … es sei denn, Sie aktivieren die anderen beiden … was ebenfalls keine positiven Ergebnisse bringt …

Die Sache ist kompliziert und komplex … es sollte einfacher sein, dies über PowerShell zu verwalten …

Antwort1

Das endgültige Skript für die programmgesteuerte Ausführung:

  • Stoppen Sie den Docker-Dienst und -Prozess.
  • Aktualisieren Sie setting.json.
  • Öffnen Sie den Docker-Desktop hier erneut:

https://gist.github.com/arcanisgk/d78acd5d51ab263d9467fb2da97781ca

Das Instabilitätsproblem trat auf, weil nicht alle in Docker integrierten Prozesse geschlossen wurden. Offenbar gibt es eine Reihe weiterer Prozesse (keine Dienste), die ebenfalls geschlossen werden müssen, da es sonst zu Instabilitäten kommt.

$ErrorActionPreference = 'Continue'

Stop-Service -Name "com.docker.*" -ErrorAction SilentlyContinue
Set-Service -Name "com.docker.service" `
  -StartupType Automatic `
  -ErrorAction SilentlyContinue

$processesToStop = @(
  'Docker Desktop',
  'com.docker.backend',
  'com.docker.extensions'
)
$processesToStop | ForEach-Object {
  Get-Process -Name $_ -ErrorAction Ignore |
    Stop-Process -Force -ErrorAction Ignore
}

$settingsToUpdate = @{
  exposeDockerAPIOnTCP2375 = $true
  updateHostsFile = $true
  licenseTermsVersion = 2
  noWindowsContainers = $false    # Required to enable read updateHostsFile
  runWinServiceInWslMode = $true  # Required to enable read updateHostsFile
  useResourceSaver = $false
}

$settingsPath    = "$env:APPDATA\Docker\settings.json"
$settingsContent = Get-Content $settingsPath -Raw 
$settingsObject  = $settingsContent | ConvertFrom-Json

$trackUpdates = 0
foreach ($update in $settingsToUpdate.GetEnumerator()) {
  if ($target = $settingsObject.psobject.Properties.Match($update.Key)) {
    if ($target.Value -ne $update.Value) {
      Write-Host $update.Key
      Add-Member `
        -InputObject $settingsObject `
        -MemberType NoteProperty `
        -Name $update.Key `
        -Value $update.Value `
        -Force
      $trackUpdates++
    }
  }
}

if ($trackUpdates -eq 0) {
  Write-Host "No new settings applied"
} else {
  $settingsObject | ConvertTo-Json | Set-Content $settingsPath
  Write-Host "Settings updated and saved successfully"
}

Start-Service -Name "com.docker.service" -ErrorAction SilentlyContinue

while ((Get-Service -Name "com.docker.service").Status -ne "Running") {
  Write-Host (Get-Service -Name "com.docker.service").Status
  Start-Sleep -Seconds 1
}

if((Get-Service -Name "com.docker.service").Status -eq "Running"){
  Write-Host "Service: com.docker.service is now:"
  Write-Host (Get-Service -Name "com.docker.service").Status
}

$dockerDesktopFilePath = $env:ProgramFiles |
  Join-Path -ChildPath 'Docker\Docker\Docker Desktop.exe'
Start-Process -FilePath $dockerDesktopFilePath

$ipcTimeout = New-TimeSpan -Seconds 20
$waitUntil = [datetime]::Now.Add($ipcTimeout)
$pipeOpen = $false
Write-Host 'Probing docker engine I/O pipe'
do {
  Start-Sleep -Milliseconds 100
  $pipeOpen = Test-Path -LiteralPath \\.\pipe\docker_engine
}
until ($pipeOpen -or ($waitUntil -le [datetime]::Now))

if (-not $pipeOpen) {
  Write-Warning "Failed to observe named IPC pipe docker_engine within timeout"
  return
}

$responseTimeout = New-TimeSpan -Seconds 5
$waitUntil = [datetime]::Now.Add($responseTimeout)

Write-Host 'Querying docker server info'
do {
  Start-Sleep -Milliseconds 500
  $dockerInfoOutput = docker info 2>&1
  $dockerInfoSuccess = $?
}
until ($dockerInfoSuccess -or ($waitUntil -le [datetime]::Now))

if (-not $dockerInfoSuccess) {
  Write-Warning "docker info failed within timeout"
  return
}

Write-Host 'Docker Desktop Is Runing Now'

verwandte Informationen