From 23551f7148e71e5108334b9263de93cc82ce3cdb Mon Sep 17 00:00:00 2001 From: Eli Bosley Date: Tue, 21 Apr 2026 16:34:21 -0400 Subject: [PATCH 1/5] feat(docker): show container MAC addresses - Purpose: expose Docker endpoint MAC addresses in the advanced container list for router and macvlan configuration workflows. - Before: the Docker page showed container network names and IPs, but discarded MacAddress from inspect data. - Problem: users had to SSH into Unraid and run docker inspect manually to find MAC addresses. - Change: preserve MacAddress for each container network and render it in an advanced-only MAC Address column. - Implementation: carries MacAddress through DockerClient network metadata and displays aligned values in DockerContainers.php. --- .../dynamix.docker.manager/DockerContainers.page | 3 ++- .../dynamix.docker.manager/include/DockerClient.php | 12 ++++++++++-- .../include/DockerContainers.php | 7 +++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page index 8cf6e687ca..7b6bdd52d3 100755 --- a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page +++ b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page @@ -38,6 +38,7 @@ $cpus = cpu_list(); _(Version)_ _(Network)_ _(Container IP)_ + _(MAC Address)_ _(Container Port)_ _(LAN IP:Port)_ _(Volume Mappings)_ (_(App to Host)_) @@ -46,7 +47,7 @@ $cpus = cpu_list(); _(Uptime)_ - + diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index 920a7fdbfd..5475cfe0b0 100755 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -1022,15 +1022,23 @@ public function getDockerContainers() { $ports = &$info['Config']['ExposedPorts']; } foreach($ct['NetworkSettings']['Networks'] as $netName => $netVals) { + $networkDetails = $info['NetworkSettings']['Networks'][$netName] ?? $netVals; $i = $c['NetworkMode']=='host' ? $host : $netVals['IPAddress']; - $c['Networks'][$netName] = [ 'IPAddress' => $i ]; + $c['Networks'][$netName] = [ + 'IPAddress' => $i, + 'MacAddress' => $networkDetails['MacAddress'] ?? '' + ]; if ( isset($driver[$netName]) && ($driver[$netName]=='ipvlan' || $driver[$netName]=='macvlan') ) { if (!isset($c['Ports']['vlan'])) $c['Ports']['vlan'] = []; $c['Ports']['vlan']["$i"] = $i; } } + $networkDetails = $info['NetworkSettings']['Networks'][$c['NetworkMode']] ?? $ct['NetworkSettings']['Networks'][$c['NetworkMode']] ?? []; $ip = $c['NetworkMode']=='host' ? $host : $ct['NetworkSettings']['Networks'][$c['NetworkMode']]['IPAddress'] ?? null; - $c['Networks'][$c['NetworkMode']] = [ 'IPAddress' => $ip ]; + $c['Networks'][$c['NetworkMode']] = [ + 'IPAddress' => $ip, + 'MacAddress' => $networkDetails['MacAddress'] ?? '' + ]; $ports = (isset($ports) && is_array($ports)) ? $ports : []; foreach ($ports as $port => $value) { if (!isset($info['HostConfig']['PortBindings'][$port])) { diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index 504728b6a4..67d7d27b4c 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -28,7 +28,7 @@ $autostart_file = $dockerManPaths['autostart-file']; if (!$containers && !$images) { - echo ""._('No Docker containers installed').""; + echo ""._('No Docker containers installed').""; return; } @@ -144,6 +144,7 @@ function my_lang_log($text) { $wait = var_split($autostart[array_search($name,$names)]??'',1); $networks = []; $network_ips = []; + $network_macs = []; $ports_internal = []; $ports_external = []; if (isset($ct['Ports']['vlan'])) { @@ -155,6 +156,7 @@ function my_lang_log($text) { foreach($ct['Networks'] as $netName => $netVals) { $networks[] = $netName; $network_ips[] = $running ? $netVals['IPAddress'] : null; + $network_macs[] = htmlspecialchars((string)($netVals['MacAddress'] ?? '')); if (isset($ct['Networks']['host'])) { $ports_external[] = sprintf('%s', $netVals['IPAddress']); $ports_internal[0] = sprintf('%s', 'all'); @@ -323,6 +325,7 @@ function my_lang_log($text) { echo "
".compress(_($version),12,0)."
"; echo " ".implode('
',$networks).$TS_status."
"; echo " ".implode('
',$network_ips)."
"; + echo " ".implode('
',$network_macs)."
"; echo "".implode('
',$ports_internal)."
"; echo "".implode('
',$ports_external)."
"; echo "".implode('
',$paths)."
"; @@ -346,7 +349,7 @@ function my_lang_log($text) { $menu = sprintf("onclick=\"addDockerImageContext('%s','%s')\"", $id, implode(',',$image['Tags'])); echo ""; echo "("._('orphan image').")
"._('stopped')."
"; - echo ""._('Image ID').": $id
"; + echo ""._('Image ID').": $id
"; echo implode(', ',$image['Tags']); echo ""._('Created')." ".htmlspecialchars(_($image['Created'],0)).""; } From 328473194ee1c8e15a59b17f18401416d40a2eac Mon Sep 17 00:00:00 2001 From: Eli Bosley Date: Tue, 21 Apr 2026 16:39:00 -0400 Subject: [PATCH 2/5] fix(docker): stack MAC addresses with container IPs - Purpose: keep the Docker container table compact while still exposing MAC addresses in advanced view. - Before: the PR added a separate advanced-only MAC Address column next to Container IP. - Problem: the extra column widened the Docker page table for data that belongs with each endpoint IP. - Change: render each network MAC address as an advanced-only line beneath the matching container IP. - Implementation: removes the MAC Address header and extra cell while preserving MacAddress data from DockerClient. --- .../dynamix.docker.manager/DockerContainers.page | 3 +-- .../include/DockerContainers.php | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page index 7b6bdd52d3..e7fc0d9914 100755 --- a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page +++ b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page @@ -38,7 +38,6 @@ $cpus = cpu_list(); _(Version)_ _(Network)_ _(Container IP)_ - _(MAC Address)_ _(Container Port)_ _(LAN IP:Port)_ _(Volume Mappings)_ (_(App to Host)_) @@ -47,7 +46,7 @@ $cpus = cpu_list(); _(Uptime)_ - + diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index 67d7d27b4c..c8699bf81a 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -28,7 +28,7 @@ $autostart_file = $dockerManPaths['autostart-file']; if (!$containers && !$images) { - echo ""._('No Docker containers installed').""; + echo ""._('No Docker containers installed').""; return; } @@ -144,7 +144,6 @@ function my_lang_log($text) { $wait = var_split($autostart[array_search($name,$names)]??'',1); $networks = []; $network_ips = []; - $network_macs = []; $ports_internal = []; $ports_external = []; if (isset($ct['Ports']['vlan'])) { @@ -155,8 +154,9 @@ function my_lang_log($text) { } foreach($ct['Networks'] as $netName => $netVals) { $networks[] = $netName; - $network_ips[] = $running ? $netVals['IPAddress'] : null; - $network_macs[] = htmlspecialchars((string)($netVals['MacAddress'] ?? '')); + $network_ip = $running ? htmlspecialchars((string)$netVals['IPAddress']) : ''; + $network_mac = htmlspecialchars((string)($netVals['MacAddress'] ?? '')); + $network_ips[] = $network_mac ? "$network_ip
"._('MAC').": $network_mac
" : $network_ip; if (isset($ct['Networks']['host'])) { $ports_external[] = sprintf('%s', $netVals['IPAddress']); $ports_internal[0] = sprintf('%s', 'all'); @@ -325,7 +325,6 @@ function my_lang_log($text) { echo "
".compress(_($version),12,0)."
"; echo " ".implode('
',$networks).$TS_status."
"; echo " ".implode('
',$network_ips)."
"; - echo " ".implode('
',$network_macs)."
"; echo "".implode('
',$ports_internal)."
"; echo "".implode('
',$ports_external)."
"; echo "".implode('
',$paths)."
"; @@ -349,7 +348,7 @@ function my_lang_log($text) { $menu = sprintf("onclick=\"addDockerImageContext('%s','%s')\"", $id, implode(',',$image['Tags'])); echo ""; echo "("._('orphan image').")
"._('stopped')."
"; - echo ""._('Image ID').": $id
"; + echo ""._('Image ID').": $id
"; echo implode(', ',$image['Tags']); echo ""._('Created')." ".htmlspecialchars(_($image['Created'],0)).""; } From dedd0d0e29e9372af9a0d5892212c6120da9aeef Mon Sep 17 00:00:00 2001 From: Eli Bosley Date: Tue, 21 Apr 2026 16:43:15 -0400 Subject: [PATCH 3/5] fix(docker): show MAC inline with container IP - Purpose: make the advanced Docker network value more compact and readable. - Before: MAC addresses appeared beneath the container IP as a stacked advanced-only line. - Problem: the requested presentation is a single Container IP / MAC value. - Change: updates the heading to include advanced-only / MAC text and renders MAC addresses inline after the container IP with a slash separator. - Implementation: keeps the MAC span advanced-only so basic view continues to show only the container IP. --- emhttp/plugins/dynamix.docker.manager/DockerContainers.page | 2 +- .../plugins/dynamix.docker.manager/include/DockerContainers.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page index e7fc0d9914..053c6d9585 100755 --- a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page +++ b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page @@ -37,7 +37,7 @@ $cpus = cpu_list(); _(Application)_ _(Version)_ _(Network)_ - _(Container IP)_ + _(Container IP)_ / _(MAC)_ _(Container Port)_ _(LAN IP:Port)_ _(Volume Mappings)_ (_(App to Host)_) diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index c8699bf81a..6e175684e3 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -156,7 +156,7 @@ function my_lang_log($text) { $networks[] = $netName; $network_ip = $running ? htmlspecialchars((string)$netVals['IPAddress']) : ''; $network_mac = htmlspecialchars((string)($netVals['MacAddress'] ?? '')); - $network_ips[] = $network_mac ? "$network_ip
"._('MAC').": $network_mac
" : $network_ip; + $network_ips[] = $network_mac ? "$network_ip / $network_mac" : $network_ip; if (isset($ct['Networks']['host'])) { $ports_external[] = sprintf('%s', $netVals['IPAddress']); $ports_internal[0] = sprintf('%s', 'all'); From 64b1bc541791690e458d08ec71bc19a98e4c55db Mon Sep 17 00:00:00 2001 From: Eli Bosley Date: Tue, 21 Apr 2026 16:43:50 -0400 Subject: [PATCH 4/5] fix(docker): stack MAC below container IP - Purpose: match the requested advanced Docker cell presentation. - Before: the MAC address rendered inline after the container IP with a slash separator. - Problem: the desired layout is easier to scan as two lines without a MAC label. - Change: renders the container IP first and the raw MAC address on the next advanced-only line. - Implementation: keeps the MAC value inside the advanced span so basic view remains unchanged. --- .../plugins/dynamix.docker.manager/include/DockerContainers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index 6e175684e3..012e937e17 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -156,7 +156,7 @@ function my_lang_log($text) { $networks[] = $netName; $network_ip = $running ? htmlspecialchars((string)$netVals['IPAddress']) : ''; $network_mac = htmlspecialchars((string)($netVals['MacAddress'] ?? '')); - $network_ips[] = $network_mac ? "$network_ip / $network_mac" : $network_ip; + $network_ips[] = $network_mac ? "$network_ip
$network_mac
" : $network_ip; if (isset($ct['Networks']['host'])) { $ports_external[] = sprintf('%s', $netVals['IPAddress']); $ports_internal[0] = sprintf('%s', 'all'); From 753204c44579a1cafb0f86f4d0b0e8858ebd82d5 Mon Sep 17 00:00:00 2001 From: Eli Bosley Date: Tue, 21 Apr 2026 20:08:01 -0400 Subject: [PATCH 5/5] fix(docker): hide MAC address for stopped containers - Purpose: address PR feedback about matching MAC visibility to container IP visibility. - Before: stopped containers hid the IP address but could still carry a MAC address value into the advanced cell. - Problem: the MAC line should follow the same running-state behavior as the IP line. - Change: only renders a network MAC address when the container is running. - Implementation: applies the existing running check to the MacAddress display value. --- .../plugins/dynamix.docker.manager/include/DockerContainers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index 012e937e17..8ed97abade 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -155,7 +155,7 @@ function my_lang_log($text) { foreach($ct['Networks'] as $netName => $netVals) { $networks[] = $netName; $network_ip = $running ? htmlspecialchars((string)$netVals['IPAddress']) : ''; - $network_mac = htmlspecialchars((string)($netVals['MacAddress'] ?? '')); + $network_mac = $running ? htmlspecialchars((string)($netVals['MacAddress'] ?? '')) : ''; $network_ips[] = $network_mac ? "$network_ip
$network_mac
" : $network_ip; if (isset($ct['Networks']['host'])) { $ports_external[] = sprintf('%s', $netVals['IPAddress']);