diff --git a/frontend-modern/src/components/Discovery/DiscoveryTab.tsx b/frontend-modern/src/components/Discovery/DiscoveryTab.tsx index dc3c647f3..ad20728d2 100644 --- a/frontend-modern/src/components/Discovery/DiscoveryTab.tsx +++ b/frontend-modern/src/components/Discovery/DiscoveryTab.tsx @@ -904,6 +904,38 @@ export const DiscoveryTab: Component = (props) => { + {/* Docker bind mounts — host ↔ container path mapping, only on + Docker resources. The host source is where to actually edit or + back up files; the container destination is what the app sees. */} + 0}> +
+
+ Bind Mounts + +
+
+ + {(mount) => ( +
+ +
+ → {mount.destination} in container + + (read-only) + +
+
+ )} +
+
+
+
+ {/* Ports */} 0}>
diff --git a/frontend-modern/src/components/Discovery/__tests__/DiscoveryTab.test.tsx b/frontend-modern/src/components/Discovery/__tests__/DiscoveryTab.test.tsx index 0653c1273..6a96e1fa3 100644 --- a/frontend-modern/src/components/Discovery/__tests__/DiscoveryTab.test.tsx +++ b/frontend-modern/src/components/Discovery/__tests__/DiscoveryTab.test.tsx @@ -354,4 +354,54 @@ describe('DiscoveryTab', () => { await screen.findByText('Mapped open ports and running processes to a PostgreSQL service.'), ).toBeInTheDocument(); }); + + it('renders Docker bind mounts so the host path is visible', async () => { + vi.mocked(discoveryApi.getDiscoveryInfo).mockResolvedValue(discoveryInfoWithProvider()); + vi.mocked(discoveryApi.getDiscovery).mockResolvedValue({ + id: 'app-container:nuc:homeassistant', + resource_type: 'app-container', + resource_id: 'homeassistant', + target_id: 'nuc', + hostname: 'nuc', + service_type: 'home-assistant', + service_name: 'Home Assistant', + service_version: '2026.5', + category: 'home_automation', + cli_access: 'docker exec homeassistant bash', + facts: [], + config_paths: ['/config/automations.yaml'], + data_paths: [], + log_paths: [], + ports: [], + docker_mounts: [ + { + container_name: 'homeassistant', + source: '/opt/homeassistant/config', + destination: '/config', + type: 'bind', + }, + ], + user_notes: '', + user_secrets: {}, + confidence: 0.9, + ai_reasoning: '', + discovered_at: '2026-05-01T00:00:00Z', + updated_at: '2026-05-01T00:00:00Z', + scan_duration: 10, + }); + + render(() => ( + + )); + + // The host source is where you actually edit/back up the files — it must be + // visible, not just the container-internal /config path. + expect(await screen.findByText('Bind Mounts')).toBeInTheDocument(); + expect(await screen.findByText('/opt/homeassistant/config')).toBeInTheDocument(); + }); }); diff --git a/frontend-modern/src/types/discovery.ts b/frontend-modern/src/types/discovery.ts index c08cca38e..4dbec0afe 100644 --- a/frontend-modern/src/types/discovery.ts +++ b/frontend-modern/src/types/discovery.ts @@ -48,6 +48,16 @@ export interface PortInfo { address: string; } +export interface DockerBindMount { + container_name?: string; + /** Host path — where the container's files actually live. */ + source: string; + /** Container path — what the service sees. */ + destination: string; + type?: string; + read_only?: boolean; +} + export interface ResourceDiscovery { id: string; resource_type: APIResourceType; @@ -67,6 +77,7 @@ export interface ResourceDiscovery { data_paths: string[]; log_paths: string[]; ports: PortInfo[]; + docker_mounts?: DockerBindMount[]; user_notes: string; user_secrets: Record; confidence: number;