跳转到主要内容

概览

仓库自带一个多阶段 Dockerfile,它编译出独立的 mirobody 二进制,并产出一个精简的运行时镜像:
  1. builder —— Ubuntu 24.04,带完整的构建工具链和 dev 头文件;从系统包集合编译出 mirobody 可执行文件(vcpkg 仅用于 Windows;Linux 用 CMake find_package)。
  2. runtime —— Ubuntu 24.04,只带二进制实际链接的共享库(经 ldd 提取),外加用于出站 TLS 的 CA 证书。
镜像把 config.example.yml 烘焙成优先级最低的默认层。真实设置来自环境变量,或你挂载到 /app/config.yml 的一个 config.yml
Mirobody 以单个镜像交付,连接你自己的数据库(可选 Redis)运行 —— 没有需要额外拉起的 docker compose 套件。

构建并运行

1

克隆

git clone https://github.com/thetahealth/mirobody.git
cd mirobody
2

构建镜像

docker build -t mirobody:latest .
镜像默认链接 PostgreSQL 后端。用一个 build arg 选择其他 SQL 后端:
docker build --build-arg MIROBODY_DATABASE_BACKEND=POSTGRESQL_LEGACY -t mirobody:legacy .
3

准备 config.yml

cp config.example.yml config.yml
编辑 config.yml,设置至少一个 LLM 密钥外加你的数据库连接(参见 数据库后端):
config.yml
GOOGLE_API_KEY: 'AIza...'      # 或 OPENAI_API_KEY

PG_HOST: 'host.docker.internal'   # 一个容器内可达的 Postgres
PG_PORT: 5432
PG_USER: 'postgres'
PG_DBNAME: 'mirobody'
PG_PASSWORD: '...'
PG_ENCRYPTION_KEY: '...'
4

运行

镜像内部把 HTTP_PORT=80 固定好,并以非特权用户运行。把你的配置挂载覆盖烘焙进去的模板:
docker run -p 80:80 \
  -v $PWD/config.yml:/app/config.yml \
  mirobody:latest
容器监听 80 端口;示例把宿主机 80 端口映射到它。打开 http://localhost
5

验证

curl http://localhost/api/health   # -> ok
容器内的优先级是:环境变量 → 挂载的 config.yml → 远程配置 → 烘焙进去的 config.example.yml。因此你完全可以用 -e 环境变量而非文件来配置,例如 -e GOOGLE_API_KEY=... -e PG_HOST=...

数据库后端

SQL 后端是编译二进制的,所以在镜像构建时就固定了。
后端何时使用如何做
PostgreSQL服务器 / 多用户(桌面默认)默认镜像;把 PG_* 指向你的数据库
SQLite自包含、单文件、无外部 DB--build-arg MIROBODY_DATABASE_BACKEND=SQLITE 构建
PostgreSQL(旧 schema)已有的 res/sql/pg_legacy 部署--build-arg MIROBODY_DATABASE_BACKEND=POSTGRESQL_LEGACY
自带的 Dockerfile 为 PostgreSQL 后端安装了 libpq-dev。要构建 MySQL / DuckDB 镜像,先把相应的 -dev 包加到 Dockerfile 的 apt-get install 行里。

缓存(可选)

服务器默认使用进程内的内存缓存 —— 单实例无需 Redis。要在多副本间共享缓存状态,跑一个 Redis 并在配置里(或经环境变量)设置 REDIS_HOST(以及 REDIS_PORT / REDIS_PASSWORD)。

经环境变量配置

任何配置键都可被同名环境变量覆盖(最高优先级)。用于密钥很方便:
docker run -p 80:80 \
  -e GOOGLE_API_KEY="AIza..." \
  -e PG_HOST="db.internal" \
  -e PG_PASSWORD="..." \
  -e PG_ENCRYPTION_KEY="..." \
  -e CONFIG_ENCRYPTION_KEY="..." \
  mirobody:latest

管理

# 日志(二进制把日志打到 stdout)
docker logs -f <container>

# 停止(SIGTERM 触发优雅关停)
docker stop <container>

# 进入运行中的容器 shell
docker exec -it <container> /bin/sh

关于运行时镜像的说明

二进制相对其工作目录解析 res/htdocHTTP_ROOT)和 res/sql,所以 res/config.yml 与二进制一起位于 /app 下。Web 客户端在容器的端口上提供。
运行时镜像安装了 nodejs,以便服务器在启动时自动发现 Tanka 二维码登录的签名器。如果你不用 Tanka,它就是多余的 —— 设置 TANKA_LOGIN_ENABLED=false(或 TANKA_WASM_AUTODISCOVER=false)。
运行时镜像只有库(没有 curl/wget),所以没有内置的 HEALTHCHECK。在 Kubernetes 下,对 /api/health 使用 httpGet 存活/就绪探针。
服务器镜像为了保持精简,把 PDF/OCR/.xls 关掉了(经 xlnt 的 .xlsx 是内置的)。要启用 PDF/OCR,把依赖和 CMake 标志加到 Dockerfile —— 参见其中的注释和 文件处理

故障排查

重映射宿主机一侧:docker run -p 8080:80 …,或用 -e HTTP_PORT=8080 改内部端口并映射到它。
查看 docker logs <container> —— 最常见的原因是连不上数据库(PG_HOST),或 PG_ENCRYPTION_KEY 缺失/无效。连接设置错误会按设计直接让启动失败。
在容器内,宿主机是 host.docker.internal(Docker Desktop)—— 把 PG_HOST 设为它,而非 localhost
关于生产环境加固,参见 生产部署