
Я снова здесь, посмотрим, сможете ли вы мне помочь...
Обычно при установке 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'