HH-776: gracefully stop managed browser containers (#15)

This commit is contained in:
2026-08-28 19:22:22 +08:00
parent d57fa68866
commit 0b9808705d
2 changed files with 149 additions and 16 deletions
+36 -16
View File
@@ -128,7 +128,7 @@ docker compose config --quiet
docker compose up --detach --build
```
数据库迁移只支持安全前进,不提供自动破坏性回滚。需要同时恢复旧代码和更新前数据库时,修改下面两个变量后**整块执行一次**;不要逐行或拆块执行。预检、恢复演练、动态容器回收、停服、主库恢复、提交切换和启动都位于同一个 fail-fast subshell 中。
数据库迁移只支持安全前进,不提供自动破坏性回滚。需要同时恢复旧代码和更新前数据库时,修改下面两个变量后**整块执行一次**;不要逐行或拆块执行。预检、恢复演练、动态容器停止、停服、主库恢复、提交切换和启动都位于同一个 fail-fast subshell 中。
```bash
(
@@ -159,11 +159,22 @@ docker compose up --detach --build
docker compose exec -T postgres \
dropdb --force -U creatorhub creatorhub_restore_check
docker ps --all --quiet \
--filter 'name=^creatorhub-browser-' \
--filter 'label=io.creatorhub.managed=true' \
--filter 'label=io.creatorhub.runtime-id' \
| xargs --no-run-if-empty docker rm --force
list_running_browsers() {
docker ps --quiet \
--filter 'name=^creatorhub-browser-' \
--filter 'label=io.creatorhub.managed=true' \
--filter 'label=io.creatorhub.runtime-id'
}
browser_ids="$(list_running_browsers)" || exit 1
for browser_id in $browser_ids; do
if ! docker stop "$browser_id"; then
docker rm --force "$browser_id"
fi
done
browser_ids="$(list_running_browsers)" || exit 1
test -z "$browser_ids"
docker compose stop creator-hub docker-gateway
umask 077
@@ -205,18 +216,27 @@ docker compose up --detach --build
## 停止与数据保留
`docker compose stop/down` 不管理网关动态创建的浏览器容器;直接执行会留下运行中的浏览器和活动会话。先严格按固定容器名前缀及两个管理标签筛选并回收,命令不带 `--volumes`,因此 Profile 卷仍会保留:
`docker compose stop/down` 不管理网关动态创建的浏览器容器;直接执行会留下运行中的浏览器和活动会话。先严格按固定容器名前缀及两个管理标签筛选并停止;只有单个容器停止失败或超时时才强制删除。命令不带 `--volumes`,因此 Profile 卷仍会保留:
```bash
docker ps --all --quiet \
--filter 'name=^creatorhub-browser-' \
--filter 'label=io.creatorhub.managed=true' \
--filter 'label=io.creatorhub.runtime-id' \
| xargs --no-run-if-empty docker rm --force
test -z "$(docker ps --all --quiet \
--filter 'name=^creatorhub-browser-' \
--filter 'label=io.creatorhub.managed=true' \
--filter 'label=io.creatorhub.runtime-id')"
set -Eeuo pipefail
list_running_browsers() {
docker ps --quiet \
--filter 'name=^creatorhub-browser-' \
--filter 'label=io.creatorhub.managed=true' \
--filter 'label=io.creatorhub.runtime-id'
}
browser_ids="$(list_running_browsers)" || exit 1
for browser_id in $browser_ids; do
if ! docker stop "$browser_id"; then
docker rm --force "$browser_id"
fi
done
browser_ids="$(list_running_browsers)" || exit 1
test -z "$browser_ids"
docker compose stop
```
+113
View File
@@ -0,0 +1,113 @@
#!/usr/bin/env bash
set -Eeuo pipefail
cd "$(dirname "$0")/.."
extract_block() {
awk -v wanted="$1" '
/^```bash$/ {
in_code = 1
strict = ""
wrapper = ""
next
}
in_code && /^\($/ { wrapper = $0 }
in_code && /^[[:space:]]*set -Eeuo pipefail$/ { strict = $0 }
/^[[:space:]]*list_running_browsers\(\) \{/ {
count++
capture = count == wanted
if (capture) {
if (wrapper) print wrapper
print strict
}
}
capture { print }
capture && /^[[:space:]]*docker compose stop/ {
capture = 0
if (!wrapper) exit
closing = 1
}
closing && /^\)$/ { print; exit }
/^```$/ { in_code = 0 }
' docs/deployment.md
}
docker() {
printf '%s\n' "$*" >>"$calls"
case "$1" in
ps)
[[ "$*" == 'ps --quiet --filter name=^creatorhub-browser- --filter label=io.creatorhub.managed=true --filter label=io.creatorhub.runtime-id' ]] || return 64
query_count=0
[[ ! -e "$state/query-count" ]] || read -r query_count <"$state/query-count"
((query_count += 1))
printf '%s\n' "$query_count" >"$state/query-count"
[[ "$mode:$query_count" != query_failure:1 && "$mode:$query_count" != recheck_failure:2 ]] || return 42
[[ -e "$state/stopped" || -e "$state/removed" ]] || printf '%s\n' browser-1
;;
stop)
case "$mode" in
stop_success) : >"$state/stopped" ;;
stop_failure) return 1 ;;
stop_timeout) return 124 ;;
esac
;;
rm)
[[ "$*" == 'rm --force browser-1' ]] || return 64
: >"$state/removed"
;;
compose)
[[ "$*" == 'compose stop' || "$*" == 'compose stop creator-hub docker-gateway' ]] || return 64
;;
esac
}
export -f docker
work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT
query='ps --quiet --filter name=^creatorhub-browser- --filter label=io.creatorhub.managed=true --filter label=io.creatorhub.runtime-id'
scenario_count=0
for block_number in 1 2; do
block="$(extract_block "$block_number")"
bash -n <<<"$block"
[[ "$block" == *'set -Eeuo pipefail'* ]]
if [[ $block_number -eq 1 ]]; then
[[ "${block%%$'\n'*}" == '(' && "${block##*$'\n'}" == ')' ]]
compose='compose stop creator-hub docker-gateway'
else
[[ "${block%%$'\n'*}" == 'set -Eeuo pipefail' ]]
compose='compose stop'
fi
for mode in stop_success stop_failure stop_timeout query_failure recheck_failure; do
state="$work/$block_number-$mode"
calls="$state/calls"
mkdir "$state"
export mode state calls
status=0
bash -c "$block" || status=$?
case "$mode" in
stop_success)
[[ $status -eq 0 ]]
diff -u <(printf '%s\n' "$query" 'stop browser-1' "$query" "$compose") "$calls"
;;
stop_failure | stop_timeout)
[[ $status -eq 0 ]]
diff -u <(printf '%s\n' "$query" 'stop browser-1' 'rm --force browser-1' "$query" "$compose") "$calls"
;;
query_failure)
[[ $status -eq 1 ]]
diff -u <(printf '%s\n' "$query") "$calls"
;;
recheck_failure)
[[ $status -eq 1 ]]
diff -u <(printf '%s\n' "$query" 'stop browser-1' "$query") "$calls"
;;
esac
scenario_count=$((scenario_count + 1))
done
done
[[ $scenario_count -eq 10 ]]