From 7bdf760c7b3bff45d8cceac16d4bc2e2eb365743 Mon Sep 17 00:00:00 2001 From: YoursFunny Date: Thu, 24 Sep 2026 03:47:34 +0800 Subject: [PATCH] ops(compose): align the deploy template defaults and gate the healthcheck MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two template landmines for anyone running docker compose from the tracked files. (1) LOCAL_USER_ID defaulted to 1000 in compose and .env.example while the entrypoint and both READMEs say 9001 — the ./data owner on the host silently depended on which doc you read; all four now say 9001. (2) The healthcheck probed WEBHOOK_PORT unconditionally, so the template's own WEBHOOK=false (polling, no listener) shipped a permanently unhealthy container — the probe is now conditional on the interpolated WEBHOOK value (test '' != true || exec 3<>/dev/tcp/…): polling deployments answer healthy without a port, webhook deployments still surface a dead listener to the orchestrator. Both expressions verified locally; compose YAML parses. --- .env.example | 5 ++++- docker-compose.yml | 11 ++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.env.example b/.env.example index ed49f09..0bd3ab6 100644 --- a/.env.example +++ b/.env.example @@ -49,6 +49,7 @@ DATA_DIR=data # --- webhook deployment (docker-compose.yml) ------------------------------ # false = long polling (no public URL needed). true = webhook behind the # bundled nginx-proxy — and then WEBHOOK_LISTEN/PORT/URL are required. +# The compose healthcheck probes the listener only when this is true. WEBHOOK=false # WEBHOOK_LISTEN=0.0.0.0 # WEBHOOK_PORT=8443 @@ -70,7 +71,9 @@ VIRTUAL_PORT=8443 # Certificate notification address for acme-companion. DEFAULT_EMAIL= # UID the container runs as; it must be able to write ./data on the host. -LOCAL_USER_ID=1000 +# The entrypoint's default (and the README's) is 9001 — keep them equal so +# the file owner on the host matches what you expect. +LOCAL_USER_ID=9001 # Uncomment (here and the matching line in docker-compose.yml) to have # acme-companion issue the certificate for VIRTUAL_HOST. # ACME_HOST= diff --git a/docker-compose.yml b/docker-compose.yml index 8832f74..ef57d38 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -64,7 +64,7 @@ services: WEBHOOK_URL: '${WEBHOOK_URL:-}' WEBHOOK_SECRET_TOKEN: '${WEBHOOK_SECRET_TOKEN:-}' # Defaults, listed so they are discoverable; override in .env when needed. - LOCAL_USER_ID: '${LOCAL_USER_ID:-1000}' + LOCAL_USER_ID: '${LOCAL_USER_ID:-9001}' RUST_LOG: '${RUST_LOG:-info}' EDIT_MESSAGE_TTL_SECONDS: '${EDIT_MESSAGE_TTL_SECONDS:-86400}' LINK_CACHE_TTL_SECONDS: '${LINK_CACHE_TTL_SECONDS:-604800}' @@ -88,11 +88,12 @@ services: - nginx-proxy container_name: tgxmb logging: *default-logging - # Webhook mode only (in polling mode there is no listener, so drop this - # block or set WEBHOOK=true): the bot listens on WEBHOOK_PORT; nginx-proxy - # shows 502s while this is down, so surface it to the orchestrator. + # Probes the listener only when WEBHOOK=true (compose interpolates the + # value from .env); a polling deployment has no listener and must not be + # reported unhealthy. nginx-proxy shows 502s while webhook mode is down, + # so surface that to the orchestrator. healthcheck: - test: ["CMD-SHELL", "bash -c 'exec 3<>/dev/tcp/127.0.0.1/${WEBHOOK_PORT:-8443}'"] + test: ["CMD-SHELL", "test '${WEBHOOK:-true}' != true || exec 3<>/dev/tcp/127.0.0.1/${WEBHOOK_PORT:-8443}"] interval: 30s timeout: 5s retries: 3