DooTask 安装部署实战:`./cmd install` 一键安装流程、前置检查与故障处理指南

原创2026-10-14 21:07:582,187 阅读
文章标签:后端前端桌面应用协同办公

DooTask 安装部署实战:./cmd install 一键安装流程、前置检查与故障处理指南

导读

DooTask 的安装被设计为一条封装完整的命令 ./cmd install(赋权 → 起容器 → composer install → key:generate → migrate --seed → up -d),但"命令好敲"不等于"可以随便敲"。本文以官方安装流程为骨架,结合仓库内 cmd 脚本的真实实现,系统讲解安装前必须完成的 5 项前置检查、--port 与 --relock 两个关键参数的选择逻辑、安装执行与安装后的初始化(数据库密码重置),以及各类典型失败场景的处理矩阵。读完本文,你将能够在服务器上以"刚性流程、单次确认、失败即停"的方式安全完成 DooTask 的首次部署,并理解每一步背后的脚本实现依据。

一、安装的核心模型:单命令封装与职责边界

./cmd install 已经把整套安装封装为一条命令。从 cmd 的 handle_install() 函数可以还原出真实的执行链路,顺序为:

  1. check_sudo:校验是否以 root 执行;
  2. check_instance:校验 APP_ID 是否与其他实例冲突;
  3. (可选)--relock 清理依赖锁文件;
  4. permission_fix + 目录权限检测:修复并验证 bootstrap/cache、docker、public、storage 等可写目录;
  5. 端口设置与 check_port 端口占用检测;
  6. docker-compose up php -d:先拉起 PHP 容器(依赖 mariadb、redis 健康后启动);
  7. composer install --optimize-autoloader:安装 PHP 依赖,并校验 vendor/autoload.php 是否生成;
  8. php artisan key:generate:生成应用密钥(APP_KEY 为空时);
  9. switch_debug "false":写入生产模式;
  10. php artisan migrate --seed:建库、迁移并灌入种子数据;
  11. docker-compose up -d --remove-orphans:启动全部容器;
  12. wait_php_healthy 兜底拉起 nginx,避免首启时序竞态;
  13. 输出访问地址,并调用 docker/mysql/repassword.sh 提示数据库密码。

因此,安装流程的正确姿态是:做好安装前把关、选对参数、执行前与用户确认、遇到已知失败按矩阵处理,而不是把脚本逻辑拆开重做,也不是遇错就"顺手改改别的地方"。

二、前置检查:全部通过才能继续

执行 ./cmd install 前,必须依次确认以下 5 项,任何一项不满足都不得继续。

1. 工作目录:必须在项目根

必须确认当前目录是项目根,且存在以下三个文件:

  • cmd(管理脚本,1229 行,见 cmd)
  • docker-compose.yml(容器编排定义,见 docker-compose.yml)
  • .env.docker(环境变量模板,见 .env.docker)

脚本通过 WORK_DIR="$(pwd)" 取当前目录(见 cmd),容器将把项目目录以 -v ./:/var/www 的方式挂载进 PHP 与 nginx 容器,因此必须在正确的目录下执行。

2. Docker 与 Docker Compose:可用且 daemon 在运行

脚本内置 check_docker() 检查(见 cmd),但提前确认能更早报错:

  • docker --version 可用;
  • docker-compose version 或 docker compose version(v2+)可用;脚本会拒绝 v1 版本("Docker-compose 版本过低,请升级至 v2+");
  • Docker daemon 处于运行状态。

3. Node.js ≥ 20

check_node()(见 cmd)会同时检查 npm 与 node,并拒绝 v1x 版本("Node.js 版本过低,请升级至 v20+")。Node 主要用于前端构建(npx vite build)等场景,安装阶段的前置校验可以提前暴露环境问题。

4. APP_ID 不冲突

若 .env 中已有 APP_ID 且被其他实例占用,脚本 check_instance()(见 cmd)会报错。其实现原理是:通过 docker inspect dootask-php-${APP_ID} 查找容器的 /var/www 挂载来源({{range .Mounts}}{{if eq .Destination "/var/www"}}{{.Source}}{{end}}{{end}}),如果挂载路径存在且不等于当前工作目录,说明该 APP_ID 已被另一台实例使用。

此时必须停止,提示用户先清空 .env 里的 APP_ID 和 APP_IPPR 再重新安装。

5. sudo:必须 root 执行

check_sudo()(见 cmd)校验 $EUID -ne 0,非 root 直接报"请使用 sudo 运行此脚本"并退出。因此安装必须使用:

sudo ./cmd install

⚠️ 重操作提醒:安装会创建数据库并执行 migrate --seed(灌入种子数据)。在已有数据的环境上重装前,务必与用户确认,避免覆盖现有数据。

前置检查全部通过后,汇报检查结果,向用户确认一次再执行。

三、参数选择:只有两个参数,按需使用

参数 作用 何时用
--port <端口> 指定 HTTP 端口(脚本会做端口占用检测) 用户要自定义端口,或默认端口被占
--relock 删除 node_modules/package-lock.json/vendor/composer.lock 后重装 谨慎:仅在依赖锁损坏、用户明确要求重建锁时用,会拖慢安装

--port 的底层检测

从源码看(cmd),check_port() 的占用检测方式很轻量:docker run --rm -p "${port}:80" --entrypoint true nginx:alpine——用一次容器端口绑定来探测端口是否可用,绑定失败即报"端口 xxx 已被占用,请指定其他端口"。默认端口来自 .env 的 APP_PORT,模板默认值为 2222(见 .env.docker)。

--relock 的影响范围

handle_install() 在检测到 --relock 时会执行:

rm -rf node_modules package-lock.json vendor composer.lock

随后重新执行 composer install 与前端依赖安装。由于删除范围包含 vendor 和 node_modules,重建依赖会显著拉长安装时间,因此默认不加,仅在用户明确要求或依赖锁确实损坏时使用。

不确定时不要自作主张加参数,按需询问用户。

四、执行安装

确认后执行(按用户选择带上参数):

sudo ./cmd install
# 或: sudo ./cmd install --port 8080

安装过程中的关键子步骤与源码对应关系:

阶段 脚本实现 说明
目录赋权 permission_fix() 项目根设为 755,可写目录归还给 SUDO_UID 调用用户并补组写权限
权限验证 目录权限检测循环 用 nginx:alpine 容器挂载各可写目录后 touch dootask.lock,逐个验证 bootstrap/cache、docker、public、storage 四个目录可写
依赖安装 composer install --optimize-autoloader 在 PHP 容器内执行,失败时检查 vendor/autoload.php 是否存在
密钥生成 php artisan key:generate 仅当 APP_KEY 为空时执行
数据库初始化 php artisan migrate --seed 建表 + 灌入种子数据(这是重操作的关键步骤)
全量启动 docker-compose up -d --remove-orphans 启动 nginx、php、redis、mariadb、appstore 全部服务

容器拓扑一览

安装后系统中将出现 5 个容器(容器名均带 APP_ID 后缀,见 docker-compose.yml):

  • dootask-php-${APP_ID}:基于 kuaifan/php:swoole-8.4 镜像,运行 Laravel/Swoole 应用与 Supervisor 进程;
  • dootask-nginx-${APP_ID}:nginx:alpine,映射 ${APP_PORT}:80 与 ${APP_SSL_PORT:-0}:443;
  • dootask-redis-${APP_ID}:缓存/队列/会话后端;
  • dootask-mariadb-${APP_ID}:mariadb:10.7.3,数据目录挂载 ./docker/mysql/data;
  • dootask-appstore-${APP_ID}:应用市场容器,需要访问 Docker socket。

网络 dootask-networks-${APP_ID} 与数据卷 dootask-shared-data-${APP_ID}、dootask-redis-data-${APP_ID} 也按 APP_ID 隔离,这正是 APP_ID 冲突检测存在的意义——保证多实例互不干扰。

五、安装成功后:访问地址与数据库密码重置

安装成功后脚本会输出访问地址:

地址: http://127.0.0.1:<APP_PORT>

并自动调用 container_exec mariadb "sh /etc/mysql/repassword.sh"(脚本末尾,见 cmd)。该脚本以卷挂载方式存在于 MariaDB 容器内(docker-compose.yml),源码见 docker/mysql/repassword.sh。

repassword.sh 支持三种用法:

./repassword.sh                      # 重置第一个管理员用户密码(随机生成 16 位)
./repassword.sh 123                  # 重置 ID=123 的用户密码(随机生成)
./repassword.sh user@example.com     # 重置指定邮箱用户的密码(随机生成)
./repassword.sh 123 newpass          # 重置 ID=123 的用户密码为 "newpass"
./repassword.sh user@example.com newpass  # 重置指定邮箱用户的密码为 "newpass"

其实现要点:纯数字参数按 userid 查询,其余按 email 查询;默认查询 identity LIKE '%,admin,%' 的第一个管理员;密码采用 md5(md5(明文) + 随机加密盐) 的双重哈希写入 users 表的 encrypt/password 字段。因此向用户报告时应包含两样信息:访问地址(http://127.0.0.1:<APP_PORT>)与数据库密码提示(管理员账号密码以脚本输出为准)。

六、失败处理:立即停止,原样报告

任何步骤失败立即停止,原样报告错误信息。不要自动重试,不要自动跳过。

常见失败与对应处理:

失败现象 处理方式
APP_ID(xxx)已被其他实例使用 停止,让用户清空 .env 的 APP_ID/APP_IPPR 再装
端口 xxx 已被占用 停止,让用户换 --port
目录【xxx】权限不足 / 目录权限检测失败 这是目录属主/权限问题,引导用户统一修复权限后重装,不要自行随意 chmod/chown
安装依赖失败(composer) 报告,交用户决定(常因网络/镜像源)

这些报错信息都能在 cmd 的多语言文案表中找到对应原文(例如"APP_ID(())已被其他实例使用:()"、"端口 () 已被占用,请指定其他端口"、"目录【()】权限不足!"),方便逐字比对定位。

七、禁止项与操作纪律(Red Flags)

禁止项速查

错误做法 正确做法
不加 sudo 直接 ./cmd install 用 sudo ./cmd install(脚本强制 root)
失败后"我再试一次"或自动跳过 立即停止,交还用户
在已有数据环境上不问就重装 先确认会 migrate --seed,可能影响现有数据
遇权限报错自己乱 chmod/chown 走权限修复流程统一处理
不问就加 --relock 默认不加;仅用户明确要求或锁损坏时用

Red Flags:出现这些念头立即停下

  • "端口/权限报错了我顺手帮 TA 改一下别的" → 停下,只处理本次报的问题,按指引走对应处理流程;
  • "种子数据应该没事,直接重装" → 不,先确认是否会覆盖现有数据;
  • "sudo 麻烦,先试试不加" → 不,install 必须 root。

这条纪律的本质来自脚本实现:check_sudo 在 handle_install 的第一步就会强制退出非 root 执行(cmd),migrate --seed 又是数据库写操作(cmd 附近),所以"违反字面规则 = 违反流程精神",安装过程中的每一步确认都不应被省略。

八、延伸:环境变量与安装的隐含初始化

虽然 ./cmd install 不需要手工编辑配置,但了解 .env 的初始化逻辑有助于排查问题。脚本中的 env_init()(见 cmd)在安装时会:

  1. 若不存在 .env,则从 .env.docker 复制生成;
  2. DB_ROOT_PASSWORD 为空时随机生成 16 位;
  3. APP_ID 为空时随机生成 6 位;
  4. APP_IPPR 为空时生成 10.x.y 形式的内部网段。

.env.docker 中的核心默认值(见 .env.docker):

变量 默认值 说明
APP_NAME DooTask 应用名
APP_PORT 2222 HTTP 访问端口
APP_ID / APP_IPPR 空(安装时随机生成) 实例唯一标识与内网段,多实例隔离的关键
DB_DATABASE / DB_USERNAME / DB_PASSWORD dootask / dootask / 123456 业务库账号(root 密码另行随机生成)
DB_PREFIX pre_ 表前缀,repassword.sh 的查询也依赖它
LARAVELS_LISTEN_PORT 20000 Swoole 内部监听端口,供 nginx 反向代理与健康检查使用

安装完成后,如需修改端口、访问地址或环境变量,可分别使用 ./cmd port <端口>、./cmd url <地址>、./cmd env <键> <值>;日常维护还有 ./cmd update、./cmd mysql backup、./cmd artisan 等命令(见 cmd 的帮助信息),但注意它们同样遵循"确认后执行、失败即停"的操作纪律。

结语

DooTask 的安装之所以能保持稳定可复现,关键在于"单命令封装 + 刚性前置把关"的设计:脚本把易错的重操作(建库、迁移、灌种子数据)收敛进 ./cmd install,而操作者只需守住前置检查、参数选择、单次确认、失败即停四条纪律。理解了 cmd 中 check_sudo、check_docker、check_node、check_instance、check_port、handle_install 等函数的实现,你就能在任何一次安装异常时快速定位问题属于环境、参数还是权限,并按照处理矩阵安全地推进到部署成功。

登录后查看全文
dootask