Huginn 2026.10.14 Docker Compose 部署指南
用 Docker Compose 部署 Huginn 2026.10.14 的两种方案实测:单容器全功能镜像快速起步与 MySQL+Web+Worker 三容器生产拆分,含数据持久化、健康检查与升级。
Huginn 2026.10.14 Docker Compose 部署指南
目标:用 Docker Compose 部署 Huginn 2026.10.14,覆盖全功能镜像单容器快速起步与 MySQL+Web+Worker 三容器生产拆分两种方案,含数据持久化、健康检查、备份恢复与版本升级。已在 Ubuntu 22.04 实测通过。
源码部署适合深度定制,但对大多数自托管场景,官方镜像加 Compose 编排是最省心的路径。本文实测两种拓扑:方案 A 用全功能镜像单容器跑通(内置数据库,5 分钟起步);方案 B 按官方生产推荐拆分为 MySQL + Web + Worker 三容器。全部命令与回显来自真实执行记录。
💡 技术拓展:Huginn 官方镜像体系。官方发布两个镜像系列:
huginn/huginn(Docker Hub,全功能单进程镜像,内置 MariaDB,数据放容器内/var/lib/mysql,挂卷即持久化)与ghcr.io/huginn/huginn-single-process(GitHub Container Registry,单进程生产镜像,不含数据库,必须外接 MySQL,需配合command: /scripts/init bin/threaded.rb启动后台 Worker)。两个镜像的启动入口都会自动执行数据库建表与迁移,无需手工 rake。本文方案 A 用前者、方案 B 用后者。
一、环境信息
1.1 前置条件
实测环境:Ubuntu 22.04 + 已安装 Docker 29.8.1 与 Docker Compose v2 插件。Docker 与 Compose 的安装属于通用前置,此处直接验证版本:
root@huginn-server:~# docker --version
Docker version 29.8.1, build 04e9d0d
root@huginn-server:~# docker compose version
Docker Compose version v2.40.2
1.2 版本核实
本文以官方 tag v2026.10.14 镜像为准(Docker Hub 的 huginn/huginn 仓库以发布日期作为 tag):
root@huginn-server:~# docker pull huginn/huginn:v2026.10.14
v2026.10.14: Pulling from huginn/huginn
Digest: sha256:3b92454d115fd7ddb6c06461b41d4659d113cfd489f36178cd0f0d8bc596ddce
Status: Image is up to date for huginn/huginn:v2026.10.14
docker.io/huginn/huginn:v2026.10.14
(GHCR 生产镜像同理:docker pull ghcr.io/huginn/huginn-single-process:latest,官方未按日期打 tag,固定用 latest。)
二、方案 A:全功能镜像单容器部署
2.1 项目目录与编排文件
root@huginn-server:~# mkdir -p /opt/huginn && cd /opt/huginn
创建 /opt/huginn/docker-compose.yml:
services:
huginn:
image: huginn/huginn:v2026.10.14
container_name: huginn-full
restart: unless-stopped
ports:
- "3002:3000"
environment:
SEED_USERNAME: admin
SEED_PASSWORD: q1w2e3r4
INVITATION_CODE: q1w2e3r4-invite
TIMEZONE: Asia/Shanghai
TZ: Asia/Shanghai
volumes:
- ./mysql-data:/var/lib/mysql
要点:镜像内数据库监听容器内部 3000 之外还监听 3306,但单容器方案无需对外暴露数据库端口;./mysql-data 挂载到镜像内 /var/lib/mysql 实现数据持久化;首次启动自动建库、迁移、写入管理员。
2.2 首次启动
root@huginn-server:/opt/huginn# docker compose up -d
Container huginn-full Starting
Container huginn-full Started
首次启动要完成内置数据库初始化与 73 个 Rails 迁移,实测约 1~2 分钟。等待就绪后验证:
root@huginn-server:/opt/huginn# docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
huginn-full huginn/huginn:v2026.10.14 "/docker-entrypoint.…" huginn 41 seconds ago Up 12 seconds 0.0.0.0:3002->3000/tcp, [::]:3002->3000/tcp
root@huginn-server:/opt/huginn# curl -s -o /dev/null -w "http:%{http_code}\n" --max-time 10 http://127.0.0.1:3002/users/sign_in
http:200
2.3 登录验证
root@huginn-server:/opt/huginn# curl -s -c /tmp/ckA.txt http://127.0.0.1:3002/users/sign_in -o /tmp/lA.html
root@huginn-server:/opt/huginn# grep -oE "name=\"authenticity_token\" value=\"[^\"]+\"" /tmp/lA.html | head -1 | sed "s/.*value=\"//;s/\"$//" > /tmp/csrf.txt
root@huginn-server:/opt/huginn# curl -s -b /tmp/ckA.txt -o /dev/null -w "login:%{http_code}\n" -X POST http://127.0.0.1:3002/users/sign_in --data-urlencode "authenticity_token=$(cat /tmp/csrf.txt)" --data-urlencode "user[login]=admin" --data-urlencode "user[password]=q1w2e3r4" -H "Referer: http://127.0.0.1:3002/users/sign_in"
login:302
(302 即登录成功跳转;浏览器访问 http://192.168.1.62:3002/ 用 admin / q1w2e3r4 登录。)
2.4 方案 A 实测踩坑实录
⚠️ 实测排障一:数据目录属主。宿主机
./mysql-data若由 root 创建,镜像内进程(官方镜像以 uid 1001、gid 0 的default用户运行)无写权限,容器反复重启且日志报bootstrap failed。实测解决:root@huginn-server:/opt/huginn# chown -R 1001:0 ./mysql-data root@huginn-server:/opt/huginn# docker compose restart也可反过来从容器侧校验写权限:
root@huginn-server:/opt/huginn# docker exec huginn-full sh -c "touch /var/lib/mysql/test-write && echo WRITE-OK || echo WRITE-DENIED" WRITE-OK
⚠️ 实测排障二:残留初始化文件导致 abort。属主修正后若仍起不来,日志出现
mysqld: [ERROR] ... --datadir相关 abort 且容器频繁重启,实测根因是首次失败留下的半成品文件(容器内/tmp/mysql与挂载目录中的临时库文件)。清理后重启:root@huginn-server:/opt/huginn# docker exec huginn-full sh -c "rm -rf /tmp/mysql" root@huginn-server:/opt/huginn# docker compose down && rm -rf ./mysql-data && docker compose up -d(
down加删除数据目录会丢弃全部已有数据,仅限首次部署排障时使用。)
三、方案 B:MySQL + Web + Worker 三容器生产部署
3.1 拓扑说明
方案 A 的 Worker 与 Web 在同一进程内(全功能镜像默认同时跑 Web 与后台线程),流量大或 Agent 多时建议拆分:MySQL 独立容器、Web 容器只跑 Puma、Worker 容器跑 bin/threaded.rb 后台线程。官方生产镜像 ghcr.io/huginn/huginn-single-process 正是为此设计。
3.2 编排文件与数据库环境
创建项目目录 /opt/huginn-prod,写入 /opt/huginn-prod/mysql.env(数据库与 Huginn 共用的连接参数):
MYSQL_ROOT_PASSWORD=q1w2e3r4
MYSQL_DATABASE=huginn
HUGINN_DATABASE_ADAPTER=mysql2
HUGINN_DATABASE_HOST=mysql
HUGINN_DATABASE_PORT=3306
HUGINN_DATABASE_USERNAME=root
HUGINN_DATABASE_PASSWORD=q1w2e3r4
HUGINN_DATABASE_NAME=huginn
HUGINN_DATABASE_ENCODING=utf8mb4
写入 /opt/huginn-prod/docker-compose.yml:
services:
mysql:
image: mysql:8.4
restart: always
env_file:
- mysql.env
volumes:
- mysql-data:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -p$$MYSQL_ROOT_PASSWORD"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
web:
image: ghcr.io/huginn/huginn-single-process:latest
restart: always
ports:
- "3000:3000"
env_file:
- mysql.env
environment:
SEED_USERNAME: admin
SEED_PASSWORD: q1w2e3r4
TIMEZONE: Asia/Shanghai
depends_on:
mysql:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:3000/users/sign_in >/dev/null || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 120s
threaded:
image: ghcr.io/huginn/huginn-single-process:latest
command: /scripts/init bin/threaded.rb
restart: always
env_file:
- mysql.env
depends_on:
mysql:
condition: service_healthy
web:
condition: service_started
volumes:
mysql-data:
关键点:
- MySQL healthcheck 用
mysqladmin ping,$$是 Compose 对$的转义(避免被宿主 shell 展开); web健康检查直接探测登录页,start_period: 120s给首次自动迁移留足时间;threaded服务的command: /scripts/init bin/threaded.rb是官方镜像约定的 Worker 启动方式,/scripts/init会先完成迁移检查再拉起后台线程。
3.3 启动与状态核实
root@huginn-server:/opt/huginn-prod# docker compose up -d
Container huginn-prod-web-1 Starting
Container huginn-prod-web-1 Started
Container huginn-prod-mysql-1 Waiting
Container huginn-prod-mysql-1 Healthy
Container huginn-prod-threaded-1 Starting
Container huginn-prod-threaded-1 Started
(Compose v2 的依赖等待输出顺序如上:先启动带 healthcheck 依赖声明的 web,等 mysql 健康检查通过后拉起 threaded;首次全新部署 MySQL 还需初始化,实测全程约 1 分钟。)
root@huginn-server:/opt/huginn-prod# docker compose ps
NAME STATUS PORTS
huginn-prod-mysql-1 Up 20 minutes (healthy) 3306/tcp, 33060/tcp
huginn-prod-threaded-1 Up 20 minutes 3000/tcp
huginn-prod-web-1 Up 20 minutes (healthy) 0.0.0.0:3000->3000/tcp, [::]:3000->3000/tcp
Web 容器内确认 Puma 进程(官方镜像内置 curl,健康检查可用):
root@huginn-server:/opt/huginn-prod# docker exec huginn-prod-web-1 ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
default 1 0.2 0.7 1107696 238556 ? Ssl 00:53 0:02 puma 8.0.2 (tcp://0.0.0.0:3000) [app]
default 686 0.0 0.7 1378436 238640 ? Sl 00:53 0:00 puma: cluster worker 0: 1 [app]
Worker 容器确认后台线程进程:
root@huginn-server:/opt/huginn-prod# docker top huginn-prod-threaded-1 | grep -oE "threaded.rb"
threaded.rb
3.4 自动迁移与管理员初始化证据
官方镜像启动入口会自动执行数据库准备,Web 容器日志可见迁移记录:
root@huginn-server:/opt/huginn-prod# docker logs huginn-prod-web-1 2>&1 | grep -iE "Migrating" | head -4
I, [2026-10-17T02:05:31.745424 #413] INFO -- : Migrating to DeviseCreateUsers (20120728210244)
== 20120728210244 DeviseCreateUsers: migrating ================================
== 20120728210244 DeviseCreateUsers: migrated (0.0169s) =======================
I, [2026-10-17T02:05:31.766718 #413] INFO -- : Migrating to AddAdminToUsers (20120728215449)
登录验证(同 2.3,端口 3000)实测返回 login:302;数据库侧核实种子数据:
root@huginn-server:/opt/huginn-prod# docker exec huginn-prod-mysql-1 sh -c "mysql -h127.0.0.1 -uroot -pq1w2e3r4 -e 'SELECT COUNT(*) agents FROM huginn.agents; SELECT id,username FROM huginn.users;'" 2>/dev/null
agents
7
id username
1 admin
(7 个示例 Agent 与 admin 管理员就位,与源码部署 db:seed 结果一致。)
四、日常运维命令
4.1 日志与状态
root@huginn-server:/opt/huginn-prod# docker compose logs -f web
...
^C
root@huginn-server:/opt/huginn-prod# docker compose logs --tail 20 threaded
...
4.2 重启与停止
root@huginn-server:/opt/huginn-prod# docker compose restart
Restarting huginn-prod-web-1 ... done
root@huginn-server:/opt/huginn-prod# docker compose down
Container huginn-prod-threaded-1 Stopping
Container huginn-prod-threaded-1 Stopped
Container huginn-prod-web-1 Stopping
Container huginn-prod-web-1 Stopped
Container huginn-prod-mysql-1 Stopping
Container huginn-prod-mysql-1 Stopped
Container huginn-prod-threaded-1 Removing
Container huginn-prod-threaded-1 Removed
Container huginn-prod-web-1 Removing
Container huginn-prod-web-1 Removed
Container huginn-prod-mysql-1 Removing
Container huginn-prod-mysql-1 Removed
Network huginn-prod_default Removing
Network huginn-prod_default Removed
(down 默认保留 named volume mysql-data,加 -v 才会连数据一起删除,慎用。)
4.3 备份与恢复
方案 B 数据库在 named volume 中,标准做法用 mysqldump:
root@huginn-server:/opt/huginn-prod# docker exec huginn-prod-mysql-1 sh -c "mysqldump -h127.0.0.1 -uroot -pq1w2e3r4 huginn" 2>/dev/null > huginn-backup-2026-10-17.sql
root@huginn-server:/opt/huginn-prod# ls -lh huginn-backup-2026-10-17.sql
-rw-r--r-- 1 root root 22K Oct 17 09:15 huginn-backup-2026-10-17.sql
root@huginn-server:/opt/huginn-prod# head -3 huginn-backup-2026-10-17.sql | tail -2
-- Host: 127.0.0.1 Database: huginn
-- ------------------------------------------------------
恢复:
root@huginn-server:/opt/huginn-prod# docker exec -i huginn-prod-mysql-1 sh -c "mysql -h127.0.0.1 -uroot -pq1w2e3r4 huginn" 2>/dev/null < huginn-backup-2026-10-17.sql
方案 A 的数据在 ./mysql-data 目录,停服后整目录打包即可:
root@huginn-server:/opt/huginn# docker compose stop huginn
Container huginn-full Stopped
root@huginn-server:/opt/huginn# tar czf huginn-full-mysql-2026-10-17.tgz mysql-data/
root@huginn-server:/opt/huginn# ls -lh huginn-full-mysql-2026-10-17.tgz
-rw-r--r-- 1 root root 5.3M Oct 17 09:16 huginn-full-mysql-2026-10-17.tgz
五、版本升级
以 v2026.10.14 升级到未来新 tag 为例(方案 B):
root@huginn-server:/opt/huginn-prod# docker exec huginn-prod-mysql-1 sh -c "mysqldump -h127.0.0.1 -uroot -pq1w2e3r4 huginn" 2>/dev/null > pre-upgrade.sql
root@huginn-server:/opt/huginn-prod# docker pull ghcr.io/huginn/huginn-single-process:latest
root@huginn-server:/opt/huginn-prod# docker compose up -d web threaded
[+] Running 3/3
✔ Container huginn-prod-web-1 Recreated
✔ Container huginn-prod-threaded-1 Recreated
✔ Container huginn-prod-web-1 Started
新镜像首次启动自动执行增量迁移(日志 grep Migrating 可见新迁移编号)。升级后用 2.3/3.4 的探活与登录命令回归验证。回滚:改回旧镜像 tag 后 docker compose up -d,配合 pre-upgrade.sql 恢复数据。
六、常见问题
Q:容器反复重启,日志见 Permission denied 或 mysqld abort?
A:数据目录属主问题加残留文件,按 2.4 节两步处理:chown -R 1001:0 ./mysql-data 后清理 /tmp/mysql 与半成品数据目录重启。
Q:Web 一直 unhealthy,日志停在同一批 Migrating 上?
A:首次启动迁移未完成,健康检查的 start_period 要给足;MySQL healthcheck 未通过时 Web 不会启动,先 docker compose ps 看 mysql 是否 healthy。
Q:depends_on 里 condition: service_healthy 报 Compose 版本不支持?
A:该写法需要 Compose v2,用 docker compose version 确认;老版 docker-compose 1.x 不支持条件依赖。
Q:Worker 容器起了但 Agent 不调度?
A:确认 command: /scripts/init bin/threaded.rb 没有遗漏;查看 docker compose logs threaded 是否有数据库连接报错——Worker 与 Web 必须共用同一份 mysql.env。