Docker Compose 部署 Live Helper Chat 4.97v 指南

使用官方 docker-standalone 编排部署 Live Helper Chat 4.97v 的完整实测指南:remdex 官方镜像实查、七服务编排结构、.env 配置、安装向导与 Redis 会话/resque worker/cronjob 全链路验证

Live Helper ChatDockerPHP在线客服2026/10/26

Docker Compose 部署 Live Helper Chat 4.97v 指南

目标:使用官方 docker-standalone 编排仓,在宿主机上以 Docker Compose 一键拉起 Live Helper Chat 4.97v 全套服务(Nginx + PHP-FPM + cronjob + php-resque + cobrowse + Redis + MariaDB),完成 .env 配置、Web 安装向导、安装后配置核对,并以管理员登录、Redis 会话、resque worker 消费、cronjob 调度、前后台聊天闭环完成端到端验证。本文所有命令与回显均来自真实部署实测(Docker 29.9.2 / Compose v5.6.1,2026-10-26)。

一、环境信息

项目本次实测值
宿主操作系统Debian 12.15 (bookworm)
Docker29.9.2(docker compose v5.6.1 子命令)
Live Helper Chat4.97v(GitHub 源码包 + 官方 lhc-php-resque 扩展仓)
编排文件docker-standalone 仓 docker-compose-standard.yml
Compose 项目名lhc-497v-stack
对外访问http://<宿主IP>:8081(LHC_PUBLIC_PORT)
数据库暴露仅宿主回环 127.0.0.1:3307(供宿主侧备份用)
cobrowse 暴露仅宿主回环 127.0.0.1:31130

官方 Docker 部署入口是独立仓库 github.com/LiveHelperChat/docker-standalone,提供 standard(无 NodeJS)与 nodejs 两种编排。本篇按 README 推荐的 standard 版实测,所有服务均使用官方预构建镜像,无需本地 build。

二、官方镜像实查(以 Docker Hub 实查为准)

官方镜像发布在 Docker Hub 的 remdex 个人组织下(注意:不是 livehelperchat 组织——该组织在 Docker Hub 上实测为空,count: 0)。standard 编排实际引用 4 个官方镜像 + 3 个上游公共镜像:

镜像用途tag实测大小
remdex/livehelperchat-phpPHP-FPM 应用服务仅 latest1.67 GB
remdex/livehelperchat-php-cronjob定时任务服务仅 latest1.71 GB
remdex/livehelperchat-php-resque后台队列 worker仅 latest约 1.7 GB
remdex/livehelperchat-cobrowse屏幕共享 NodeJS 服务仅 latest1.69 GB
nginx:latestweb 反代/静态latest243 MB
redis:alpine会话 + 队列后端alpine约 40 MB
mariadb数据库latest约 460 MB

两个实测结论值得注意:

  • 官方四个应用镜像只有 latest tag,没有版本号 tag。应用版本取决于你挂载进去的代码卷(livehelperchat/lhc_web),镜像本身只是运行环境(php:8.5-fpm 基底 + gd/ldap/imagick/imap/redis 等扩展)。
  • php-cronjob 与 php-resque 两个镜像的 Dockerfile 内容几乎完全一致(同样的 php:8.5-fpm 基底与扩展集),真正差异只在镜像内 /etc/cron.d/lhc 的计划任务条目:cronjob 镜像内置 15 条 cron.php 任务,resque 镜像内置 3 条 worker 看护任务。

三、编排结构:一个项目七个服务

docker-compose-standard.yml 定义 7 个服务,全部挂在同一个 bridge 网络 code-network:

服务镜像挂载的关键卷说明
webnginx:latest代码卷、nginx 配置唯一对外入口,${LHC_PUBLIC_PORT}:80
phpremdex/…-php代码卷、resque 扩展、scripts、php-fpm 覆盖配置PHP-FPM,处理全部动态请求
php-cronjobremdex/…-php-cronjob代码卷、resque 扩展、scripts常驻 cron -f,跑官方 15 条计划任务
php-resqueremdex/…-php-resque代码卷、resque 扩展、scripts、.env 只读挂载队列 worker 看护
cobrowseremdex/…-cobrowse无屏幕共享,31130 端口仅回环
redisredis:alpine无db0 存会话,db1 存 resque 队列
dbmariadb./dbdata数据库,3307 仅回环暴露

两个贯穿全部服务的挂载约定:

  • 代码卷共享:./livehelperchat/lhc_web:/code 同时挂给 web/php/php-cronjob/php-resque 四个服务,代码只有一份;
  • 扩展卷:./lhc-php-resque/lhcphpresque:/code/extension/lhcphpresque 把队列扩展挂进应用目录,配合 .env 里的 LHC_RESQUE_* 变量工作。

四、准备代码与扩展(install.sh 做了什么)

官方 install.sh 脚本负责准备两个代码目录,它做的每一步都值得在部署前过一遍:

# 1. 克隆主程序(本篇实测用 4.97v 发行包/源码包替代 master)
git clone --branch master https://github.com/LiveHelperChat/livehelperchat.git --depth 10
# 2. 克隆 php-resque 扩展
git clone --branch master https://github.com/LiveHelperChat/lhc-php-resque.git --depth 10
# 3. 把 resque 入口脚本拷进应用根目录
cp lhc-php-resque/lhcphpresque/doc/resque.php livehelperchat/lhc_web
# 4. 生成扩展自身的配置文件
cp lhc-php-resque/lhcphpresque/settings/settings.ini.default.php \
   lhc-php-resque/lhcphpresque/settings/settings.ini.php

随后是 4 处 sed 修改,各对应一个行为开关:

sed 目标修改作用
lhcphpresque/settings.ini.php'localhost' → 'redis'队列扩展连编排内的 redis 服务
lhc_web/settings/settings.ini.default.phpforce_virtual_host false → trueURL 不再带 index.php 前缀
同上 extensions 数组启用 lhcphpresque安装时把扩展写进应用配置
同上 webhooks.worker'http' → 'resque'Webhook 出站改走队列 worker

实测完成后核对(三处都改到位才算就绪):

grep -n "force_virtual_host\|'lhcphpresque'\|'worker' => 'resque'" \
  livehelperchat/lhc_web/settings/settings.ini.default.php
20:                    'force_virtual_host' => true,
49:                            'lhcphpresque'
99:                    'worker' => 'resque',

实测踩坑:GitHub 源码包(约 37 MB)不含 Composer 依赖,直接挂载后首次访问报 500(详见第八节排障一)。要么用官方 Release 页的 4.97v-with-dependencies.tgz(65.6 MB,内置 vendor),要么进 php 容器手工 php composer.phar install。从已装好的实例迁移代码时记得把 lhc_web/lib/vendor/ 一起带走。

五、配置 .env

cd docker-standalone
cp .env.default .env

必须核对的关键字段(全文见 .env.default):

变量默认值说明
LHC_SECRET_HASHCHANGE_ME_TO_SOMETHING必改,应用安装时会原样写入 secrethash,用于签名
LHC_PUBLIC_PORT8081web 服务对外端口
MYSQL_ROOT_PASSWORD / MYSQL_DATABASE / MYSQL_USER / MYSQL_PASSWORDlhcroot / lhc / lhc / lhc数据库四件套,安装向导里要填的 host 是 db
LHC_RESQUE_WORKERS_COUNT6resque worker 数
LHC_RESQUE_QUEUE*消费的队列名
REDIS_BACKEND / REDIS_BACKEND_DBredis:6379 / 1队列后端地址与 db 号
LHC_NODE_JS_PORT / REDIS_HOST8081 / redisNodeJS 相关(standard 版可忽略)

本次实测将 LHC_SECRET_HASH 设为自定随机串,其余保持默认。安装完成后可验证该值确实注入了应用配置:

docker exec lhc-497v-stack-php-1 grep secrethash /code/settings/settings.ini.php
'secrethash' => 'lhc497vstack9f3c81ab27e5',

六、启动与安装向导

6.1 拉镜像并启动

docker compose -f docker-compose-standard.yml pull
docker compose -f docker-compose-standard.yml up -d

实测启动后状态(项目名在 compose 文件里用顶层 name: 显式指定,容器名即 lhc-497v-stack-<服务>-1):

docker compose -f docker-compose-standard.yml ps --format 'table {{.Name}}\t{{.Status}}'
NAME                           STATUS
lhc-497v-stack-cobrowse-1      Up 10 minutes
lhc-497v-stack-db-1            Up 10 minutes
lhc-497v-stack-php-1           Up 10 minutes
lhc-497v-stack-php-cronjob-1   Up 10 minutes
lhc-497v-stack-php-resque-1    Up About a minute
lhc-497v-stack-redis-1         Up 10 minutes
lhc-497v-stack-web-1           Up 10 minutes

6.2 修正代码目录属主

首次访问前,按官方 README 把代码卷内三个运行时目录的属主交给容器内的 www-data(php:8.5-fpm 官方镜像中该用户为 uid/gid 33,宿主机上直接 chown 33:33):

cd livehelperchat/lhc_web
chown -R 33:33 cache settings var
ls -ld cache settings var
drwxrwxr-x 6 www-data www-data 4096 cache
drwxrwxr-x 2 www-data www-data 4096 settings
drwxrwxr-x 14 www-data www-data 4096 var

6.3 进入安装向导

浏览器访问 http://<宿主IP>:8081/,会自动 302 跳转到安装向导:

GET /  ->  302  Location: /site_admin/install/install

注意跳转后的 URL 是 /site_admin/install/install——没有 index.php 前缀,这正是第四节 force_virtual_host => true 的效果。与源码部署(URL 形如 /index.php/site_admin/...)相比,Compose 版的 URL 更短,nginx 配置已内置对应 rewrite。

安装向导共三步:

  1. 环境检查:实测 22 项全部 Yes(14 个目录写权限 + 7 个 PHP 扩展 + PHP 最低版本);
  2. 数据库:按 .env 填写——Username lhc、Password lhc、Host db(服务名,不是 127.0.0.1)、Port 3306、Name lhc;
  3. 初始管理员:admin / 强口令 / 邮箱 / 姓名与部门。

第三步提交后实测返回:

Installation was completed
Installation is complete. You can start by adding users and departments.

6.4 安装结果核对

应用配置在安装瞬间落盘为 settings/settings.ini.php,逐项核对关键值:

docker exec lhc-497v-stack-php-1 sh -c \
  "grep -A3 'extensions' /code/settings/settings.ini.php | head -4; \
   grep -B1 \"'worker'\" /code/settings/settings.ini.php | head -3; \
   grep -A6 \"'db'\" /code/settings/settings.ini.php | head -7"
'extensions' =>
array (
  0 => 'lhcphpresque',
),
'enabled' => '1',
'worker' => 'resque',
'db' =>
array (
  'host' => 'db',
  'user' => 'lhc',
  'password' => 'lhc',
  'database' => 'lhc',

数据库侧实测建表 156 张,管理员账号已写入:

SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='lhc';
SELECT username FROM lh_users;
tables_cnt
156
username
admin

七、安装后验证:四个维度

7.1 管理后台登录与会话落在 Redis

访问 http://<宿主IP>:8081/site_admin/user/login,用初始管理员登录,进入仪表盘可见 Hello Admin!。

会话存储验证:php-fpm 的池配置(conf/php-fpm/zz-lhc.conf)把 session 指向了 redis,登录后 Redis db0 出现会话键:

docker exec lhc-497v-stack-redis-1 redis-cli -n 0 keys 'PHPREDIS_SESSION*' | head -3
PHPREDIS_SESSION:f0d4296c28cd594d64e5f7c3ae57512b
PHPREDIS_SESSION:19fb88d002a82f91871e8c8bcb544acf
PHPREDIS_SESSION:250ac5b89b33fdbbdce0e60e2bb12f1a

7.2 坐席在线与前台聊天闭环

与源码部署一样,坐席默认离线,前台聊天窗此时显示 Chat is currently unavailable. Please try again later.。在后台把管理员账号置为长期在线(也可用接口):

TOKEN=$(grep -oE "csrf_token = '[a-f0-9]+'" 页面源码 | grep -oE '[a-f0-9]{32}')
curl -b 会话Cookie -H "X-CSRFToken: $TOKEN" \
  http://127.0.0.1:8081/site_admin/user/setalwaysonline/true
{"error":false}

之后前台 /index.php/chat/chatwidget(无 virtual host 时)或 /chat/chatwidget 出现提问表单,提交后聊天进入等待队列。数据库验证:

SELECT id,dep_id,nick,status FROM lh_chat;
SELECT id,chat_id,user_id,LEFT(msg,50) FROM lh_msg;
id  dep_id  nick     status
1   1       Visitor  0

id  chat_id  user_id  LEFT(msg,50)
1   1        0        Hello, testing docker stack chat.

坐席在后台 Chats List 打开会话回复,实测三条消息完整落库(user_id -1 为系统事件消息):

id  chat_id  user_id  LEFT(msg,60)
1   1        0        Hello, testing docker stack chat.
2   1        1        Hello! Reply from docker stack operator.
3   1        -1       Admin User has accepted the pending chat by sending a messag

7.3 resque worker 消费队列

php-resque 服务启动后,实测其 cron 计划(@reboot 启动 + 每分钟看护,见第八节排障三)拉起 worker,数量与 LHC_RESQUE_WORKERS_COUNT=6 一致:

docker exec lhc-497v-stack-php-resque-1 ps aux | grep resque | grep -v grep
/usr/local/bin/php resque.php
resque-1.2: Waiting for *     x6

Redis db1 中出现 worker 注册与统计键,安装期积压的 lhc_imap_copy 队列被即时消费清零:

docker exec lhc-497v-stack-redis-1 redis-cli -n 1 keys 'resque*'
docker exec lhc-497v-stack-redis-1 redis-cli -n 1 llen resque:queue:lhc_imap_copy
resque:queues
resque:stat:processed
resque:stat:processed:73609c0ee037:30:*   ...
resque:worker:73609c0ee037:30:*:started   ...
resque:workers
0

7.4 cronjob 调度

php-cronjob 服务常驻 cron -f,按镜像内 /etc/cron.d/lhc 的 15 条计划执行(每分钟的 workflow/webhook/transfer、每 5 分钟的 cron_5m、每日的 archive/encrypt/report 等)。实测每分钟调度已生效:

docker exec lhc-497v-stack-php-cronjob-1 ps aux | head -6
root  1    cron -f
root  576  CRON -f
root  577  CRON -f
root  578  CRON -f
www-data 586 /bin/sh -c cd /scripts && ./workflow.sh >> /dev/null 2>&1

7.5 运行状态端点

编排内置了监控端点(网络内可达,nginx 配置默认放行私网地址段):

docker exec lhc-497v-stack-web-1 curl -s 'http://web/fpm-status?json'
{"pool":"www","process manager":"dynamic","start time":1793005202,
 "start since":683,"accepted conn":22,"listen queue":0,
 "idle processes":4,"active processes":1,"total processes":5,
 "max active processes":1,"max children reached":0,
 "slow requests":0,"memory peak":8388608}

http://web/nginx_status 同理可取 nginx 连接计数。日志按服务取:docker compose -f docker-compose-standard.yml logs php(PHP 错误走 stderr)与 logs web(nginx)。

八、排障实录(三个首启真问题)

8.1 首页 500:Failed opening required 'lib/vendor/autoload.php'

现象:栈全部 Up,但 GET / 返回 500,php 容器日志:

PHP Warning:  require_once(lib/vendor/autoload.php): Failed to open stream:
No such file or directory in /code/index.php on line 30
PHP Fatal error:  Uncaught Error: Failed opening required 'lib/vendor/autoload.php'

原因:挂载的代码来自 GitHub 源码包,不含 Composer 依赖目录。 解决:改用官方 Release 的 4.97v-with-dependencies.tgz 部署代码卷;或进 php 容器按 getcomposer.org 流程装 composer.phar 后执行 php composer.phar install。实测从已有实例 docker cp 拷贝 lhc_web/lib/vendor/(144 MB)后立即恢复,GET / 变为 302 进入安装向导。

8.2 安装向导 500:Directory cache/cacheconfig/ not writable!

现象:代码就绪后访问向导直接输出异常栈。 原因:bind mount 进容器的 cache/settings/var 在宿主上是 root 属主,容器内 php-fpm 以 www-data(uid 33)运行无法写入。 解决:宿主上 chown -R 33:33 cache settings var(官方 README 的容器内 chown 方案等价)。

8.3 php-resque 容器起来了但 worker 未运行

现象:容器 Up,进程里只有 cron -f,Redis 无 resque worker 注册键。 原因:resque 镜像内的 /etc/cron.d/lhc 靠 @reboot ... phpresque.sh 拉起 worker,而容器场景下 cron 的 @reboot 不一定触发;备用的每分钟看护脚本 resque.sh 要求 /scripts/.enable-cron 标志文件存在才会启动 worker。 解决:手动执行一次 docker exec -d lhc-497v-stack-php-resque-1 /bin/sh -c 'cd /scripts && ./phpresque.sh';生产环境可按官方脚本约定 touch conf/scripts/.enable-cron 让看护脚本自动拉起。

8.4 补充:php-resque 官方镜像拉取受阻的等效替代

国内网络环境下 remdex/php-resque 镜像经多个加速通道长时间拉不完时,可用已拉取的 cronjob 镜像等效替代(两者 Dockerfile 完全同源):

docker tag remdex/livehelperchat-php-cronjob:latest remdex/livehelperchat-php-resque:latest

并在 compose 的 php-resque 服务追加一行挂载,把 resque 版计划任务盖回镜像内的 cronjob 版:

volumes:
  - ./Dockerfiles/php-resque/lhc/cron:/etc/cron.d/lhc:ro

实测该组合下 worker 正常拉起并消费队列(见 7.3)。

九、日常运维

  • 更新:git pull 三个仓库(主程序/php-resque/编排仓)→ 必要时 docker compose build --no-cache 或 pull → down && up -d;进 php 容器执行 php composer.phar update && php composer.phar install,再跑 php cron.php -s site_admin -c cron/util/update_database -p local 与 php cron.php -s site_admin -c cron/util/clear_cache。
  • 数据库备份:容器内无 mysqldump,官方设计是从宿主走仅回环暴露的 127.0.0.1:3307 连接 MariaDB 做导出。
  • HTTPS:由外层反代或改造 web 服务实现(官方 README 提供 certbot webroot 方案与站点配置样例);走反代时记得开启 settings.ini.php 的 proxy_mode 并配置转发头。
  • 安装后推荐设置(官方 README「After install todo」):Screen sharing 启用 NodeJs 支持并填 /wsnodejs/socket.io;Online tracking 勾选两项 cronjob 化;Workflow 勾选离场转移;settings.ini.php 与 lhcphpresque 配置里的 site_address 填实际站点地址。

十、小结

验证维度结果
七服务编排启动全部 Up,容器名前缀 lhc-497v-stack
.env 注入secrethash/worker 数/队列 db 均按 .env 生效
安装向导三步完成,156 张表落库
Redis 会话db0 PHPREDIS_SESSION 键随登录出现
聊天闭环访客发问 → 坐席接管回复,3 条消息落库
resque worker6 worker 注册,积压队列消费归零
cronjob15 条计划任务每分钟调度生效

Compose 版与源码部署的核心差异就三点:代码以卷挂载方式进容器、URL 少了 index.php 前缀(force_virtual_host)、会话与队列天然落在编排内的 Redis。记住第四节"源码包无 vendor"、第八节三个首启问题,部署基本可以一次走通。相关阅读:环境与选型见《Live Helper Chat 4.97v 介绍与选型指南》,源码方式部署见《Debian 12 安装 Live Helper Chat 4.97v 指南》,安装后的配置文件逐项说明见本专栏下一篇配置详解。