establecer la configuración de Docker-Desktop mediante programación

establecer la configuración de Docker-Desktop mediante programación

Estoy aquí de nuevo, a ver si me podéis echar una mano...

Normalmente, cuando instalas docker-desktop desde 0, algunos archivos de configuración se configuran en:

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

Casi siempre es necesario hacer pasos manuales: abrir la aplicación, hacer la encuesta, luego hacer cambios en la configuración, guardar y aplicar, luego cerrar… e iniciar sesión nuevamente.

Me gusta más usar docker-desktop desde la terminal, suelo ejecutar los comandos para crear la red y levantar los contenedores en función dedocker-compose

El problema o más bien la ayuda que busco es si me pueden ayudar a hacer la parte programática de actualizar la configuración y cerrar y volver a abrir la aplicación de escritorio: docker-desktop.

Intenté hacer algo antes de venir aquí en C# pero resultó ser inestable:

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

Estoy seguro de que esto se podría lograr con PowerShell pero no sé mucho al respecto.

Foro de publicaciones de Docker relacionado:https://forums.docker.com/t/programmatic-manipulation-and-management-of-docker-desktop/140018

En powershell he hecho esto:

# 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"

Pero detecto que Docker-Desktop vuelve a ser inestable... y la configuración para actualizar el archivo Hosts se aplica a settings.json pero no se conversa con Docker-Desktop.

Actualizar:

¿Cuáles son los síntomas exactos de la "inestabilidad"?

respuesta:Al abrir Docker-Desktop usando el script, la interfaz de usuario de Docker-Desktop se ralentiza lentamente hasta el punto de bloquearse y no responde a los clics del mouse.

¿Qué y cómo se prueba si los cambios se han aplicado después de reiniciar el escritorio Docker?

respuesta:se abre la pestaña de configuración en docker-desktop y continúan como si no se hubieran realizado los cambios. pero los cambios se reflejan en el archivo settings.json.

Actualización #2

Resumamos lo que estoy haciendo, dejé C# a un lado para evaluar qué hace que el escritorio de Docker sea inestable, y este es el script de PowerShell completo que estoy implementando, con los cambios que necesito en settings.json, el script funciona correctamente, pero Una vez que la interfaz de usuario de Docker-Desktop se abre después de 30 segundos, es completamente inestable o parpadea cuando intenta hacer clic en cualquier control de la interfaz de usuario:

$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'

Actualización #3

Entonces el problema no es cómo se abre la aplicación, sino cómo se cierra…

un amigo intenta ejecutar este script:

$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
}

En mi caso, el servicio no estaría ejecutándose, por lo que la sección superior del código no importa. En el administrador de tareas pude ver que se están ejecutando 4 o 6 procesos respectivamente en relación con el escritorio Docker. De modo que el comando Stop-Process finalizó el proceso “Docker Desktop” inmediatamente. Pero 2 procesos "Docker Desktop Backend" y "Docker Desktop Extensions" todavía se están ejecutando. Inicié Docker Desktop haciendo doble clic en un acceso directo y luego pude ver que Docker Engine estaba en pausa y la aplicación no se ejecutaba de manera estable. Luego terminé todos los procesos y pude abrir Docker Desktop nuevamente sin ningún problema. A partir de ahora, todo lo demás lo tendrás que descubrir tú mismo.

No tengo claro cuántos procesos deben cerrarse al cerrar Docker-Desktop, parece que el cierre requiere un comodín: "Docker-Desktop*"o "Docker Desktop*"o "*Docker*"pero esto puede provocar que se cierren procesos que deben mantenerse ejecutándose.

Por otro lado encontré algo curioso anoche cuando hice la instalación #64 desde 0.

Resulta que si tienes Docker ejecutándose y vas a configuración por primera vez y marcas la opción de actualizar el archivo hosts, la propiedad updateHostsFile no es la única que cambia; Estos otros 2 también cambian: noWindowsContainers, runWinServiceInWslMode y joden la configuración general de Docker, si estás usando Windows 11/10 home, ya que estas opciones solo deben estar habilitadas si estás usando la versión PRO con Hiper-V.

Entonces por esta razón, si activas programáticamente updateHostsFile no tendrá ningún efecto… a menos que actives los otros dos… lo cual tampoco tendrá resultados positivos…

La cosa es complicada y compleja… debería ser más sencillo gestionar esto a través de PowerShell…

Respuesta1

El script final para programación:

  • Detenga el servicio y proceso de Docker.
  • Actualice la configuración.json.
  • Reabrir el escritorio de Docker está aquí:

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

El problema de la inestabilidad se dio porque no se cerraron todos los procesos que incorpora docker, al parecer hay una serie de procesos adicionales (no servicios) que se deben cerrar igualmente o causará inestabilidad.

$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'

información relacionada