программно установить конфигурацию docker-desktop

программно установить конфигурацию docker-desktop

Я снова здесь, посмотрим, сможете ли вы мне помочь...

Обычно при установке docker-desktop с 0 некоторые файлы конфигурации устанавливаются следующим образом:

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

Почти всегда необходимо выполнять действия вручную: открыть приложение, пройти опрос, затем внести изменения в настройки, сохранить и применить, затем закрыть... и снова войти в систему.

Мне больше нравится использовать docker-desktop из терминала, я обычно выполняю команды для создания сети и поднимаю контейнеры на основеdocker-compose

Проблема или, скорее, помощь, которую я ищу, заключается в том, можете ли вы помочь мне выполнить программную часть обновления настроек, а также закрытия и повторного открытия настольного приложения: docker-desktop.

До того, как прийти сюда, я пытался что-то сделать на C#, но это оказалось нестабильным:

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

Я уверен, что этого можно добиться с помощью PowerShell, но я не очень хорошо разбираюсь в этой теме.

Пост Docker на форуме, связанный с:https://forums.docker.com/t/programmatic-manipulation-and-management-of-docker-desktop/140018

В powershell я сделал так:

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

Но я обнаружил, что docker-desktop снова стал нестабильным... и настройка для обновления файла Hosts применяется к setting.json, но не передается в docker-desktop.

Обновлять:

Каковы точные симптомы «нестабильности»?

отвечать:При открытии Docker-Desktop с помощью скрипта пользовательский интерфейс Docker-Desktop медленно замедляется до такой степени, что блокируется, не реагируя на щелчки мыши.

Что и как проверить, были ли изменения применены после перезапуска рабочего стола Docker?

отвечать:вкладка настроек открывается в docker-desktop и они продолжают работать так, как будто изменения не были внесены. но изменения отражаются в файле setting.json.

Обновление №2

Давайте подведем итоги того, что я делаю. Я отложил C# в сторону, чтобы оценить, что делает docker desktop нестабильным. Вот полный скрипт PowerShell, который я развертываю, с необходимыми мне изменениями в setting.json. Скрипт работает правильно, но как только пользовательский интерфейс docker-desktop открывается через 30 секунд, он становится совершенно нестабильным / начинает мерцать при попытке нажать на любой элемент управления пользовательского интерфейса:

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

Обновление №3

Так что проблема не в том, как приложение открывается, а в том, как оно закрывается…

друг попробуй запустить этот скрипт:

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

В моем случае служба не будет запущена, поэтому верхняя часть кода не имеет значения. В диспетчере задач я мог видеть, что 4 или соответственно 6 процессов запущены относительно Docker Desktop. Так что команда Stop-Process немедленно завершила процесс «Docker Desktop». Но 2 процесса «Docker Desktop Backend» и «Docker Desktop Extensions» все еще работают. Я запустил Docker Desktop двойным щелчком по ярлыку и затем увидел, что Docker Engine был приостановлен, а приложение работало нестабильно. Затем я завершил все процессы и смог снова открыть Docker Desktop без каких-либо проблем. С этого момента вы должны выяснить все остальное самостоятельно.

Мне не ясно, сколько процессов должно быть закрыто при закрытии Docker-Desktop, похоже, что для закрытия требуется подстановочный знак: "Docker-Desktop*"или "Docker Desktop*"или "*Docker*"но это может привести к закрытию процессов, которые должны быть запущены.

С другой стороны, вчера вечером, когда я делал установку #64 с 0, я обнаружил нечто любопытное.

Оказывается, если у вас запущен Docker и вы впервые заходите в настройки и проверяете опцию обновления файла hosts, то меняется не только свойство updateHostsFile; меняются также и эти два других: noWindowsContainers, runWinServiceInWslMode, и портят общую конфигурацию Docker, если вы используете Windows 11/10 Home, поскольку эти опции следует включать только в том случае, если вы используете версию PRO с Hiper-V.

По этой причине, если вы программно активируете updateHostsFile, это не даст никакого эффекта... если только вы не активируете два других... что также не даст положительных результатов...

Дело это сложное и запутанное... проще было бы управлять этим через PowerShell...

решение1

Окончательный сценарий для программирования:

  • Остановите службу и процесс Docker.
  • Обновите setting.json.
  • Повторное открытие рабочего стола Docker находится здесь:

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

Проблема нестабильности возникла из-за того, что не все процессы, входящие в Docker, были закрыты. По-видимому, существует ряд дополнительных процессов (не служб), которые необходимо закрыть в равной степени, иначе это приведет к нестабильности.

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

Связанный контент