Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions interface-definitions/container.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,67 @@
</properties>
<defaultValue>journald</defaultValue>
</leafNode>
<node name="health-check">
<properties>
<help>Configure health check for the container</help>
</properties>
<children>
<leafNode name="disable">
<properties>
<help>Disable health check if container has one defined</help>
<valueless/>
</properties>
</leafNode>
Comment on lines +564 to +569
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
<leafNode name="disable">
<properties>
<help>Disable health check if container has one defined</help>
<valueless/>
</properties>
</leafNode>
#include <include/generic-disable-node.xml.i>

We have a generic XML building block for the disable CLI option.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Given the semantics are different I'd keep the custom help text here.

<leafNode name="command">
<properties>
<help>Health check command to run for the container</help>
</properties>
</leafNode>
<leafNode name="interval">
<properties>
<help>Interval for the health checks</help>
<completionHelp>
<list>disable</list>
Copy link
Member

Choose a reason for hiding this comment

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

An interval that is not defined on the CLI should count as disabled

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The situation is a bit more complex. Container can define health checks including intervals etc. Podman by default will run them as defined by the image.

So all the config options here are overrides if the image defines them already. And the disable option is there to explicitly also disable pre-defined health checks.

</completionHelp>
<valueHelp>
<format>disable</format>
<description>Run health checks manually</description>
</valueHelp>
<valueHelp>
<format>u32:1-16384</format>
<description>Time in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-16384"/>
</constraint>
</properties>
</leafNode>
<leafNode name="timeout">
<properties>
<help>Timeout for the health check to complete</help>
<valueHelp>
<format>u32:1-16384</format>
<description>Time in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-16384"/>
</constraint>
</properties>
</leafNode>
<leafNode name="retries">
<properties>
<help>The number of retries before container is consider unhealthy</help>
<valueHelp>
<format>0</format>
<description>No retry</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-255"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
</children>
</tagNode>
<tagNode name="network">
Expand Down
21 changes: 21 additions & 0 deletions smoketest/scripts/cli/test_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ def test_basic(self):

self.cli_set(base_path + ['name', cont_name, 'image', busybox_image])
self.cli_set(base_path + ['name', cont_name, 'allow-host-networks'])
self.cli_set(base_path + ['name', cont_name, 'health-check', 'disable'])
self.cli_set(
base_path
+ [
Expand Down Expand Up @@ -112,6 +113,26 @@ def test_basic(self):

l = cmd_to_json(f'sudo podman container inspect {cont_name}')
self.assertEqual(l['HostConfig']['LogConfig']['Type'], 'journald')
self.assertEqual(l['Config']['Healthcheck']['Test'], ['NONE'])

def test_healthcheck(self):
cont_name = 'health-test'

self.cli_set(base_path + ['name', cont_name, 'allow-host-networks'])
self.cli_set(base_path + ['name', cont_name, 'image', busybox_image])

self.cli_set(base_path + ['name', cont_name, 'health-check', 'command', 'true'])
self.cli_set(base_path + ['name', cont_name, 'health-check', 'interval', '10s'])
self.cli_set(base_path + ['name', cont_name, 'health-check', 'timeout', '1s'])
self.cli_set(base_path + ['name', cont_name, 'health-check', 'retries', '2'])
self.cli_commit()

l = cmd_to_json(f'sudo podman container inspect {cont_name}')
self.assertEqual(l['HostConfig']['LogConfig']['Type'], 'journald')
self.assertEqual(l['Config']['Healthcheck']['Test'], ['CMD-SHELL', 'true'])
self.assertEqual(l['Config']['Healthcheck']['Interval'], 10000000000)
self.assertEqual(l['Config']['Healthcheck']['Timeout'], 1000000000)
self.assertEqual(l['Config']['Healthcheck']['Retries'], 2)


def test_name_server(self):
Expand Down
23 changes: 21 additions & 2 deletions src/conf_mode/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,25 @@ def generate_run_arguments(name, container_config, host_ident):
entrypoint = json_write(container_config['entrypoint'].split()).replace('"', "&quot;")
entrypoint = f'--entrypoint &apos;{entrypoint}&apos;'

healthcheck = ''
if 'health_check' in container_config:
if 'command' in container_config['health_check']:
health_cmd = container_config['health_check']['command']
healthcheck += f' --health-cmd="{health_cmd}"'
if 'interval' in container_config['health_check']:
health_int = container_config['health_check']['interval']
if health_int != 'disable':
health_int = f'{health_int}s'
healthcheck += f' --health-interval={health_int}'
if 'timeout' in container_config['health_check']:
health_to = container_config['health_check']['timeout']
healthcheck += f' --health-timeout={health_to}s'
if 'retries' in container_config['health_check']:
health_rt = container_config['health_check']['retries']
healthcheck += f' --health-retries={health_rt}'
if 'disable' in container_config['health_check']:
healthcheck = f' --no-healthcheck'

command = ''
if 'command' in container_config:
command = container_config['command'].strip()
Expand All @@ -471,7 +490,7 @@ def generate_run_arguments(name, container_config, host_ident):
command_arguments = container_config['arguments'].strip()

if 'allow_host_networks' in container_config:
return f'{container_base_cmd} --net host {entrypoint} {image} {command} {command_arguments}'.strip()
return f'{container_base_cmd} {healthcheck} --net host {entrypoint} {image} {command} {command_arguments}'.strip()

ip_param = ''
addr_info = ''
Expand All @@ -489,7 +508,7 @@ def generate_run_arguments(name, container_config, host_ident):

mac_address = f'--mac-address {gen_mac(name, addr_info, host_ident)}'

return f'{container_base_cmd} --no-healthcheck --net {networks} {ip_param} {mac_address} {entrypoint} {image} {command} {command_arguments}'.strip()
return f'{container_base_cmd} {healthcheck} --net {networks} {ip_param} {mac_address} {entrypoint} {image} {command} {command_arguments}'.strip()
Copy link
Member

Choose a reason for hiding this comment

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

The default behaviour is changed,
If we do not have any health-check option, we used --no-healthcheck, but now it will be ''

Copy link
Contributor Author

@nvollmar nvollmar Sep 24, 2025

Choose a reason for hiding this comment

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

The issue here is, the --no-healthcheck was only added when using container networking, when host networking was used (see line 491) it wasn't.
So far I never encountered a container which defined health checks in the image by itself. I'd argue changing the default behaviour here to make it consistent regardless of which networking is used would be preferable.



def generate(container):
Expand Down
Loading