Kener Docker Compose 部署指南
在 Linux 服务器以 Docker Compose 从零部署 Kener v4.1.7(Kener+Redis 双服务、SQLite 落盘、8109 端口),含镜像选型、数据目录属主排障、首个管理员注册、健康检查语义、升级与运维命令,全程实测回显。
Kener Docker Compose 部署指南
目标:在 Linux 服务器上以 Docker Compose 从零部署 Kener v4.1.7 开源状态页与监控告警平台(Kener + Redis 双服务、SQLite 数据落盘、端口 8109 对外),覆盖镜像选型、部署、首个管理员注册、健康检查、数据持久化与升级运维,全部命令与回显均在 Ubuntu 服务器(内核 6.8.0-138-generic,Docker 29.8.1)实测通过。
一、环境信息
本文所有命令与回显来自以下实测环境,读者在同类环境(x86_64 Linux + Docker)可直接复现。
- 操作系统:Ubuntu 22.04(内核
6.8.0-138-generic,uname -r实测回显); - 服务器内网 IP:192.168.146.128(
ip -4 addr show ens33实测,下文 ORIGIN 与浏览器访问地址均以此为准); - Docker:
Docker version 29.8.1, build 4a63305; - Docker Compose:
Docker Compose version v5.5.1; - Kener 版本:
rajnandan1/kener:v4.1.7(2026-10-07 发布的最新稳定版;磁盘占用 827 MB,压缩内容 163 MB); - Redis:
redis:7-alpine(实测redis-server v=7.4.11,镜像 57.8 MB)——Kener v4 起强制依赖 Redis(BullMQ 队列后端),无 Redis 无法启动; - 编排目录:
/opt/data/quzuo/kener-compose/docker-compose.yml; - 数据目录:
/opt/data/quzuo/kener-data(宿主机 bind mount 到服务内/app/database,SQLite 数据库文件落盘处); - 对外端口:8109 → 3000。启动前用
ss -ltn复核:实测 8109 空闲可直接使用;同机 8113/8114 已被其他服务占用。若 8109 在你的服务器上被占,按本文同法顺延挑一个空闲端口并同步修改 compose 与ORIGIN; - 容器网络:compose 项目网络
kener-net,显式子网10.89.39.0/24(规划槽位 10.89.38.0/24 已被同机其他编排栈占用,实测顺延取 39); - 实测管理账号:
admin@example.com/Q1w2e3r4(首账号即管理员;密码实测必须含大写字母,详见 4.6 节与 FAQ)。
二、镜像选型说明
Kener 官方在 Docker Hub 与 GHCR 双发布镜像,v4.1.7 线有以下变体(来源:官方 Deployment 文档与 Docker Hub,2026-10-18 核实):
| 镜像 tag | 变体说明 | 适用场景 |
|---|---|---|
rajnandan1/kener:v4.1.7 | Debian 精简基底(与 latest 等价的版本锁定写法) | 本文采用:版本固定、复现性好 |
rajnandan1/kener:v4.1.7-alpine | Alpine 基底,体积更小 | 资源受限、追求小镜像 |
rajnandan1/kener:v4.1.7-status | 构建期烘焙 KENER_BASE_PATH=/status | 子路径部署(如 https://example.com/status) |
rajnandan1/kener:latest | 滚动最新 | 追新,但升级不可控 |
配套的 Redis 使用官方 redis:7-alpine(57.8 MB),与 Kener 官方 docker-compose.yml 保持一致。GHCR 等价地址为 ghcr.io/rajnandan1/kener:v4.1.7,两者内容相同,按网络可达性任选。
选型建议:生产固定版本号(本文 v4.1.7),不要裸用 latest;只有明确要把状态页挂在反代子路径下时才换 -status 变体——普通镜像在运行期改 KENER_BASE_PATH 不会生效(该参数构建期烘焙,官方 Deployment 文档 IMPORTANT 注明)。
三、前置条件
- 服务器已安装 Docker 与 Compose 插件(实测版本见环境信息);
- 目录已规划:编排与数据目录可按需创建(本文实测用
/opt/data/quzuo/kener-compose与/opt/data/quzuo/kener-data):mkdir -p /opt/data/quzuo/kener-compose /opt/data/quzuo/kener-data - 端口已复核:对外端口启动前必须实测检查,避免带病启动:
实测回显:
ss -ltn | grep -E ':(8109)\b' || echo "8109 未占用,可启动"8109 未占用,可启动⚠️ 若输出显示 8109 已被监听,换用其他空闲端口(如 8115、8116),并同步修改后文 compose 的
ports与环境变量ORIGIN; - 网络可达性:能拉取 Docker Hub 镜像(国外资源慢时可配置镜像加速或 HTTP 代理,本文环境 Docker 守护进程已配代理);
- 浏览器可访问服务器 IP:部署完成后状态页与管理台都通过
http://<服务器IP>:8109访问。
四、部署步骤
4.1 编写 docker-compose.yml
在编排目录创建 docker-compose.yml,内容如下(与官方 docker-compose.yml 等价,做了三处适配:版本号锁定 v4.1.7、对外端口 8109、数据库目录 bind mount 到宿主机、显式子网):
services:
redis:
image: redis:7-alpine
container_name: kener-4-1-7-redis
restart: unless-stopped
volumes:
- kener_redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- kener-net
kener:
image: rajnandan1/kener:v4.1.7
container_name: kener-4-1-7-app
environment:
KENER_SECRET_KEY: kXv9mQ4pLtR2wN8yBhE6jZ3cA5uDs7Vg1oIf0nPa
ORIGIN: http://192.168.146.128:8109
REDIS_URL: redis://redis:6379
DOC_BASE_URL: http://localhost:3000
ports:
- "8109:3000"
volumes:
- /opt/data/quzuo/kener-data:/app/database
depends_on:
redis:
condition: service_healthy
restart: unless-stopped
networks:
- kener-net
networks:
kener-net:
driver: bridge
ipam:
config:
- subnet: 10.89.39.0/24
volumes:
kener_redis_data:
name: kener_redis_data
逐项说明:
| 配置项 | 值与作用 |
|---|---|
KENER_SECRET_KEY | JWT 签名与敏感数据加密密钥。必须换成你自己的强随机串:openssl rand -base64 32 生成。不设会有启动告警且会话不安全 |
ORIGIN | 用户实际访问的公开 URL,必须带协议、不带尾斜杠。生产缺省或不匹配时,所有表单提交(登录/注册/后台保存)都会被 CSRF 拦截报错 |
REDIS_URL | Redis 连接串,redis://redis:6379 指向 compose 内的 redis 服务(服务名即 DNS) |
DOC_BASE_URL | 自定义环境变量示例(监控配置里可用 $DOC_BASE_URL 引用),非必需,见《Kener 4.1.7 配置参数详解》 |
ports: "8109:3000" | 宿主机 8109 映射服务内 3000(Kener 默认监听端口) |
volumes(bind mount) | SQLite 数据库落盘到宿主机 /opt/data/quzuo/kener-data |
kener_redis_data | Redis 持久化命名卷,队列与缓存数据重启不丢 |
depends_on: service_healthy | 等 Redis 健康检查通过后再启动 Kener |
ipam subnet | 显式子网,避免依赖自动分配 |
4.2 拉取镜像
docker pull rajnandan1/kener:v4.1.7
docker pull redis:7-alpine
实测回显(Kener 首拉):
v4.1.7: Pulling from rajnandan1/kener
Digest: sha256:b99d2b595f92b240d05e75176042542f14e8eb0e57d3f6b3f09794c6dd3c8fd8
Status: Downloaded newer image for rajnandan1/kener:v4.1.7
docker.io/rajnandan1/kener:v4.1.7
镜像本地占用确认:
docker images --format '{{.Repository}}:{{.Tag}} {{.Size}}' | grep -E 'kener|redis:7-alpine'
rajnandan1/kener:v4.1.7 827MB
rajnandan1/kener:v4.1.7-status 827MB
redis:7-alpine 57.8MB
4.3 启动编排栈
cd /opt/data/quzuo/kener-compose
docker compose up -d
实测回显:
[+] Running 4/4
✔ Network kener-compose_kener-net Created
✔ Volume "kener_redis_data" Created
✔ Container kener-4-1-7-redis Healthy
✔ Container kener-4-1-7-app Started
⚠️ 首次启动关键排障(实测实录):本文首次
up -d后服务看似正常,健康检查却返回{"status":"degraded","db":false,"redis":true},日志出现:Error running migrations: SqliteError: unable to open database file at new Database (/app/node_modules/better-sqlite3/lib/database.js:69:26) ... code: 'SQLITE_CANTOPEN'原因:Kener 服务内以非 root 的
node用户(UID 1000)运行,而宿主机新建的/opt/data/quzuo/kener-data属主是 root,进程无权创建 SQLite 文件。解决:把数据目录属主改为 UID 1000 再重启:chown -R 1000:1000 /opt/data/quzuo/kener-data docker compose restart kener重启后日志即出现
Running migrations... Migrations completed successfully!(见 4.4)。命名的 Redis 卷由 Docker 自动管理属主,无需处理。
4.4 确认启动日志与首次初始化
docker logs kener-4-1-7-app
实测回显(属主修正后的首次完整启动,节选):
Configuring database with type sqlite
Running migrations...
Migrations completed successfully!
Running seed...
Seed completed successfully!
Kener is running on port 3000!
Using option immediately with every does not affect the job's schedule. Job will run immediately anyway.
Maintenance event scheduler started (runs every hour)
Daily cleanup scheduler started (runs at 00:00 UTC)
_ __ _ _ _ _____
| |/ /___ _ __ ___ _ __ __ _| || | / ||___ |
| ' // _ \ '_ \ / _ \ '__| \ \ / / || |_ | | / /
| . \ __/ | | | __/ | \ V /|__ _|| |_ / /
|_|\_\___|_| |_|\___|_| \_/ |_|(_)_(_)_/
Kener version 4.1.7 is running!
ADDING NEW SCHEDULER: kener
ADDING NEW SCHEDULER: earth
要点:Migrations completed successfully! 表示数据库表结构已自动建好;Seed completed successfully! 会预置两个示例监控(kener、earth);Kener version 4.1.7 is running! 是版本确认行。
4.5 健康检查与服务验证
curl -s http://127.0.0.1:8109/healthcheck
实测回显:
{"status":"ok","db":true,"redis":true}
浏览器访问 http://192.168.146.128:8109 应能看到状态页首页(实测页面标题):
curl -s http://127.0.0.1:8109/ | grep -oE '<title>[^<]*</title>'
<title>Home - Kener.ing</title>
编排栈状态复核:
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
kener-4-1-7-app rajnandan1/kener:v4.1.7 "./docker-entrypoint…" kener 23 seconds ago Up 12 seconds (healthy) 0.0.0.0:8109->3000/tcp, [::]:8109->3000/tcp
kener-4-1-7-redis redis:7-alpine "docker-entrypoint.s…" redis 23 seconds ago Up 22 seconds (healthy) 6379/tcp
两个服务均为 healthy 即部署成功。子网复核:
docker network inspect kener-compose_kener-net --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
10.89.39.0/24
4.6 注册首个管理员账号
Kener 首个注册账号自动成为管理员(admin 角色、is_owner)。浏览器打开 http://192.168.146.128:8109/account/signin,切换到注册页签,填入名称、邮箱与密码提交即可。本文用 curl 复现该请求(注册是表单 POST 到 /account/signin?/signup):
curl -s -X POST "http://127.0.0.1:8109/account/signin?/signup" \
-H "Origin: http://192.168.146.128:8109" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "name=admin&email=admin@example.com&password=q1w2e3r4"
实测回显——纯数字+小写密码被密码策略拒绝:
{"type":"failure","status":400,"data":"[{\"error\":1,\"values\":2},\"Password must contain at least one digit, one lowercase letter, one uppercase letter, and have a minimum length of 8 characters\",{\"name\":3,\"email\":4},\"admin\",\"admin@example.com\"]"}
补一个含大写字母的变体 Q1w2e3r4 重新提交:
curl -s -X POST "http://127.0.0.1:8109/account/signin?/signup" \
-H "Origin: http://192.168.146.128:8109" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "name=admin&email=admin@example.com&password=Q1w2e3r4"
实测回显(302 跳转到管理台,注册成功):
{"type":"redirect","status":302,"location":"/manage/app/site-configurations"}
登录验证(同样的表单动作改 ?/login):
curl -s -c /tmp/kener-cookie.txt -X POST "http://127.0.0.1:8109/account/signin?/login" \
-H "Origin: http://192.168.146.128:8109" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "email=admin@example.com&password=Q1w2e3r4"
实测回显:
{"type":"redirect","status":302,"location":"/manage/app/site-configurations"}
浏览器登录 http://192.168.146.128:8109/account/signin(邮箱 admin@example.com、密码 Q1w2e3r4)进入 /manage/app/site-configurations 管理台即全部就绪。
4.7 健康端点故障语义实测
Kener 健康端点区分「普通」与「严格」两种语义(官方 Deployment 文档说明,本文实测复核)。停掉 Redis 模拟依赖故障:
docker stop kener-4-1-7-redis
curl -s -w "\nHTTP %{http_code}\n" http://127.0.0.1:8109/healthcheck
curl -s -w "\nHTTP %{http_code}\n" "http://127.0.0.1:8109/healthcheck?strict=1"
实测回显(非 strict 恒 200 只报 degraded;strict=1 返回 503):
-- 非 strict:
{"status":"degraded","db":true,"redis":false}
HTTP 200
-- strict=1:
{"status":"degraded","db":true,"redis":false}
HTTP 503
恢复 Redis 后自愈:
docker start kener-4-1-7-redis
sleep 8 && curl -s -w "\nHTTP %{http_code}\n" http://127.0.0.1:8109/healthcheck
-- redis 恢复后:
{"status":"ok","db":true,"redis":true}
HTTP 200
💡 说明:给「失败即重启」的外部看门狗(编排健康检查、负载均衡探活)接
?strict=1时要谨慎——重启 Kener 治不了 Redis/数据库宕机,官方文档明确警告会导致整个故障期无限重启循环;编排HEALTHCHECK用默认端点即可(官方镜像已内置,打默认/healthcheck)。
五、数据持久化说明
| 数据 | 落盘位置 | 持久化方式 |
|---|---|---|
| SQLite 数据库(监控、事件、维护、用户、API Key、配置等全部业务数据) | 宿主机 /opt/data/quzuo/kener-data/kener.sqlite.db | bind mount → 服务内 /app/database |
| Redis 队列/缓存 | Docker 命名卷 kener_redis_data | compose volumes: 声明,down 不删 |
实测数据文件(属主 UID 1000 即服务内 node 用户):
ls -lh /opt/data/quzuo/kener-data/
total 472K
-rw-r--r-- 1 yahui yahui 472K 10月 18 22:55 kener.sqlite.db
要点:备份即拷贝 kener.sqlite.db(建议先 docker compose stop kener 再拷,保证一致性);docker compose down 不会删除 bind mount 数据与命名卷,加 -v 才会连 kener_redis_data 一起删。
六、环境变量表
Kener v4 的部署配置全部走环境变量(v3 的 config.yaml 已废弃,完整逐项实测见《Kener 4.1.7 配置参数详解》)。部署必知的最小集合:
| 变量 | 必需 | 默认值 | 说明 |
|---|---|---|---|
KENER_SECRET_KEY | 是 | 无(不设用内置默认值并告警) | JWT/敏感数据加密密钥,openssl rand -base64 32 生成 |
ORIGIN | 是 | 无 | 公开访问 URL,生产缺省时全部表单被 CSRF 拦截 |
REDIS_URL | 是 | 无 | BullMQ 队列后端,如 redis://redis:6379 |
DATABASE_URL | 否 | sqlite://./database/kener.sqlite.db | 换 PostgreSQL/MySQL 时设置,如 postgresql://user:pass@host:5432/kener |
PORT | 否 | 3000 | 服务内监听端口 |
KENER_BASE_PATH | 否 | / | 子路径部署;需配套 -status 构建镜像 |
TZ | 否 | UTC | 时区;官方建议保持 UTC(应用启动时内部强制 UTC) |
BODY_SIZE_LIMIT | 否 | 3M(官方镜像内置) | 请求体上限,管理台上传大图时调大 |
KENER_FORCE_LOCAL_LOGIN | 否 | 未设 | 应急开关:OIDC 配坏导致本地登录被禁时置 true 找回入口 |
七、配置参数说明
compose 内与运行行为直接相关的参数逐项说明(均在 4.1 节出现,此处给改动指引):
ports: "8109:3000":冒号前是宿主机端口(对外访问http://<IP>:8109),冒号后是服务内端口(Kener 默认 3000,除非同时改PORT,一般不动)。改宿主机端口后必须同步改ORIGIN,否则登录表单会被 CSRF 拦截;restart: unless-stopped:服务崩溃自动拉起(手动docker compose stop的除外),生产推荐;always与之差异在于 Docker 守护进程重启后的行为;depends_on: condition: service_healthy:严格等 Redis 的redis-cli ping健康检查通过才启动 Kener,避免启动竞态导致队列连接失败;healthcheck(redis 服务):10 秒间隔 × 5 次重试,判定 Redis 可用性;Kener 服务自己的健康检查由官方镜像内置(curl /healthcheck,30 秒间隔);KENER_SECRET_KEY轮换:换新密钥后所有已登录会话与旧 API 签名失效,用户需重新登录,属预期行为;ORIGIN与反代:后续上 Nginx/Caddy 反代加域名 HTTPS 时,把ORIGIN改为https://status.example.com并docker compose up -d重建服务即可,反代转发目标仍是127.0.0.1:8109。
八、配置文件挂载
Kener v4 没有需要挂载的主配置文件——站点配置(站点名、Logo、主题、页脚等)在管理后台修改后存进数据库(SQLite 文件已持久化),监控与告警同样库内管理。需要挂载的只有两类:
- 数据库目录(本文已挂):
/opt/data/quzuo/kener-data:/app/database; - 可选:
.env文件:若偏好把环境变量收进.env而不是写死在 compose 里,可在编排目录建.env并在 kener 服务加env_file: - .env:
# /opt/data/quzuo/kener-compose/.env
KENER_SECRET_KEY=kXv9mQ4pLtR2wN8yBhE6jZ3cA5uDs7Vg1oIf0nPa
ORIGIN=http://192.168.146.128:8109
REDIS_URL=redis://redis:6379
# docker-compose.yml 的 kener 服务内追加
env_file:
- .env
服务启动时会自动加载 .env(启动日志中的 [dotenv@17.2.4] injecting env ... from .env 行即加载动作,实测可见)。
九、等价 docker run
不用 Compose 时,以下两条命令与本文编排完全等价(先建网络,Redis 起在同网络内):
docker network create -d bridge --subnet 10.89.39.0/24 kener-net
docker run -d --name kener-4-1-7-redis --network kener-net \
-v kener_redis_data:/data \
--restart unless-stopped \
redis:7-alpine
docker run -d --name kener-4-1-7-app --network kener-net \
-p 8109:3000 \
-e KENER_SECRET_KEY=kXv9mQ4pLtR2wN8yBhE6jZ3cA5uDs7Vg1oIf0nPa \
-e ORIGIN=http://192.168.146.128:8109 \
-e REDIS_URL=redis://kener-4-1-7-redis:6379 \
-v /opt/data/quzuo/kener-data:/app/database \
--restart unless-stopped \
rajnandan1/kener:v4.1.7
注意 docker run 方式下 depends_on 语义需自行保证(先起 Redis 再起 Kener),REDIS_URL 的主机名直接用 Redis 的容器名 kener-4-1-7-redis(同网络内 Docker DNS 解析)。日常仍推荐 Compose,升级与重建成本最低。
十、常用运维命令
以下命令均在编排目录 /opt/data/quzuo/kener-compose 下执行。
查看服务状态:
docker compose ps
(实测回显见 4.5 节,两服务 healthy。)
跟踪运行日志:
docker compose logs -f kener
实测回显节选(探测调度运行痕迹):
kener-4-1-7-app | Kener version 4.1.7 is running!
kener-4-1-7-app | ADDING NEW SCHEDULER: kener
kener-4-1-7-app | ADDING NEW SCHEDULER: earth
重启单个服务:
docker compose restart kener
实测回显:
Container kener-4-1-7-app Restarting
Container kener-4-1-7-app Started
整栈停止与再启动:
docker compose down # 停止并移除服务与网络,数据卷保留
docker compose up -d # 再启动
升级版本(示例:升级到未来某个新版本,替换 tag 即可):
docker pull rajnandan1/kener:v4.1.8 # 拉新版本镜像(以实际发布为准)
# 编辑 docker-compose.yml,把 kener 服务的 image 改为 rajnandan1/kener:v4.1.8
docker compose up -d # 重建服务,数据库迁移自动执行
升级要点:Kener 启动时自动跑数据库迁移,正常升级无需手工迁移;升级前建议备份 /opt/data/quzuo/kener-data/kener.sqlite.db;跨大版本(如 3.x → 4.x)先读官方 changelog 的迁移说明。
健康巡检:
curl -s http://127.0.0.1:8109/healthcheck
{"status":"ok","db":true,"redis":true}
十一、常见问题
Q1:启动后健康检查 {"status":"degraded","db":false,"redis":true},日志报 SqliteError: unable to open database file?
数据目录属主问题(见 4.3 节排障实录)。Kener 服务内以 UID 1000 的 node 用户运行,宿主机 bind mount 目录需放行:chown -R 1000:1000 /opt/data/quzuo/kener-data,然后 docker compose restart kener。修复后日志应出现 Migrations completed successfully!。
Q2:注册/登录提交表单报错或无响应?
两个常见原因:一是密码策略——实测密码必须「至少 8 位、含数字、含小写、含大写」,纯小写数字如 q1w2e3r4 会被拒绝(实测回显见 4.6 节),换成含大写的变体即可;二是 ORIGIN 未设置或与浏览器实际访问地址不一致,生产环境所有表单 POST 会被 CSRF 拦截,把 ORIGIN 改成用户真实访问的 URL(含端口)后重建服务。
Q3:健康检查什么时候用 ?strict=1?
普通 /healthcheck 永远返回 200(status 字段区分 ok/degraded),适合编排健康检查防误杀;?strict=1 在 db/redis 任一不可用时返回 503,适合需要「依赖不可用即摘流」的负载均衡场景。不要把 strict 端点接到「失败即重启容器」的看门狗上(见 4.7 节说明)。
Q4:端口启动前怎么规划?
先 ss -ltn | grep ':8109' 实测复核再写入 compose(示例用 8109,替换为你的目标端口)。本文环境实测 8109 空闲采用之;同机 8113/8114 已被占用。若与其他 Web 服务混部,8100–8199 段逐个复核选用,改端口后同步改 ORIGIN。
Q5:想挂子路径 /status 部署怎么办?
必须换 -status 后缀镜像(如 rajnandan1/kener:v4.1.7-status,该镜像构建期烘焙了 /status 基路径),同时环境变量设 KENER_BASE_PATH=/status、ORIGIN 保持域名根。普通镜像运行期设该变量无效。
Q6:Redis 数据重要吗?丢了会怎样? Redis 存的是 BullMQ 队列与缓存,业务事实数据都在 SQLite。Redis 卷丢失会导致待处理任务清空、缓存重建,探测调度会自动恢复,不影响历史状态数据。因此 Redis 用命名卷即可,无需额外备份。
Q7:如何完全卸载?
cd /opt/data/quzuo/kener-compose
docker compose down -v # 停止并删除服务、网络与 kener_redis_data 卷
docker rmi rajnandan1/kener:v4.1.7 redis:7-alpine
rm -rf /opt/data/quzuo/kener-data # 最后再删数据(确认无需保留)
十二、参考链接
- Kener 官方仓库:https://github.com/rajnandan1/kener
- 官方 Docker Compose 文件(v4.1.7 源码内):https://github.com/rajnandan1/kener/blob/v4.1.7/docker-compose.yml
- 官方部署文档(Deployment):https://kener.ing/docs/v4/setup/deployment
- 官方 Quick Start:https://kener.ing/docs/v4/getting-started/quick-start
- 官方环境变量文档:https://kener.ing/docs/v4/setup/environment-variables
- Docker Hub 镜像:https://hub.docker.com/r/rajnandan1/kener
- Kener 4.1.7 Release:https://github.com/rajnandan1/kener/releases/tag/v4.1.7
- 同专栏篇目:《Kener 4.1.7 介绍与选型指南》(选型与架构认知)、《Kener 4.1.7 配置参数详解》(环境变量逐项实测)