Skip to main content

Docker upgrade on WIN server

Upgrade Docker engine

You have two options how to upgrade docker engine. "Docker engine as a service" (A), "Docker engine triggered by scheduled task" (B)

tip

Before upgrading docker engine stop all running containers by docker-compose down command from project directory.

A) Docker engine as a service

Best practise is to use docker engine as a service. Here are steps how to create new service:

Work in cmd as administator
In all commands replace "_$version_number" with real number of installed docker, e.g. path to docker binaries: C:\Program Files\Docker$version_number

tip

You can follow steps below or use script which does the work:

Loading files from: /documents/installation/files.json

Directory: /documents/installation

Example of how to run the script.:

.\Install-DockerEngine.ps1 -DockerVersion "29.1.5" -ComposeVersion "5.0.2"

Steps to upgrade Docker engine

  1. Download binaries files with version that you want from web and unzip to host server to "C:\Program Files\Docker$version_number". You should have unzipped "docker.exe" and "dockerd.exe" files.
  2. Create data folder for new service:
    mkdir "C:\ProgramData\Docker_$version_number"
    mkdir "C:\ProgramData\Docker_$version_number\exec"
  3. Register new service:
    sc.exe create "Docker-_$version_number" binPath= "\"C:\Program Files\Docker\_$version_number\dockerd.exe\" --run-service --data-root=\"C:\ProgramData\Docker__$version_number\" --exec-root=\"C:\ProgramData\Docker__$version_number\exec\"" DisplayName= "Docker Engine _$version_number" start= demand
  4. Check service:
    sc.exe qc Docker-_$version_number
  5. Stop old docker service in "Services" manager
  6. Start new service:
    sc.exe start Docker-_$version_number
  7. Change environment variable in PATH to new folder with docker binaries, should be C:\Program Files\Docker\$version_number
warning

If steps above crashes with any error (1053/SCM timeout) - mainly on Windows servers 2019 - and you won't be able to run newly registered service you need to follow backup plan (option B)

B) Docker engine triggered by scheduled task

Steps 1 and 2 are same as in A) option.

  1. Create ps1 script in "C:\Program Files\Docker_$version_number\start-dockerd-_$version_number.ps1" with this content:
    $ErrorActionPreference = 'Stop'

    $dockerd = 'C:\Program Files\Docker\$version_number\dockerd.exe'
    $dataRoot = 'C:\ProgramData\Docker_$version_number'
    $execRoot = 'C:\ProgramData\Docker_$version_number\exec'

    # "Header" log (human-readable), only launcher start/stop
    $logHeader = 'C:\ProgramData\Docker_$version_number\dockerd.log'
    # Dockerd stdout (daemon log)/stderr logs
    $logOut = 'C:\ProgramData\Docker_$version_number\dockerd.out.log'
    $logErr = 'C:\ProgramData\Docker_$version_number\dockerd.err.log'

    New-Item -ItemType Directory -Force -Path $dataRoot | Out-Null
    New-Item -ItemType Directory -Force -Path $execRoot | Out-Null

    "==================================================" | Out-File -FilePath $logHeader -Append -Encoding ascii
    "start-dockerd-29.ps1 start: $(Get-Date -Format s)" | Out-File -FilePath $logHeader -Append -Encoding ascii
    "Computer: $env:COMPUTERNAME" | Out-File -FilePath $logHeader -Append -Encoding ascii
    "User: $env:USERNAME" | Out-File -FilePath $logHeader -Append -Encoding ascii
    "DataRoot: $dataRoot" | Out-File -FilePath $logHeader -Append -Encoding ascii
    "ExecRoot: $execRoot" | Out-File -FilePath $logHeader -Append -Encoding ascii
    "Stdout: $logOut" | Out-File -FilePath $logHeader -Append -Encoding ascii
    "Stderr: $logErr" | Out-File -FilePath $logHeader -Append -Encoding ascii
    "==================================================" | Out-File -FilePath $logHeader -Append -Encoding ascii

    # Guard: if dockerd already runs, do nothing
    $existing = Get-CimInstance Win32_Process -Filter "Name='dockerd.exe'" -ErrorAction SilentlyContinue
    if ($existing) {
    "dockerd already running (PID(s): $($existing.ProcessId -join ',')); exiting." |
    Out-File -FilePath $logHeader -Append -Encoding ascii
    exit 0
    }

    $args = @(
    '--debug',
    '--log-level', 'debug',
    '--data-root', $dataRoot,
    '--exec-root', $execRoot
    )

    # Clean old stderr file (stdout can be overwritten; that's fine)
    if (Test-Path $logErr) { Remove-Item -Force $logErr -ErrorAction SilentlyContinue }

    # IMPORTANT: redirect into separate files so header isn't truncated
    Start-Process -FilePath $dockerd -ArgumentList $args -NoNewWindow `
    -RedirectStandardOutput $logOut -RedirectStandardError $logErr

    "dockerd started." | Out-File -FilePath $logHeader -Append -Encoding ascii

    # wait up to 60s for default pipe
    $deadline = (Get-Date).AddSeconds(60)
    while ((Get-Date) -lt $deadline) {
    if (Test-Path "\\.\pipe\docker_engine") { break }
    Start-Sleep -Milliseconds 500
    }

    if (-not (Test-Path "\\.\pipe\docker_engine")) {
    "WARNING: docker_engine pipe not available after 60s" | Out-File -FilePath $logHeader -Append -Encoding ascii
    } else {
    "OK: docker_engine pipe is available" | Out-File -FilePath $logHeader -Append -Encoding ascii
    }
  2. Create task which triggers script above after Windows startup:
    schtasks /Create /TN "Docker Engine $version_number" /SC ONSTART /RU "SYSTEM" /RL HIGHEST /F /TR "\"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe\" -NoProfile -ExecutionPolicy Bypass -File \"C:\Program Files\Docker\$version_number\start-dockerd-$version_number.ps1\""
  3. Kill previous instances of runnig dockerd:
    taskkill /F /IM dockerd.exe
  4. Run task to check.
    schtasks /Run /TN "Docker Engine $version_number"` and check if dockerd is runnig: `tasklist /fi "imagename eq dockerd.exe"

Upgrade Docker-compose plugin

  1. Create folder in "Docker" directory:
    mkdir "C:\Program Files\Docker\$version_number\cli-plugins"
  2. Download "docker-compose" binary file:
    $ver = "v5.0.2"
    Start-BitsTransfer `
    -Source "https://github.com/docker/compose/releases/download/$ver/docker-compose-windows-x86_64.exe" `
    -Destination "$Env:ProgramFiles\Docker\$version_number\cli-plugins\docker-compose.exe"
  3. Set environment variable in PATH to folder with "cli_plugins"
  4. Test plugin:
    docker-compose version
    • you should see correct version number of plugin

Clean environment

info

After successfull installation of new Docker engine service you have to delete (or disable) previous service and clean remains.

  1. Delete previous Docker service:
    sc.exe delete Docker
    • you should get message: [SC] DeleteService SUCCESS
  2. Delete environment variable in PATH for previous Docker folder
  3. Delete data folder for previous Docker service (typically: C:\ProgramData\docker)
  4. Delete folder with binaries for previous Docker service