fix(web): refresh API proxy DNS after backend redeploy

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
XiaoSeS 2026-09-23 11:01:24 +08:00
parent ed2ff97d00
commit 353e9025cc
5 changed files with 92 additions and 6 deletions

View file

@ -70,6 +70,7 @@ services:
- ./web/dist:/usr/share/nginx/html:ro
- ./web/nginx.conf.template:/etc/nginx/templates/default.conf.template:ro
environment:
NGINX_ENTRYPOINT_LOCAL_RESOLVERS: "1"
SKILLHUB_API_UPSTREAM: http://server:8080
SKILLHUB_WEB_API_BASE_URL: ""
SKILLHUB_PUBLIC_BASE_URL: ""

View file

@ -42,10 +42,12 @@ wait_for_nginx() {
start_proxy() {
local container="$1"
local trust_forwarded_proto="$2"
local backend_name="${3:-$BACKEND}"
docker run --detach \
--name "$container" \
--network "$NETWORK" \
--env "SKILLHUB_API_UPSTREAM=http://$BACKEND:8080" \
--env "NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1" \
--env "SKILLHUB_API_UPSTREAM=http://$backend_name:8080" \
--env "SKILLHUB_TRUST_FORWARDED_PROTO=$trust_forwarded_proto" \
--volume "$TEMPLATE:/etc/nginx/templates/default.conf.template:ro" \
"$NGINX_IMAGE" >/dev/null
@ -98,4 +100,80 @@ done
assert_proto "$TRUSTED_PROXY" http
assert_proto "$TRUSTED_PROXY" http "https,http"
echo "nginx-forwarded-proto-test passed"
DNS_BACKEND="${TEST_ID}-dns-backend"
DNS_OLD_BACKEND="${TEST_ID}-dns-old"
DNS_NEW_BACKEND="${TEST_ID}-dns-new"
DNS_STALE_BACKEND="${TEST_ID}-dns-stale"
DNS_PROXY="${TEST_ID}-dns-proxy"
start_dns_backend() {
local container="$1"
local response="$2"
local alias="${3:-}"
local static_ip="${4:-}"
local config="$TMP_DIR/$container.conf"
cat >"$config" <<EOF
server {
listen 8080;
location / {
default_type text/plain;
return 200 "$response";
}
}
EOF
local alias_args=()
local ip_args=()
if [[ -n "$alias" ]]; then
alias_args+=(--network-alias "$alias")
fi
if [[ -n "$static_ip" ]]; then
ip_args+=(--ip "$static_ip")
fi
docker run --detach \
--name "$container" \
--network "$NETWORK" \
"${alias_args[@]}" \
"${ip_args[@]}" \
--volume "$config:/etc/nginx/conf.d/default.conf:ro" \
"$NGINX_IMAGE" >/dev/null
CONTAINERS+=("$container")
}
container_ip() {
docker inspect --format "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" "$1"
}
start_dns_backend "$DNS_OLD_BACKEND" first "$DNS_BACKEND"
start_proxy "$DNS_PROXY" false "$DNS_BACKEND"
assert_dns_response() {
local expected="$1"
local actual
actual="$(docker exec "$DNS_PROXY" wget -qO- http://127.0.0.1/api/dns)" \
|| fail "DNS proxy request failed; expected '$expected'"
[[ "$actual" == "$expected" ]] \
|| fail "DNS proxy returned '$actual', expected '$expected'"
}
assert_dns_response first
old_ip="$(container_ip "$DNS_OLD_BACKEND")"
docker rm -f "$DNS_OLD_BACKEND" >/dev/null
start_dns_backend "$DNS_STALE_BACKEND" stale "" "$old_ip"
start_dns_backend "$DNS_NEW_BACKEND" second "$DNS_BACKEND"
new_ip="$(container_ip "$DNS_NEW_BACKEND")"
[[ "$old_ip" != "$new_ip" ]] || fail "replacement backend reused old IP $old_ip"
refreshed=false
for attempt in {1..36}; do
if actual="$(docker exec "$DNS_PROXY" wget -qO- http://127.0.0.1/api/dns 2>/dev/null)" \
&& [[ "$actual" == second ]]; then
refreshed=true
break
fi
sleep 0.5
done
[[ "$refreshed" == true ]] \
|| { docker logs "$DNS_PROXY" >&2 || true; fail "unchanged proxy did not reach replacement backend $new_ip"; }
echo "nginx-forwarded-proto-test passed, including DNS refresh ($old_ip -> $new_ip)"

View file

@ -41,6 +41,7 @@ chmod +x "$entrypoint_d/20-base-path.sh" "$entrypoint_d/30-runtime-config.sh"
if ! docker run -d --name "$name" \
-p "$port:80" \
-e NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1 \
-e SKILLHUB_API_UPSTREAM=http://127.0.0.1:9 \
-e SKILLHUB_TRUST_FORWARDED_PROTO=false \
-e SKILLHUB_WEB_BASE_PATH=/skillhub/ \
@ -154,6 +155,7 @@ name_default="$name-default"
port_default=18082
docker run -d --name "$name_default" \
-p "$port_default:80" \
-e NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1 \
-e SKILLHUB_API_UPSTREAM=http://127.0.0.1:9 \
-e SKILLHUB_TRUST_FORWARDED_PROTO=false \
-e SKILLHUB_WEB_BASE_PATH=/skillhub/ \
@ -206,6 +208,7 @@ name_trusted="$name-trusted"
port_trusted=18083
docker run -d --name "$name_trusted" \
-p "$port_trusted:80" \
-e NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1 \
-e SKILLHUB_API_UPSTREAM=http://127.0.0.1:9 \
-e SKILLHUB_TRUST_FORWARDED_PROTO=true \
-e SKILLHUB_WEB_BASE_PATH=/skillhub/ \
@ -246,6 +249,7 @@ fixed_port=18081
docker run -d --name "$fixed_name" \
-p "$fixed_port:80" \
-e NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1 \
-e SKILLHUB_API_UPSTREAM=http://127.0.0.1:9 \
-e SKILLHUB_TRUST_FORWARDED_PROTO=false \
-e SKILLHUB_WEB_BASE_PATH= \

View file

@ -13,6 +13,7 @@ RUN pnpm build
FROM nginx:alpine
ENV SKILLHUB_TRUST_FORWARDED_PROTO=false
ENV NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1
# Record a fixed build-time base so the entrypoint defaults SKILLHUB_WEB_BASE_PATH
# to it and generates matching Nginx routing without repeating the value at runtime.
# Placeholder builds (the default) intentionally write no file and default to '/'.

View file

@ -2,6 +2,8 @@ server_tokens off;
server {
listen 80;
server_name _;
resolver ${NGINX_LOCAL_RESOLVERS} valid=10s;
set $skillhub_api_upstream "${SKILLHUB_API_UPSTREAM}";
root /usr/share/nginx/html;
index index.html;
@ -34,7 +36,7 @@ server {
}
location /api/ {
proxy_pass ${SKILLHUB_API_UPSTREAM};
proxy_pass $skillhub_api_upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@ -43,7 +45,7 @@ server {
}
location /oauth2/ {
proxy_pass ${SKILLHUB_API_UPSTREAM};
proxy_pass $skillhub_api_upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@ -52,7 +54,7 @@ server {
}
location /login/oauth2/ {
proxy_pass ${SKILLHUB_API_UPSTREAM};
proxy_pass $skillhub_api_upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@ -61,7 +63,7 @@ server {
}
location /.well-known/ {
proxy_pass ${SKILLHUB_API_UPSTREAM};
proxy_pass $skillhub_api_upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;