I’m here again, let’s see if you can give me a hand…
Normally when you install docker-desktop from 0, some configuration files are set to:
C:UsersAppDataRoamingDockersetting.json
It is almost always necessary to do manual steps: open the application, do the survey, then make changes to the settings, save and apply, then close… and log in again.
I am more into using docker-desktop from the terminal, I usually execute the commands to create the network and raise the containers based on docker-compose
The problem or rather the help I am looking for is if you can help me do the programmatic part of updating the settings and closing and reopening the desktop application: docker-desktop
.
I tried doing something before coming here in C# but it turned out to be unstable:
Check/Wait for the invoked application to be open
I’m sure this could be achieved with PowerShell but I don’t know much about it, In powershell i have done this:
# 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:APPDATADockersettings.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') + 'DockerDockerDocker 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"
But i detect that docker-desktop become unstable again… and the setting update file is applied to setting.json but is not charged to docker-desktop when is reopen..
Docker post forum related: https://forums.docker.com/t/programmatic-manipulation-and-management-of-docker-desktop/140018
Update:
What are the exact symptoms of "instability"? answer: When opening Docker-Desktop using the script, the Docker-Desktop User Interface slowly slows down to the point that it are blocked, no response to mouse clicks.
What And how do you test if the changes have been applied after restarting the Docker desktop? answer: the settings tab is opened in docker-desktop and they continue as if the changes had not been made. but the changes are reflected in the setting.json file.
Update #2
Let’s summarize what I’m doing, I’ve left C# aside to evaluate what makes docker desktop unstable, and this is the complete powershell script I’m deploying, with the changes I need in setting.json, the script works correctly, but once that docker-desktop UI opens after 30 seconds, it is completely unstable / somne flicker when try to click any UI control:
$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:APPDATADockersettings.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 'DockerDockerDocker 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 \.pipedocker_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'
Update #3
So the problem is not how the application is opened, but how it is closed…
a friend try to run this 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
}
In my case, the service would not be running, so the upper section of the code does not matter.
In the task manager I could see that 4 or respectively 6 processes are running in relation to Docker desktop. So that the Stop-Process command terminated the porcess “Docker Desktop” immediately.
But 2 processes “Docker Desktop Backend” and “Docker Desktop Extensions” are still running.
I started Docker Desktop by double-clicking on a shortcut and could then see that the Docker Engine was paused and the application was not running stably. I then terminated all processes and was able to open Docker Desktop again without any problems. From here on, you have to find out everything else for yourself.
it is not clear to me how many processes have to be closed when closing Docker-Desktop, it seems that the closing requires a wild-card: "Docker-Desktop*"
or "Docker Desktop*"
or "*Docker*"
but this can cause processes that should be kept running to close.
On the other hand I found something curious last night when I did installation #64 from 0.
It turns out that if you have docker running and you go to the settings for the first time and check the option to update the hosts file, the updateHostsFile property is not the only one that changes; These other 2 also change: noWindowsContainers, runWinServiceInWslMode and screw up the general docker configuration, if you are using Windows 11/10 home, since these options should only be enabled if you are using the PRO version with Hiper-V.
So for this reason, if you programmatically activate updateHostsFile it will have no effect… unless you activate the other two… which will not have positive results either…
The thing is complicated and complex… it should be simpler to manage this through PowerShell…
2
Answers
The final script to programaticaly:
https://gist.github.com/arcanisgk/d78acd5d51ab263d9467fb2da97781ca
The problem of instability occurred because not all the processes that doccker incorporates were closed, apparently there are a series of additional processes (not services) that must be closed equally or it will cause instability.
The following sequence of steps work for me with Docker Desktop 4.3 and Docker Engine 20.10 on Windows:
settings.json
docker_engine
IPC pipe, and fordocker info
queriesFor stopping the process, make life easier by using
Get-Process ... |Stop-Process
– this allows you to ignore failure to resolve existing running processes but still stop on failure to kill any existing processes:Now you can remove all that ugly code to detect whether the processes stopped – it either does exactly what you expect, or it fails conclusively!
Next, let’s look at updating the settings file. Your regex-replace strategy probably works most of the time, but a more robust approach would be:
Step 3 and 4 are the simplest –
Restart-Service
to restart the engine service,Start-Process
to launch Docker Desktop:If you want to revert the settings changes on failure to restart docker engine at this point, consider using a simple
try
/catch
to re-apply the original document contents:Now we just need to wait for docker desktop to become responsive – the following appears to work consistently for me:
Hope this helps!