Skip to content

fix(docker): use configured gateways for VLAN networks#2634

Merged
limetech merged 1 commit into
masterfrom
codex/docker-vlan-gateway-fallback
May 12, 2026
Merged

fix(docker): use configured gateways for VLAN networks#2634
limetech merged 1 commit into
masterfrom
codex/docker-vlan-gateway-fallback

Conversation

@elibosley
Copy link
Copy Markdown
Member

@elibosley elibosley commented May 11, 2026

Summary

  • Add a configured_gateway fallback for automatic Docker custom network creation.
  • Use configured GATEWAY / GATEWAY6 values from /boot/config/network.cfg when no interface-specific default route exists.
  • Source the same network config shape used by rc.inet1.conf, with associative arrays declared before import, instead of parsing generated network.ini text.
  • Preserve existing live-route behavior when a default route is present.

Root Cause

rc.docker recreates automatic custom Docker networks from the live interface state. For VLANs and secondary interfaces, ip route show to default dev <network> can be empty even though Unraid has a configured gateway for that network.

When Docker creates a macvlan/ipvlan network without --gateway, Docker may select the first address in the subnet as the gateway. On common VLANs this can collide with the real router address, for example 192.168.10.1, breaking containers that depend on DHCP or static IP reachability.

Impact

This keeps VLAN and secondary-NIC Docker custom networks from losing their configured gateway during automatic network recreation, addressing reports where containers on VLANs stopped receiving DHCP or became unreachable after upgrading.

Validation

  • Ran bash -n etc/rc.d/rc.docker.
  • Ran git diff --check.
  • Exercised configured_gateway locally against synthetic network.cfg inputs for:
    • eth0, br0, br0.10, eth0.30, br1.20, eth1.20, br2.40, and bond2.40 IPv4 gateway lookup
    • br0.10 IPv6 gateway lookup
    • missing VLAN returns no fallback gateway
    • legacy scalar GATEWAY / GATEWAY6 lookup for br0 and bond0
    • CRLF network.cfg import through fromdos
    • sourcing a config containing other associative fields such as IPADDR[0,1] and USE_DHCP[1,1]
  • Repeated helper tests on root@unraid.local using its real Bash/fromdos environment.
  • On root@unraid.local, waited for Docker startup after the array was unlocked, then reproduced the missing-default-route case with temporary VLAN interfaces and verified Docker network creation used the configured gateway:
    • default route gateway was empty
    • configured gateway resolved to 192.0.2.254 and Docker inspect reported gateway=192.0.2.254
    • repeated across both Docker drivers with ipvlan and macvlan; each reported gateway=192.0.3.254
  • Configured a real UniFi VLAN 30 on root@unraid.local as br0.30 using DHCP with route metric 999:
    • br0.30 received 192.168.30.166/24 from gateway 192.168.30.1
    • installed this PR version of rc.docker on the dev server and ran /etc/rc.d/rc.docker restart
    • Docker created br0.30 as macvlan with parent br0.30, subnet 192.168.30.0/24, gateway 192.168.30.1, and aux address server=192.168.30.166
    • existing containers restarted and health checks settled with no unhealthy containers
  • Validated the WebGUI/Dockerman template path for the exact bug scenario with DOCKER_USER_NETWORKS="remove":
    • created a temporary saved template my-codex-vlan30-webgui.xml with <Network>br0.30</Network>, <MyIP>192.168.30.250</MyIP>, and fixed <MyMAC>
    • rebuilt it through /usr/local/emhttp/plugins/dynamix.docker.manager/scripts/rebuild_container, which uses the same template-to-command code as the Docker WebGUI
    • confirmed the container started on br0.30 with IP 192.168.30.250 and MAC 02:42:c0:a8:1e:fa, and could ping 192.168.30.1
    • ran /etc/rc.d/rc.docker restart; br0.30 network ID changed from ace392... to b5f728..., proving it was removed and recreated rather than preserved
    • confirmed the WebGUI-template container reconnected to recreated br0.30 with the same IP/MAC and could still ping 192.168.30.1
    • removed the temporary container/template/autostart entry afterward
  • Repeated the real UniFi VLAN 30 WebGUI-template validation with Docker custom networks set to ipvlan (DOCKER_NETWORK_TYPE="1"):
    • br0.30 was recreated as ipvlan with gateway 192.168.30.1
    • fixed-MAC templates are not valid on ipvlan; Docker correctly rejected that with ipvlan interfaces do not support custom mac address assignment
    • using the valid ipvlan case (<MyIP>192.168.30.250</MyIP> and empty <MyMAC/>), the WebGUI-template container started on br0.30 and could ping 192.168.30.1
    • ran /etc/rc.d/rc.docker restart; br0.30 was removed/recreated as ipvlan, rc.docker logged connecting codex-vlan30-webgui-ipvlan-ip to network br0.30, and the container reconnected with 192.168.30.250/24 and could still ping 192.168.30.1
    • while switching this dev server from macvlan to ipvlan, stale macvlan host-access shim links had to be removed so they could be recreated as ipvlan; otherwise Docker reported failed to create the ipvlan port: device or resource busy. This appears independent of the gateway fallback change.
    • restored the server to its original macvlan Docker setting afterward and confirmed no unhealthy or starting containers remained
  • Temporarily restored the pre-PR rc.docker on root@unraid.local to validate the negative path:
    • with a temporary VLAN interface, configured gateway 198.51.100.254, and no live default route, the pre-PR logic produced no --gateway argument
    • Docker created the macvlan network with Gateway=invalid IP, reproducing the missing-gateway failure path
    • restored the PR rc.docker and reran the same setup; configured_gateway resolved 198.51.100.254, Docker was created with --gateway=198.51.100.254, and inspect reported gateway=198.51.100.254
  • Confirmed no temporary codex-gw* Docker networks or interfaces remained after validation.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 313fe8c0-4bcb-484d-afb2-a9df4b3d0883

📥 Commits

Reviewing files that changed from the base of the PR and between be65432 and d56c259.

📒 Files selected for processing (1)
  • etc/rc.d/rc.docker
🚧 Files skipped from review as they are similar to previous changes (1)
  • etc/rc.d/rc.docker

Walkthrough

Adds a bash helper, configured_gateway(), which parses /boot/config/network.cfg (VLAN-aware) to return configured IPv4/IPv6 gateway values; docker_network_start now uses it as a fallback to populate GATEWAY/GATEWAY6 when routing-derived values are empty during automatic custom-network creation.

Changes

Docker Custom Network Gateway Configuration

Layer / File(s) Summary
Gateway configuration helper
etc/rc.d/rc.docker
Adds configured_gateway() that parses $(NETWORK_CFG:-/boot/config/network.cfg) and returns configured GATEWAY or GATEWAY6 for a given Docker network name, supporting VLAN-qualified names.
Custom-network gateway fallback
etc/rc.d/rc.docker
docker_network_start calls configured_gateway("$NETWORK", GATEWAY) and configured_gateway("$NETWORK", GATEWAY6) to populate IPv4 GATEWAY and IPv6 GATEWAY6 when routing-derived values are empty before invoking docker network create.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nibble through configs under moonlit log,

I find the gateway hidden in the fog,
When routes are shy and pathways thin,
I hop in place to guide them in,
VLAN or bridge — a rabbit’s small nod to win.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding configured gateway fallback support for VLAN networks in Docker. It directly relates to the core purpose of the PR which is fixing Docker custom network creation for VLANs by using configured gateways.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/docker-vlan-gateway-fallback

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 11, 2026

🔧 PR Test Plugin Available

A test plugin has been generated for this PR that includes the modified files.

Version: 2026.05.12.1707
Build: View Workflow Run

📥 Installation Instructions:

Install via Unraid Web UI:

  1. Go to Plugins → Install Plugin
  2. Copy and paste this URL:
https://preview.dl.unraid.net/pr-plugins/pr-2634/webgui-pr-2634.plg
  1. Click Install

Alternative: Direct Download

⚠️ Important Notes:

  • Testing only: This plugin is for testing PR changes
  • Backup included: Original files are automatically backed up
  • Easy removal: Files are restored when plugin is removed
  • Conflicts: Remove this plugin before installing production updates
  • Post-merge behavior: This preview stays available after merge until preview storage expires or it is manually cleaned up

📝 Modified Files:

Click to expand file list
etc/rc.d/rc.docker

🔄 To Remove:

Navigate to Plugins → Installed Plugins and remove webgui-pr-2634, or run:

plugin remove webgui-pr-2634

🤖 This comment is automatically generated and will be updated with each new push to this PR.

@elibosley elibosley force-pushed the codex/docker-vlan-gateway-fallback branch from f9dc3d2 to be65432 Compare May 12, 2026 15:01
@elibosley elibosley marked this pull request as ready for review May 12, 2026 16:49
@elibosley elibosley added the 7.3 label May 12, 2026
- Purpose: keep Docker custom networks on VLAN and secondary interfaces from losing their configured gateway during automatic network recreation.

- Before: rc.docker only read the gateway from a default route on the interface, so VLANs without an interface-specific default route created Docker networks without --gateway.

- Why that was a problem: Docker could claim the first subnet address as the macvlan/ipvlan gateway, colliding with real VLAN gateways such as 192.168.10.1 and breaking DHCP or static-IP containers.

- What the new change accomplishes: automatic Docker network creation now falls back to the configured IPv4 or IPv6 gateway stored in network.ini when no live default route exists.

- How it works: configured_gateway maps br/bond network names back to their eth network.ini section, resolves VLAN IDs to their indexed entries, and returns the matching GATEWAY or GATEWAY6 value before network create arguments are assembled.
@elibosley elibosley force-pushed the codex/docker-vlan-gateway-fallback branch from be65432 to d56c259 Compare May 12, 2026 17:07
@limetech limetech merged commit 98cf9f9 into master May 12, 2026
5 checks passed
@limetech limetech deleted the codex/docker-vlan-gateway-fallback branch May 12, 2026 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants