Skip to content

Commit d56c259

Browse files
committed
fix(docker): use configured gateways for VLAN networks
- 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.
1 parent 373651a commit d56c259

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

etc/rc.d/rc.docker

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,51 @@ network(){
210210
docker network ls --filter driver="$1" --format='{{.Name}}' 2>/dev/null | grep -P "^[a-z]+$2(\$|\.)" | tr '\n' ' '
211211
}
212212

213+
configured_gateway(){
214+
local NETWORK=$1
215+
local KEY=$2
216+
local CFG=${NETWORK_CFG:-/boot/config/network.cfg}
217+
[[ -s $CFG ]] || return
218+
219+
(
220+
declare -A VLANID USE_DHCP IPADDR NETMASK GATEWAY METRIC USE_DHCP6 IPADDR6 NETMASK6 GATEWAY6 METRIC6 PRIVACY6 DESCRIPTION PROTOCOL
221+
local BASE=${NETWORK%%.*}
222+
local VLAN=
223+
local IFACE ETH VALUE
224+
local CANDIDATE
225+
local -a CANDIDATES
226+
local i j
227+
228+
[[ $NETWORK == *.* ]] && VLAN=${NETWORK#*.}
229+
. <(fromdos <"$CFG")
230+
231+
for ((i=0; i<${SYSNICS:-1}; i++)); do
232+
IFACE=${IFNAME[$i]:-eth$i}
233+
ETH=${IFACE/#br/eth}
234+
ETH=${ETH/#bond/eth}
235+
CANDIDATES=("$IFACE" "$ETH" "${BRNAME[$i]}" "${BONDNAME[$i]}")
236+
if [[ $i -eq 0 ]]; then
237+
[[ ${BRIDGING:-} == yes ]] && CANDIDATES+=("br0")
238+
[[ ${BONDING:-} == yes ]] && CANDIDATES+=("bond0")
239+
fi
240+
for CANDIDATE in "${CANDIDATES[@]}"; do
241+
[[ -n $CANDIDATE && $CANDIDATE == "$BASE" ]] || continue
242+
if [[ -z $VLAN ]]; then
243+
[[ $KEY == GATEWAY6 ]] && VALUE=${GATEWAY6[$i]} || VALUE=${GATEWAY[$i]}
244+
[[ -n $VALUE ]] && printf '%s\n' "$VALUE"
245+
exit
246+
fi
247+
for ((j=1; j<${VLANS[$i]:-0}; j++)); do
248+
[[ ${VLANID[$i,$j]} == "$VLAN" ]] || continue
249+
[[ $KEY == GATEWAY6 ]] && VALUE=${GATEWAY6[$i,$j]} || VALUE=${GATEWAY[$i,$j]}
250+
[[ -n $VALUE ]] && printf '%s\n' "$VALUE"
251+
exit
252+
done
253+
done
254+
done
255+
)
256+
}
257+
213258
# Is container running?
214259
container_running(){
215260
local CONTAINER
@@ -470,6 +515,7 @@ docker_network_start(){
470515
if [[ -n $IPV4 ]]; then
471516
SUBNET=$(ip -4 route show dev $NETWORK | sort | awk -v ORS=" " '$1 !~ /^default/ {print $1}' | sed 's/ $//')
472517
GATEWAY=$(ip -4 route show to default dev $NETWORK | awk '{print $3;exit}')
518+
[[ -n $GATEWAY ]] || GATEWAY=$(configured_gateway "$NETWORK" GATEWAY)
473519
SERVER=${IPV4%/*}
474520
DHCP=${NETWORK/./_}
475521
DHCP=DOCKER_DHCP_${DHCP^^}
@@ -481,6 +527,7 @@ docker_network_start(){
481527
if [[ -n $IPV6 ]]; then
482528
SUBNET6=$(ip -6 route show dev $NETWORK | sort | awk -v ORS=" " '$1 !~ /^(default|fe80)/ {print $1}' | sed 's/ $//')
483529
GATEWAY6=$(ip -6 route show to default dev $NETWORK | awk '{print $3;exit}')
530+
[[ -n $GATEWAY6 ]] || GATEWAY6=$(configured_gateway "$NETWORK" GATEWAY6)
484531
fi
485532
else
486533
# add user defined networks

0 commit comments

Comments
 (0)