blob: 68a40dea923b3c398839ef5c0980f06f684350df [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001#!/bin/sh /etc/rc.common
2
3USE_PROCD=1
4START=99
5
6extra_command "uciadd" "<interface> <device> <zone> Add docker bridge configuration to network and firewall uci config"
7extra_command "ucidel" "<interface> <device> <zone> Delete docker bridge configuration from network and firewall uci config"
8
9DOCKER_CONF_DIR="/tmp/dockerd"
10DOCKERD_CONF="${DOCKER_CONF_DIR}/daemon.json"
11
12uci_quiet() {
13 uci -q "${@}" >/dev/null
14}
15
16json_add_array_string() {
17 json_add_string "" "${1}"
18}
19
20find_network_device() {
21 local device="${1}"
22 local device_section=""
23
24 check_device() {
25 local cfg="${1}"
26 local device="${2}"
27
28 local type name
29 config_get type "${cfg}" type
30 config_get name "${cfg}" name
31
32 [ "${type}" = "bridge" ] && [ "${name}" = "${device}" ] \
33 && device_section="${cfg}"
34 }
35
36 config_load network
37 config_foreach check_device device "${device}"
38
39 echo "${device_section}"
40}
41
42boot() {
43 uciadd
44 rc_procd start_service
45}
46
47uciadd() {
48 local iface="${1}"
49 local device="${2}"
50 local zone="${3}"
51
52 [ -z "${iface}" ] && {
53 iface="docker"
54 device="docker0"
55 zone="docker"
56 }
57
58 /etc/init.d/dockerd running && {
59 echo "Please stop dockerd service first"
60 exit 0
61 }
62
63 # Add network interface
64 if ! uci_quiet get network.${iface}; then
65 logger -t "dockerd-init" -p notice "Adding interface '${iface}' to network config"
66 uci_quiet add network interface
67 uci_quiet rename network.@interface[-1]="${iface}"
68 uci_quiet set network.@interface[-1].device="${device}"
69 uci_quiet set network.@interface[-1].proto="none"
70 uci_quiet set network.@interface[-1].auto="0"
71 uci_quiet commit network
72 fi
73
74 # Add docker bridge device
75 if [ "$(find_network_device "$device")" = "" ]; then
76 logger -t "dockerd-init" -p notice "Adding bridge device '${device}' to network config"
77 uci_quiet add network device
78 uci_quiet set network.@device[-1].type="bridge"
79 uci_quiet set network.@device[-1].name="${device}"
80 uci_quiet commit network
81 else
82 logger -t "dockerd-init" -p notice "Bridge device '${device}' already defined in network config"
83 fi
84
85 # Add firewall zone
86 if ! uci_quiet get firewall.${zone}; then
87 logger -t "dockerd-init" -p notice "Adding firewall zone '${zone}' to firewall config"
88 uci_quiet add firewall zone
89 uci_quiet rename firewall.@zone[-1]="${zone}"
90 uci_quiet set firewall.@zone[-1].input="ACCEPT"
91 uci_quiet set firewall.@zone[-1].output="ACCEPT"
92 uci_quiet set firewall.@zone[-1].forward="ACCEPT"
93 uci_quiet set firewall.@zone[-1].name="${zone}"
94 uci_quiet commit firewall
95 fi
96
97 # Add interface to firewall zone
98 if uci_quiet get firewall.${zone}; then
99 uci_quiet del_list firewall.${zone}.network="${iface}"
100 uci_quiet add_list firewall.${zone}.network="${iface}"
101 uci_quiet commit firewall
102 fi
103
104 reload_config
105}
106
107ucidel() {
108 local iface="${1}"
109 local device="${2}"
110 local zone="${3}"
111
112 [ -z "${iface}" ] && {
113 iface="docker"
114 device="docker0"
115 zone="docker"
116 }
117
118 /etc/init.d/dockerd running && {
119 echo "Please stop dockerd service first"
120 exit 0
121 }
122
123 # Remove network device
124 if uci_quiet delete network.$(find_network_device "${device}"); then
125 logger -t "dockerd-init" -p notice "Deleting bridge device '${device}' from network config"
126 uci_quiet commit network
127 fi
128
129 # Remove network interface
130 if uci_quiet get network.${iface}; then
131 logger -t "dockerd-init" -p notice "Deleting interface '${iface}' from network config"
132 uci_quiet delete network.${iface}
133 uci_quiet commit network
134 fi
135
136 # Remove interface from firewall zone
137 if uci_quiet get firewall.${zone}; then
138 logger -t "dockerd-init" -p notice "Deleting network interface '${iface}' in zone '${zone}' from firewall config"
139 uci_quiet del_list firewall.${zone}.network="${iface}"
140 uci_quiet commit firewall
141 # Remove Firewall zone if network is empty
142 if ! uci_quiet get firewall.${zone}.network; then
143 logger -t "dockerd-init" -p notice "Deleting firewall zone '${zone}' from firewall config"
144 uci_quiet delete firewall.${zone}
145 fi
146 uci_quiet commit firewall
147 fi
148
149 reload_config
150}
151
152process_config() {
153 local alt_config_file data_root log_level iptables bip
154
155 [ -f /etc/config/dockerd ] || {
156 # Use the daemon default configuration
157 DOCKERD_CONF=""
158 return 0
159 }
160
161 # reset configuration
162 rm -fr "${DOCKER_CONF_DIR}"
163 mkdir -p "${DOCKER_CONF_DIR}"
164
165 config_load 'dockerd'
166 config_get alt_config_file globals alt_config_file
167 [ -n "${alt_config_file}" ] && [ -f "${alt_config_file}" ] && {
168 ln -s "${alt_config_file}" "${DOCKERD_CONF}"
169 return 0
170 }
171
172 config_get data_root globals data_root "/opt/docker/"
173 config_get log_level globals log_level "warn"
174 config_get_bool iptables globals iptables "1"
175
176 # Don't add these options by default
177 # omission == docker defaults
178 config_get bip globals bip ""
179 config_get registry_mirrors globals registry_mirrors ""
180 config_get hosts globals hosts ""
181 config_get dns globals dns ""
182 config_get_bool ipv6 globals ipv6 ""
183 config_get ip globals ip ""
184 config_get fixed_cidr globals fixed_cidr ""
185 config_get fixed_cidr_v6 globals fixed_cidr_v6 ""
186
187 . /usr/share/libubox/jshn.sh
188 json_init
189 json_add_string "data-root" "${data_root}"
190 json_add_string "log-level" "${log_level}"
191 json_add_boolean "iptables" "${iptables}"
192 [ -z "${bip}" ] || json_add_string "bip" "${bip}"
193 [ -z "${registry_mirrors}" ] || json_add_array "registry-mirrors"
194 [ -z "${registry_mirrors}" ] || config_list_foreach globals registry_mirrors json_add_array_string
195 [ -z "${registry_mirrors}" ] || json_close_array
196 [ -z "${hosts}" ] || json_add_array "hosts"
197 [ -z "${hosts}" ] || config_list_foreach globals hosts json_add_array_string
198 [ -z "${hosts}" ] || json_close_array
199 [ -z "${dns}" ] || json_add_array "dns"
200 [ -z "${dns}" ] || config_list_foreach globals dns json_add_array_string
201 [ -z "${dns}" ] || json_close_array
202 [ -z "${ipv6}" ] || json_add_boolean "ipv6" "${ipv6}"
203 [ -z "${ip}" ] || json_add_string "ip" "${ip}"
204 [ -z "${fixed_cidr}" ] || json_add_string "fixed-cidr" "${fixed_cidr}"
205 [ -z "${fixed_cidr_v6}" ] || json_add_string "fixed-cidr-v6" "${fixed_cidr_v6}"
206 json_dump > "${DOCKERD_CONF}"
207
208 [ "${iptables}" -eq "1" ] && config_foreach iptables_add_blocking_rule firewall
209}
210
211start_service() {
212 local nofile=$(cat /proc/sys/fs/nr_open)
213
214 process_config
215
216 procd_open_instance
217 procd_set_param stderr 1
218 if [ -z "${DOCKERD_CONF}" ]; then
219 procd_set_param command /usr/bin/dockerd
220 else
221 procd_set_param command /usr/bin/dockerd --config-file="${DOCKERD_CONF}"
222 fi
223 procd_set_param limits nofile="${nofile} ${nofile}"
224 procd_close_instance
225}
226
227reload_service() {
228 process_config
229 procd_send_signal dockerd
230}
231
232service_triggers() {
233 procd_add_reload_trigger 'dockerd'
234}
235
236iptables_add_blocking_rule() {
237 local cfg="${1}"
238
239 local device=""
240 local extra_iptables_args=""
241
242 handle_iptables_rule() {
243 local interface="${1}"
244 local outbound="${2}"
245 local extra_iptables_args="${3}"
246
247 local inbound=""
248
249 . /lib/functions/network.sh
250 network_get_physdev inbound "${interface}"
251
252 [ -z "${inbound}" ] && {
253 logger -t "dockerd-init" -p notice "Unable to get physical device for interface ${interface}"
254 return
255 }
256
257 # Wait for a maximum of 10 second per command, retrying every millisecond
258 local iptables_wait_args="--wait 10 --wait-interval 1000"
259
260 # Ignore errors as it might already be present
261 iptables ${iptables_wait_args} --table filter --new DOCKER-USER 2>/dev/null
262 if ! iptables ${iptables_wait_args} --table filter --check DOCKER-USER --in-interface "${inbound}" --out-interface "${outbound}" ${extra_iptables_args} --jump REJECT 2>/dev/null; then
263 logger -t "dockerd-init" -p notice "Drop traffic from ${inbound} to ${outbound}"
264 iptables ${iptables_wait_args} --table filter --insert DOCKER-USER --in-interface "${inbound}" --out-interface "${outbound}" ${extra_iptables_args} --jump REJECT
265 fi
266 }
267
268 config_get device "${cfg}" device
269
270 [ -z "${device}" ] && {
271 logger -t "dockerd-init" -p notice "No device configured for ${cfg}"
272 return
273 }
274
275 config_get extra_iptables_args "${cfg}" extra_iptables_args
276 config_list_foreach "${cfg}" blocked_interfaces handle_iptables_rule "${device}" "${extra_iptables_args}"
277}
278
279stop_service() {
280 if /etc/init.d/dockerd running; then
281 service_stop "/usr/bin/dockerd"
282 fi
283}