From 94855bdd0b79046a54d1bd558cbfa4535242d853 Mon Sep 17 00:00:00 2001 From: CHANTXU64 Date: Tue, 2 Jun 2026 17:53:50 +0800 Subject: [PATCH] Add timezone defaults and server timezone display --- README.md | 1 + apps/src/app/settings/page.tsx | 13 ++++++-- .../src/app/settings/settings-page-helpers.ts | 16 ++++++++++ apps/src/lib/api/normalize.ts | 17 ++++++++++ apps/src/lib/i18n/messages/en.ts | 3 ++ apps/src/lib/i18n/messages/ko.ts | 3 ++ apps/src/lib/i18n/messages/ru.ts | 3 ++ apps/src/lib/store/useAppStore.ts | 5 +++ apps/src/types/settings.ts | 7 ++++ apps/tests/settings-page-helpers.test.mjs | 32 +++++++++++++++++++ .../service/src/app_settings/api/current.rs | 25 +++++++++++++++ crates/service/tests/app_settings.rs | 31 ++++++++++++++++++ docker-compose.yml | 1 + docker/Dockerfile.all-in-one | 4 ++- docker/Dockerfile.service | 4 ++- docker/Dockerfile.service.release | 4 ++- docker/Dockerfile.web | 4 ++- docker/Dockerfile.web.release | 4 ++- docker/docker-compose.all-in-one.yml | 1 + docker/docker-compose.release.yml | 2 ++ docker/docker-compose.yml | 2 ++ .../report/environment-and-runtime-config.md | 4 +++ .../en/report/runtime-and-deployment-guide.md | 4 +++ ...15\347\275\256\350\257\264\346\230\216.md" | 4 +++ ...50\347\275\262\346\214\207\345\215\227.md" | 4 +++ 25 files changed, 190 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0720f0dd1..824e491cd 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,7 @@ - macOS:`~/Library/Application Support/com.codexmanager.desktop/codexmanager.db` - Linux:`~/.local/share/com.codexmanager.desktop/codexmanager.db` - 如需调整数据库、代理、监听地址等运行配置,可继续查看 [环境变量与运行配置](docs/zh-CN/report/环境变量与运行配置说明.md)。 +- Docker 镜像默认使用 `TZ=Asia/Shanghai`;compose 示例会优先沿用部署环境里的 `TZ`,没有设置时回退到 `Asia/Shanghai`,其他地区部署时请改成对应 IANA 时区。 ## 页面展示 ### 桌面端 diff --git a/apps/src/app/settings/page.tsx b/apps/src/app/settings/page.tsx index 702007ce7..7a46b4344 100644 --- a/apps/src/app/settings/page.tsx +++ b/apps/src/app/settings/page.tsx @@ -103,6 +103,7 @@ import { compareEnvOverrideItems, ensureModelForwardRuleRows, formatFreeAccountModelLabel, + formatRuntimeTimeZoneLabel, inferServiceBindPreview, matchesRecommendedWorkerSettings, normalizeEnvRiskLevel, @@ -2069,9 +2070,15 @@ function AdminSettingsPage() {
- {snapshot.backgroundTasks.warmupCronEnabled - ? t("定时账号预热已启用") - : t("定时账号预热未启用。多个计划用 | 分隔。")} + {t( + "计划按服务端时区 {timeZone} 执行。多个计划用 | 分隔。", + { + timeZone: formatRuntimeTimeZoneLabel( + snapshot.runtimeTimeZone, + t("服务端本地时区"), + ), + }, + )}
diff --git a/apps/src/app/settings/settings-page-helpers.ts b/apps/src/app/settings/settings-page-helpers.ts index b21a974d9..ef3be2a3f 100644 --- a/apps/src/app/settings/settings-page-helpers.ts +++ b/apps/src/app/settings/settings-page-helpers.ts @@ -3,6 +3,7 @@ import type { AppSettings, BackgroundTaskSettings, EnvOverrideCatalogItem, + RuntimeTimeZone, } from "@/types"; export const ENV_DESCRIPTION_MAP: Record = { @@ -227,6 +228,21 @@ export function stringifyNumber(value: number | null | undefined): string { return value == null ? "" : String(value); } +export function formatRuntimeTimeZoneLabel( + runtimeTimeZone: RuntimeTimeZone | null | undefined, + localTimeZoneLabel = "服务端本地时区", +): string { + const name = String(runtimeTimeZone?.name || "").trim(); + const offset = String(runtimeTimeZone?.offset || "").trim(); + const displayName = + name && name !== "Local" ? name : localTimeZoneLabel; + const normalizedOffset = + offset && !offset.toUpperCase().startsWith("UTC") + ? `UTC${offset.startsWith("+") || offset.startsWith("-") ? offset : `+${offset}`}` + : offset; + return normalizedOffset ? `${displayName} (${normalizedOffset})` : displayName; +} + export function readNumberField( source: Record, key: string, diff --git a/apps/src/lib/api/normalize.ts b/apps/src/lib/api/normalize.ts index 809183fac..5fd363a71 100644 --- a/apps/src/lib/api/normalize.ts +++ b/apps/src/lib/api/normalize.ts @@ -18,6 +18,7 @@ import { AppSettings, BackgroundTaskSettings, QuotaGuardSettings, + RuntimeTimeZone, DeviceAuthInfo, EnvOverrideCatalogItem, InstalledPluginSummary, @@ -83,6 +84,12 @@ const DEFAULT_QUOTA_GUARD: QuotaGuardSettings = { allowAllLowQuotaFallback: true, }; +const DEFAULT_RUNTIME_TIME_ZONE: RuntimeTimeZone = { + name: "Local", + offset: "", + source: "system", +}; + /** * 函数 `asObject` * @@ -1697,6 +1704,15 @@ export function normalizeQuotaGuard(payload: unknown): QuotaGuardSettings { }; } +export function normalizeRuntimeTimeZone(payload: unknown): RuntimeTimeZone { + const source = asObject(payload); + return { + name: asString(source.name) || DEFAULT_RUNTIME_TIME_ZONE.name, + offset: asString(source.offset), + source: asString(source.source) || DEFAULT_RUNTIME_TIME_ZONE.source, + }; +} + export function normalizeEnvOverrideCatalog(payload: unknown): EnvOverrideCatalogItem[] { return asArray(payload).reduce((result, item) => { const source = asObject(item); @@ -1803,6 +1819,7 @@ export function normalizeAppSettings(payload: unknown): AppSettings { upstreamTotalTimeoutMs: asInteger(source.upstreamTotalTimeoutMs, 0, 0), sseKeepaliveIntervalMs: asInteger(source.sseKeepaliveIntervalMs, 15_000, 1), backgroundTasks: normalizeBackgroundTasks(source.backgroundTasks), + runtimeTimeZone: normalizeRuntimeTimeZone(source.runtimeTimeZone), envOverrides: normalizeStringRecord(source.envOverrides), envOverrideCatalog: normalizeEnvOverrideCatalog(source.envOverrideCatalog), envOverrideReservedKeys: asArray(source.envOverrideReservedKeys).map((item) => diff --git a/apps/src/lib/i18n/messages/en.ts b/apps/src/lib/i18n/messages/en.ts index 0419e71fe..bfefc6c22 100644 --- a/apps/src/lib/i18n/messages/en.ts +++ b/apps/src/lib/i18n/messages/en.ts @@ -558,6 +558,9 @@ export const EN_MESSAGES: MessageCatalog = { 网关保活线程: "Gateway keepalive worker", 令牌刷新轮询: "Token refresh polling", "Worker 并发参数": "Worker concurrency", + "计划按服务端时区 {timeZone} 执行。多个计划用 | 分隔。": + "Schedule runs in server time zone {timeZone}. Separate multiple schedules with |.", + 服务端本地时区: "Server local time zone", 当前档位: "Current preset", 自定义: "Custom", "搜索变量...": "Search variables...", diff --git a/apps/src/lib/i18n/messages/ko.ts b/apps/src/lib/i18n/messages/ko.ts index 75eb25642..05740fca7 100644 --- a/apps/src/lib/i18n/messages/ko.ts +++ b/apps/src/lib/i18n/messages/ko.ts @@ -474,6 +474,9 @@ export const KO_MESSAGES: MessageCatalog = { 网关策略: "게이트웨이 정책", 后台任务线程: "백그라운드 작업 스레드", "Worker 并发参数": "Worker 동시성 설정", + "计划按服务端时区 {timeZone} 执行。多个计划用 | 分隔。": + "예약은 서버 시간대 {timeZone} 기준으로 실행됩니다. 여러 예약은 | 로 구분하세요.", + 服务端本地时区: "서버 로컬 시간대", 当前档位: "현재 프리셋", 自定义: "사용자 지정", "搜索变量...": "변수 검색...", diff --git a/apps/src/lib/i18n/messages/ru.ts b/apps/src/lib/i18n/messages/ru.ts index 1017510a4..9bef22952 100644 --- a/apps/src/lib/i18n/messages/ru.ts +++ b/apps/src/lib/i18n/messages/ru.ts @@ -476,6 +476,9 @@ export const RU_MESSAGES: MessageCatalog = { 网关策略: "Политика шлюза", 后台任务线程: "Фоновые рабочие потоки", "Worker 并发参数": "Параметры конкуренции Worker", + "计划按服务端时区 {timeZone} 执行。多个计划用 | 分隔。": + "Расписание выполняется в часовом поясе сервера {timeZone}. Несколько расписаний разделяйте символом |.", + 服务端本地时区: "Локальный часовой пояс сервера", 当前档位: "Текущий профиль", 自定义: "Свой", "搜索变量...": "Поиск переменных...", diff --git a/apps/src/lib/store/useAppStore.ts b/apps/src/lib/store/useAppStore.ts index 0d184c6c2..a40fafa1a 100644 --- a/apps/src/lib/store/useAppStore.ts +++ b/apps/src/lib/store/useAppStore.ts @@ -124,6 +124,11 @@ export const useAppStore = create((set) => ({ warmupCronEnabled: false, warmupCronExpression: "", }, + runtimeTimeZone: { + name: "Local", + offset: "", + source: "system", + }, envOverrides: {}, envOverrideCatalog: [], envOverrideReservedKeys: [], diff --git a/apps/src/types/settings.ts b/apps/src/types/settings.ts index d428b13b9..f9a985407 100644 --- a/apps/src/types/settings.ts +++ b/apps/src/types/settings.ts @@ -27,6 +27,12 @@ export interface BackgroundTaskSettings { warmupCronExpression: string; } +export interface RuntimeTimeZone { + name: string; + offset: string; + source: string; +} + export interface QuotaGuardSettings { enabled: boolean; primaryMinRemainingPercent: number; @@ -76,6 +82,7 @@ export interface AppSettings { upstreamTotalTimeoutMs: number; sseKeepaliveIntervalMs: number; backgroundTasks: BackgroundTaskSettings; + runtimeTimeZone: RuntimeTimeZone; envOverrides: Record; envOverrideCatalog: EnvOverrideCatalogItem[]; envOverrideReservedKeys: string[]; diff --git a/apps/tests/settings-page-helpers.test.mjs b/apps/tests/settings-page-helpers.test.mjs index 37b1781f9..b76c24c3f 100644 --- a/apps/tests/settings-page-helpers.test.mjs +++ b/apps/tests/settings-page-helpers.test.mjs @@ -60,3 +60,35 @@ test("compareEnvOverrideItems 将高风险请求语义项排在普通项之后", "CODEXMANAGER_STRICT_REQUEST_PARAM_ALLOWLIST", ]); }); + +test("formatRuntimeTimeZoneLabel 显示后端传回的时区和偏移", () => { + assert.equal( + helpers.formatRuntimeTimeZoneLabel({ + name: "Asia/Shanghai", + offset: "+08:00", + source: "TZ", + }), + "Asia/Shanghai (UTC+08:00)" + ); + + assert.equal( + helpers.formatRuntimeTimeZoneLabel({ + name: "Local", + offset: "-05:00", + source: "system", + }), + "服务端本地时区 (UTC-05:00)" + ); + + assert.equal( + helpers.formatRuntimeTimeZoneLabel( + { + name: "Local", + offset: "+01:00", + source: "system", + }, + "Server local time zone" + ), + "Server local time zone (UTC+01:00)" + ); +}); diff --git a/crates/service/src/app_settings/api/current.rs b/crates/service/src/app_settings/api/current.rs index 0d1888798..de9f4e601 100644 --- a/crates/service/src/app_settings/api/current.rs +++ b/crates/service/src/app_settings/api/current.rs @@ -1,6 +1,7 @@ use crate::app_settings::{list_app_settings_map, listener_bind_addr_for_mode}; use crate::initialize_storage_if_needed; use crate::{current_web_auth_mode, distribution_enabled, web_access_password_configured}; +use chrono::Local; use codexmanager_core::rpc::types::ModelInfo; use serde_json::Value; use std::collections::BTreeMap; @@ -78,6 +79,28 @@ fn normalize_service_bind_mode_value(raw: Option<&str>) -> &'static str { } } +fn current_runtime_time_zone_value() -> Value { + let env_tz = std::env::var("TZ") + .ok() + .map(|value| value.trim().to_string()) + .filter(|value| !value.is_empty()); + let offset = Local::now().offset().to_string(); + let source = if env_tz.is_some() { "TZ" } else { "system" }; + let name = env_tz.unwrap_or_else(|| { + if offset == "+00:00" { + "UTC".to_string() + } else { + "Local".to_string() + } + }); + + serde_json::json!({ + "name": name, + "offset": offset, + "source": source, + }) +} + /// 函数 `current_app_settings_value` /// /// 作者: gaohongshun @@ -97,6 +120,7 @@ pub(super) fn current_app_settings_value( initialize_storage_if_needed()?; sync_runtime_settings_from_storage(); let background_tasks = current_background_tasks_snapshot_value()?; + let runtime_time_zone = current_runtime_time_zone_value(); let update_auto_check = current_update_auto_check_enabled(); let persisted_close_to_tray = current_close_to_tray_on_close_setting(); let close_to_tray = close_to_tray_on_close.unwrap_or(persisted_close_to_tray); @@ -259,6 +283,7 @@ pub(super) fn current_app_settings_value( "webAccessPasswordConfigured": web_access_password_configured(), }); if let Some(object) = result.as_object_mut() { + object.insert("runtimeTimeZone".to_string(), runtime_time_zone); object.insert("webAuthMode".to_string(), current_web_auth_mode().into()); object.insert( "webAuthModeOptions".to_string(), diff --git a/crates/service/tests/app_settings.rs b/crates/service/tests/app_settings.rs index d54315649..989741550 100644 --- a/crates/service/tests/app_settings.rs +++ b/crates/service/tests/app_settings.rs @@ -1032,6 +1032,37 @@ fn app_settings_get_defaults_codex_cli_guide_to_false() { }); } +#[test] +fn app_settings_get_exposes_runtime_time_zone_from_tz_env() { + with_temp_db(|_| { + let _tz = override_env_vars(&[("TZ", Some("Asia/Shanghai"))]); + + let snapshot = codexmanager_service::app_settings_get().expect("get app settings"); + let runtime_time_zone = snapshot + .get("runtimeTimeZone") + .and_then(|value| value.as_object()) + .expect("runtime time zone object"); + + assert_eq!( + runtime_time_zone.get("name").and_then(|value| value.as_str()), + Some("Asia/Shanghai") + ); + assert_eq!( + runtime_time_zone + .get("source") + .and_then(|value| value.as_str()), + Some("TZ") + ); + assert!( + runtime_time_zone + .get("offset") + .and_then(|value| value.as_str()) + .is_some_and(|value| !value.is_empty()), + "runtime time zone should include an offset: {runtime_time_zone:?}" + ); + }); +} + /// 函数 `sync_runtime_settings_from_storage_applies_saved_runtime_values` /// /// 作者: gaohongshun diff --git a/docker-compose.yml b/docker-compose.yml index b60b244e6..a6390856d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,7 @@ services: CODEXMANAGER_SERVICE_ADDR: 0.0.0.0:48760 CODEXMANAGER_WEB_ADDR: 0.0.0.0:48761 CODEXMANAGER_WEB_NO_OPEN: "1" + TZ: ${TZ:-Asia/Shanghai} CODEXMANAGER_DB_PATH: /data/codexmanager.db CODEXMANAGER_RPC_TOKEN_FILE: /data/codexmanager.rpc-token CODEXMANAGER_GATEWAY_TRACE_STDOUT: "1" diff --git a/docker/Dockerfile.all-in-one b/docker/Dockerfile.all-in-one index b4cacf9ec..0daaf153d 100644 --- a/docker/Dockerfile.all-in-one +++ b/docker/Dockerfile.all-in-one @@ -46,10 +46,12 @@ FROM debian:bookworm-slim ARG APP_USER=codexmanager ARG APP_UID=10001 +ENV TZ=Asia/Shanghai + WORKDIR /app RUN apt-get update \ - && apt-get install -y --no-install-recommends ca-certificates wget \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates wget tzdata \ && rm -rf /var/lib/apt/lists/* \ && groupadd --system --gid ${APP_UID} ${APP_USER} \ && useradd --system --uid ${APP_UID} --gid ${APP_UID} --home-dir /app --create-home --shell /usr/sbin/nologin ${APP_USER} \ diff --git a/docker/Dockerfile.service b/docker/Dockerfile.service index 95a013c25..212cdd58c 100644 --- a/docker/Dockerfile.service +++ b/docker/Dockerfile.service @@ -13,10 +13,12 @@ FROM debian:bookworm-slim ARG APP_USER=codexmanager ARG APP_UID=10001 +ENV TZ=Asia/Shanghai + WORKDIR /app RUN apt-get update \ - && apt-get install -y --no-install-recommends ca-certificates wget \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates wget tzdata \ && rm -rf /var/lib/apt/lists/* \ && groupadd --system --gid ${APP_UID} ${APP_USER} \ && useradd --system --uid ${APP_UID} --gid ${APP_UID} --home-dir /app --create-home --shell /usr/sbin/nologin ${APP_USER} \ diff --git a/docker/Dockerfile.service.release b/docker/Dockerfile.service.release index 4d0a9f92b..1d7c25106 100644 --- a/docker/Dockerfile.service.release +++ b/docker/Dockerfile.service.release @@ -3,10 +3,12 @@ FROM debian:bookworm-slim ARG APP_USER=codexmanager ARG APP_UID=10001 +ENV TZ=Asia/Shanghai + WORKDIR /app RUN apt-get update \ - && apt-get install -y --no-install-recommends ca-certificates wget \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates wget tzdata \ && rm -rf /var/lib/apt/lists/* \ && groupadd --system --gid ${APP_UID} ${APP_USER} \ && useradd --system --uid ${APP_UID} --gid ${APP_UID} --home-dir /app --create-home --shell /usr/sbin/nologin ${APP_USER} \ diff --git a/docker/Dockerfile.web b/docker/Dockerfile.web index e066c04ce..f3d25989b 100644 --- a/docker/Dockerfile.web +++ b/docker/Dockerfile.web @@ -28,10 +28,12 @@ FROM debian:bookworm-slim ARG APP_USER=codexmanager ARG APP_UID=10001 +ENV TZ=Asia/Shanghai + WORKDIR /app RUN apt-get update \ - && apt-get install -y --no-install-recommends ca-certificates wget \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates wget tzdata \ && rm -rf /var/lib/apt/lists/* \ && groupadd --system --gid ${APP_UID} ${APP_USER} \ && useradd --system --uid ${APP_UID} --gid ${APP_UID} --home-dir /app --create-home --shell /usr/sbin/nologin ${APP_USER} \ diff --git a/docker/Dockerfile.web.release b/docker/Dockerfile.web.release index 80960d5e4..076f9a01a 100644 --- a/docker/Dockerfile.web.release +++ b/docker/Dockerfile.web.release @@ -3,10 +3,12 @@ FROM debian:bookworm-slim ARG APP_USER=codexmanager ARG APP_UID=10001 +ENV TZ=Asia/Shanghai + WORKDIR /app RUN apt-get update \ - && apt-get install -y --no-install-recommends ca-certificates wget \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates wget tzdata \ && rm -rf /var/lib/apt/lists/* \ && groupadd --system --gid ${APP_UID} ${APP_USER} \ && useradd --system --uid ${APP_UID} --gid ${APP_UID} --home-dir /app --create-home --shell /usr/sbin/nologin ${APP_USER} \ diff --git a/docker/docker-compose.all-in-one.yml b/docker/docker-compose.all-in-one.yml index 24903436d..e8491356f 100644 --- a/docker/docker-compose.all-in-one.yml +++ b/docker/docker-compose.all-in-one.yml @@ -8,6 +8,7 @@ services: CODEXMANAGER_SERVICE_ADDR: 0.0.0.0:48760 CODEXMANAGER_WEB_ADDR: 0.0.0.0:48761 CODEXMANAGER_WEB_NO_OPEN: "1" + TZ: ${TZ:-Asia/Shanghai} CODEXMANAGER_DB_PATH: /data/codexmanager.db CODEXMANAGER_RPC_TOKEN_FILE: /data/codexmanager.rpc-token CODEXMANAGER_GATEWAY_TRACE_STDOUT: "1" diff --git a/docker/docker-compose.release.yml b/docker/docker-compose.release.yml index bd4570a2c..47bff7442 100644 --- a/docker/docker-compose.release.yml +++ b/docker/docker-compose.release.yml @@ -4,6 +4,7 @@ services: restart: unless-stopped environment: CODEXMANAGER_SERVICE_ADDR: 0.0.0.0:48760 + TZ: ${TZ:-Asia/Shanghai} CODEXMANAGER_DB_PATH: /data/codexmanager.db CODEXMANAGER_RPC_TOKEN_FILE: /data/codexmanager.rpc-token volumes: @@ -21,6 +22,7 @@ services: CODEXMANAGER_WEB_ADDR: 0.0.0.0:48761 CODEXMANAGER_WEB_NO_SPAWN_SERVICE: "1" CODEXMANAGER_SERVICE_ADDR: codexmanager-service:48760 + TZ: ${TZ:-Asia/Shanghai} CODEXMANAGER_DB_PATH: /data/codexmanager.db CODEXMANAGER_RPC_TOKEN_FILE: /data/codexmanager.rpc-token CODEXMANAGER_WEB_NO_OPEN: "1" diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index a4dab5619..30cc7b87b 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -6,6 +6,7 @@ services: restart: unless-stopped environment: CODEXMANAGER_SERVICE_ADDR: 0.0.0.0:48760 + TZ: ${TZ:-Asia/Shanghai} CODEXMANAGER_DB_PATH: /data/codexmanager.db CODEXMANAGER_RPC_TOKEN_FILE: /data/codexmanager.rpc-token CODEXMANAGER_GATEWAY_TRACE_STDOUT: "1" @@ -29,6 +30,7 @@ services: CODEXMANAGER_WEB_ADDR: 0.0.0.0:48761 CODEXMANAGER_WEB_NO_SPAWN_SERVICE: "1" CODEXMANAGER_SERVICE_ADDR: codexmanager-service:48760 + TZ: ${TZ:-Asia/Shanghai} CODEXMANAGER_DB_PATH: /data/codexmanager.db CODEXMANAGER_RPC_TOKEN_FILE: /data/codexmanager.rpc-token CODEXMANAGER_WEB_NO_OPEN: "1" diff --git a/docs/en/report/environment-and-runtime-config.md b/docs/en/report/environment-and-runtime-config.md index 15ba82aa9..323728aec 100644 --- a/docs/en/report/environment-and-runtime-config.md +++ b/docs/en/report/environment-and-runtime-config.md @@ -78,6 +78,10 @@ - `CODEXMANAGER_WEB_ROOT`:web 静态资源目录 - `CODEXMANAGER_LOGIN_ADDR`:本地 OAuth 回调监听地址 +### Docker containers + +- `TZ`: container time zone. Docker images default to `Asia/Shanghai`; compose examples use `${TZ:-Asia/Shanghai}`, so they pass through `TZ` from the deployment environment and fall back to `Asia/Shanghai` when unset. Change it to your own IANA time zone when deploying elsewhere. + ### 网关与上游 - `CODEXMANAGER_UPSTREAM_BASE_URL` diff --git a/docs/en/report/runtime-and-deployment-guide.md b/docs/en/report/runtime-and-deployment-guide.md index f0d3ac46c..44f82e94b 100644 --- a/docs/en/report/runtime-and-deployment-guide.md +++ b/docs/en/report/runtime-and-deployment-guide.md @@ -90,6 +90,8 @@ You can still set `CODEXMANAGER_WEB_ROOT=/path/to/out` when you intentionally wa ## Docker deployment +Docker images default to `TZ=Asia/Shanghai`, and compose examples use `TZ=${TZ:-Asia/Shanghai}`: if the deployment environment already sets `TZ`, compose passes it through; otherwise it falls back to `Asia/Shanghai`. If you deploy in another region, set `TZ` or change it under `environment` to your own IANA time zone, for example `Europe/London` or `America/Los_Angeles`. + ### GitHub Packages / GHCR - After a Release is published, both `codexmanager-service` and `codexmanager-web` images are pushed to GitHub Packages (GHCR). - Pull the corresponding release tag, for example: `docker pull ghcr.io/qxcnm/codexmanager-service:v0.1.15` @@ -114,6 +116,7 @@ docker run --rm --name codexmanager-service \ --network-alias codexmanager-service \ -p 48760:48760 \ -v codexmanager-data:/data \ + -e TZ=Asia/Shanghai \ -e CODEXMANAGER_RPC_TOKEN=replace_with_your_token \ codexmanager-service @@ -123,6 +126,7 @@ docker run --rm --name codexmanager-web \ --network codexmanager-net \ -p 48761:48761 \ -v codexmanager-data:/data \ + -e TZ=Asia/Shanghai \ -e CODEXMANAGER_WEB_NO_SPAWN_SERVICE=1 \ -e CODEXMANAGER_SERVICE_ADDR=codexmanager-service:48760 \ -e CODEXMANAGER_RPC_TOKEN=replace_with_your_token \ diff --git "a/docs/zh-CN/report/\347\216\257\345\242\203\345\217\230\351\207\217\344\270\216\350\277\220\350\241\214\351\205\215\347\275\256\350\257\264\346\230\216.md" "b/docs/zh-CN/report/\347\216\257\345\242\203\345\217\230\351\207\217\344\270\216\350\277\220\350\241\214\351\205\215\347\275\256\350\257\264\346\230\216.md" index 69a5e2882..6bcf02079 100644 --- "a/docs/zh-CN/report/\347\216\257\345\242\203\345\217\230\351\207\217\344\270\216\350\277\220\350\241\214\351\205\215\347\275\256\350\257\264\346\230\216.md" +++ "b/docs/zh-CN/report/\347\216\257\345\242\203\345\217\230\351\207\217\344\270\216\350\277\220\350\241\214\351\205\215\347\275\256\350\257\264\346\230\216.md" @@ -78,6 +78,10 @@ - `CODEXMANAGER_WEB_ROOT`:web 静态资源目录 - `CODEXMANAGER_LOGIN_ADDR`:本地 OAuth 回调监听地址 +### Docker 容器 + +- `TZ`:容器时区,Docker 镜像默认 `Asia/Shanghai`;compose 示例使用 `${TZ:-Asia/Shanghai}`,会优先沿用部署环境里的 `TZ`,没有设置时回退到 `Asia/Shanghai`。其他地区部署时请改成自己的 IANA 时区。 + ### 网关与上游 - `CODEXMANAGER_UPSTREAM_BASE_URL` diff --git "a/docs/zh-CN/report/\350\277\220\350\241\214\344\270\216\351\203\250\347\275\262\346\214\207\345\215\227.md" "b/docs/zh-CN/report/\350\277\220\350\241\214\344\270\216\351\203\250\347\275\262\346\214\207\345\215\227.md" index bd41277e0..02f67c19a 100644 --- "a/docs/zh-CN/report/\350\277\220\350\241\214\344\270\216\351\203\250\347\275\262\346\214\207\345\215\227.md" +++ "b/docs/zh-CN/report/\350\277\220\350\241\214\344\270\216\351\203\250\347\275\262\346\214\207\345\215\227.md" @@ -108,6 +108,8 @@ wire_api = "responses" ## Docker 部署 +Docker 镜像默认设置 `TZ=Asia/Shanghai`,compose 示例使用 `TZ=${TZ:-Asia/Shanghai}`:如果部署环境已经设置 `TZ`,会直接沿用;否则回退到 `Asia/Shanghai`。如果部署在其他地区,请设置 `TZ` 或在 compose 的 `environment` 中改成自己的 IANA 时区,例如 `Europe/London`、`America/Los_Angeles`。 + ### GitHub Packages / GHCR - Release 发布后会同时推送 `codexmanager-service` 和 `codexmanager-web` 镜像到 GitHub Packages(GHCR)。 - 直接拉取对应发布 tag 即可,例如:`docker pull ghcr.io/qxcnm/codexmanager-service:v0.1.15` @@ -144,6 +146,7 @@ docker run --rm --name codexmanager-service \ --network-alias codexmanager-service \ -p 48760:48760 \ -v codexmanager-data:/data \ + -e TZ=Asia/Shanghai \ -e CODEXMANAGER_RPC_TOKEN=replace_with_your_token \ codexmanager-service @@ -153,6 +156,7 @@ docker run --rm --name codexmanager-web \ --network codexmanager-net \ -p 48761:48761 \ -v codexmanager-data:/data \ + -e TZ=Asia/Shanghai \ -e CODEXMANAGER_WEB_NO_SPAWN_SERVICE=1 \ -e CODEXMANAGER_SERVICE_ADDR=codexmanager-service:48760 \ -e CODEXMANAGER_RPC_TOKEN=replace_with_your_token \