Skip to content
28 changes: 21 additions & 7 deletions src/azure-cli/azure/cli/command_modules/acr/check_health.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# --------------------------------------------------------------------------------------------

import re
import json
from knack.util import CLIError
from knack.log import get_logger
from .custom import get_docker_command
Expand Down Expand Up @@ -88,18 +89,31 @@ def _get_docker_status_and_version(ignore_errors, yes):
docker_daemon_available = False

if docker_daemon_available:
logger.warning("Docker daemon status: available")
logger.warning("%s daemon status: available", docker_command.title())

# Docker version check
output, warning, stderr, succeeded = _subprocess_communicate(
[docker_command, "version", "--format", "'Docker version {{.Server.Version}}, "
"build {{.Server.GitCommit}}, platform {{.Server.Os}}/{{.Server.Arch}}'"])
output, warning, stderr, succeeded = _subprocess_communicate([docker_command, "version", "--format", "json"])
if not succeeded:
_handle_error(DOCKER_VERSION_ERROR.append_error_message(stderr), ignore_errors)
else:
if warning:
logger.warning(warning)
logger.warning("Docker version: %s", output)
try:
json_output = json.loads(output).get("Client")
except json.decoder.JSONDecodeError:
json_output = {}
version = json_output.get("Version", "unknown")
commit = json_output.get("GitCommit", "unknown")[:7]
if docker_command == "docker":
os = json_output.get("Os", "unknown")
arch = json_output.get("Arch", "unknown")
else:
try:
os, arch = json_output.get("OsArch", "unknown").split("/")
except ValueError:
os = "unknown"
arch = "unknown"
logger.warning("%s version: %s, build %s, platform %s/%s", docker_command.title(), version, commit, os, arch)
Copy link
Member

@lizMSFT lizMSFT Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this logger.warning("%s version: %s, build %s, platform %s/%s", docker_command.title(), version, commit, os, arch) statement be indented inside the else block?
Right now it can raise a NameError if version, commit, os, or arch aren’t defined.


# Docker pull check - only if docker daemon is available
if docker_daemon_available:
Expand All @@ -114,14 +128,14 @@ def _get_docker_status_and_version(ignore_errors, yes):

if not succeeded:
if stderr and DOCKER_PULL_WRONG_PLATFORM in stderr:
print_pass("Docker pull of '{}'".format(IMAGE))
print_pass(f"{docker_command.title()} pull of '{IMAGE}'")
logger.warning("Image '%s' can be pulled but cannot be used on this platform", IMAGE)
return
_handle_error(DOCKER_PULL_ERROR.append_error_message(stderr), ignore_errors)
else:
if warning:
logger.warning(warning)
print_pass("Docker pull of '{}'".format(IMAGE))
print_pass(f"{docker_command.title()} pull of '{IMAGE}'")


# Get current CLI version
Expand Down
5 changes: 4 additions & 1 deletion src/azure-cli/azure/cli/command_modules/acr/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import os
import re
import shutil
from knack.util import CLIError
from knack.log import get_logger
from azure.cli.core.azclierror import InvalidArgumentValueError, RequiredArgumentMissingError
Expand Down Expand Up @@ -396,6 +397,8 @@ def get_docker_command(is_diagnostics_context=False):
docker_command = os.getenv('DOCKER_COMMAND')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name is now misleading because the logic supports Podman as well. Consider renaming it to avoid confusion for future maintainers.

else:
docker_command = 'docker'
if not shutil.which('docker') and shutil.which('podman'):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is also used by _get_docker_status_and_version which outputs hardcoded "Docker" messages (e.g., "Docker version", "Docker daemon status"). When Podman is used instead, these messages will be inaccurate. Please update check_healthy.py as well to dynamically reflect which tool is being checked, or use tool-agnostic terminology like "Container runtime".

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lizMSFT this has been updated, however, docker version and podman version behave quite differently so I ended up parsing the --format json output instead of trying to reconcile the differences in the two commands. Let me know if you're happy with this.

docker_command = 'podman'

from subprocess import PIPE, Popen, CalledProcessError
try:
Expand All @@ -405,7 +408,7 @@ def get_docker_command(is_diagnostics_context=False):
logger.debug("Could not run '%s' command. Exception: %s", docker_command, str(e))
# The executable may not be discoverable in WSL so retry *.exe once
try:
docker_command = 'docker.exe'
docker_command = f'{docker_command}.exe'
p = Popen([docker_command, "ps"], stdout=PIPE, stderr=PIPE)
_, stderr = p.communicate()
except OSError as inner:
Expand Down