ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Huginn 多进程 Docker 镜像深度解析:从单容器部署、数据库联动到出站流量管控

Huginn 多进程 Docker 镜像深度解析:从单容器部署、数据库联动到出站流量管控 Huginn 多进程 Docker 镜像深度解析从单容器部署、数据库联动到出站流量管控【免费下载链接】huginnCreate agents that monitor and act on your behalf. Your agents are standing by!项目地址: https://gitcode.com/gh_mirrors/hu/huginn本文以 Huginn 仓库中的 docker/multi-process/README.md 为主线讲清这个单容器、多进程官方 Docker 镜像的内部结构与全部部署姿势容器内 supervisord 如何编排 mysqld、foreman 与 Smokescreen 三个进程init/setup_env/bootstrap.sh/foreman.sh脚本链如何完成.env生成、数据库探测、迁移与种子数据填充以及 MySQL 5.7 数据卷升级到 8.0 的完整流程。读完本文你可以独立选择内置 MySQL、链接数据库容器或外部数据库三种方式部署 Huginn并理解每个环境变量在启动脚本中的真实作用点。一、镜像定位与整体架构该镜像的运行目标是提供一个可链接linkable的 Huginn 实例既能在自己内部启动一个 MySQL 让 Huginn 开箱即用也能通过 Docker 容器链接或网络环境变量无缝对接外部的 MySQL/MariaDB/PostgreSQL。镜像采用与 classic GitLab 镜像相同的多进程模式由 Dockerfile 构建其关键构建步骤包括基础镜像为rubylang/ruby:4.0.6-jammy通过多阶段构建golang:1.27-alpine编译并内嵌一个固定 commit 版本的 Smokescreen 出站代理二进制以非 root 用户UID 1001运行这直接关系到下文数据卷的权限要求构建期执行npm install --production、bootsnap precompile与rake assets:clean assets:precompile运行时不再预编译资产EXPOSE 3000声明 Web 端口VOLUME /var/lib/mysql声明内置 MySQL 数据卷最终CMD [/scripts/init]由 init 脚本拉起 supervisord。容器内部是一个由 supervisord.conf 管理的进程树通过/etc/supervisor/conf.d/下的四个 program 配置实现分层启动程序配置文件启动方式职责bootstrapbootstrap.confautostarttrue执行 bootstrap.sh完成 Smokescreen/MySQL 的前置启动再手动拉起 foremanmysqldmysqld.confautostartfalse由 bootstrap.sh 中supervisorctl start mysqld触发内置 MySQL 服务autorestarttruesmokescreensmokescreen.confautostartfalse仅在ENABLE_SMOKESCREENtrue时由 bootstrap.sh 启动监听127.0.0.1:4750的出站代理foremanforeman.confautostartfalse由 bootstrap.sh 最后启动执行数据库创建/迁移/种子再foreman start跑 Huginn 主进程这套bootstrap 只做引导、业务进程按需拉起的设计保证 Huginn 的 web/jobs 进程一定在数据库就绪之后才启动。二、启动流程init → setup_env → supervisord → bootstrap → foreman2.1 入口脚本 init容器启动时执行init它做三件事清理遗留的server.pidsource /scripts/setup_env生成环境变量文件若设置了DO_NOT_RUN_JOBS用sed把 Procfile 中的jobs:行注释掉即只跑 web 进程常用于把后台任务拆到独立容器最后exec supervisord接管容器。README 提示 Huginn 完整启动不到一分钟实际耗时的主要成分是数据库迁移与种子阶段。2.2 环境解析 setup_env这是整个镜像的配置中枢它的核心逻辑与官方 README 的说明一一对应DATABASE_URL最高优先级。若设置了DATABASE_URL脚本用 Ruby 解析 URL推导DATABASE_ADAPTERmysql前缀映射为mysql2postgres映射为postgresql并拆出 host/port/user/password/dbname 写入HUGINN_DATABASE_*。探测链接容器。从源码结构看判断顺序是MYSQL_PORT_3306_TCP_ADDR存在或显式DATABASE_ADAPTERmysql2且给了DATABASE_HOST→ 使用链接的 MySQL默认端口 3306否则POSTGRES_PORT_5432_TCP_ADDR存在或DATABASE_ADAPTERpostgresql且有DATABASE_HOST→ 使用链接的 PostgreSQL默认端口 5432两者都没有 →START_MYSQLtrue启动容器内置 MySQL。变量合并规则。脚本先把 .env.example 拷贝到/tmp/再对其中每个变量按HUGINN_$var $var .env.example 默认值的优先级取值写入生成的.env即/tmp/.env最终落盘为/app/.env。这也解释了 README 中所有.env.example里的变量都可以用来覆盖默认值这一说法——包括DO_NOT_CREATE_DATABASE、DO_NOT_SEED、ENABLE_SMOKESCREEN等。内置 MySQL 时追加DATABASE_SOCKET/app/tmp/sockets/mysqld.sock让 Rails 通过本地 socket 连库。Smokescreen 代理注入当ENABLE_SMOKESCREENtrue且未显式设置OUTBOUND_PROXY时自动写入OUTBOUND_PROXYhttp://127.0.0.1:4750。2.3 bootstrap.sh前置服务编排bootstrap 程序在 supervisord 中自动启动按顺序若ENABLE_SMOKESCREENtruesupervisorctl start smokescreen若START_MYSQLtrueDATABASE_ADAPTERpostgresql时直接报错退出内置数据库只支持 MySQLPostgreSQL 必须外部提供首次运行/var/lib/mysql/mysql不存在时执行mysqld --initialize-insecure --user$(whoami) --datadir/tmp/mysql初始化再把数据搬到/var/lib/mysql执行 upgrade-mysql 脚本——若检测到数据目录是 MySQL 5.7通过读取ib_logfile0redo log 头部的版本串判断会下载官方 MySQL 5.7.44 救援二进制先做 GPG 签名校验以innodb_fast_shutdown0做一次干净停机让后续 MySQL 8.0 能自动完成数据字典升级。该脚本只支持x86_64其他架构会提示先用 amd64 镜像跑一遍干净停机写入mysql_init.sqlALTER USER rootlocalhost ...用环境变量里的密码重置 root随后supervisorctl start mysqld并以mysqladmin status轮询等待最多等 120 秒失败即exit 1最后supervisorctl start foreman。2.4 foreman.sh迁移、种子与主进程foreman 程序启动后先等待数据库连接INTENTIONALLY_SLEEP可强制先睡 N 秒develop.yml 中设为 10DATABASE_INITIAL_CONNECT_MAX_RETRIES配合rake database_test:ping做最多 N 次重连每次间隔DATABASE_INITIAL_CONNECT_SLEEP默认 5 秒应对外部数据库冷启动慢于 Huginn 的场景。然后依次执行三个幂等步骤每步都可被对应的开关变量跳过# We may need to try and create a database if [ -z ${DO_NOT_CREATE_DATABASE} ]; then bundle exec rake db:create fi # Assuming we have a created database, run the migrations and seed it idempotently. if [ -z ${DO_NOT_MIGRATE} ]; then bundle exec rake db:migrate fi if [ -z ${DO_NOT_SEED} ]; then bundle exec rake db:seed fi # Start huginn exec bundle exec foreman start其中rake db:migrate即 README 所说的幂等的数据库迁移rake db:seed会创建初始 admin 账号并导入默认场景即 README 提到的默认 6 个 agents。三、数据库配置三种连接方式README 明确了三种模式的选择逻辑与setup_env源码完全吻合3.1 内置 MySQL默认不指定任何数据库链接变量时START_MYSQLtrue容器内启动 MySQL 并导出/var/lib/mysql卷。README 给出两条必须记住的约束必须导出数据卷或使用外部数据库容器否则更新 Huginn 会丢失数据镜像以 UID 1001 的非 root 用户运行挂载卷的属主/权限必须正确777 或 chown 1001否则 MySQL 无法启动且镜像不提供 GUID/PUID 一类的权限环境变量。3.2 链接--link数据库容器init通过容器链接自动注入的环境变量感知数据库MYSQL_PORT_3306_TCP_ADDR MYSQL_PORT_3306_TCP_PORT以及POSTGRES_PORT_5432_TCP_ADDR POSTGRES_PORT_5432_TCP_PORTREADME 建议选用支持用环境变量在docker run时建库的官方数据库镜像以保证setup_env运行前数据库已就绪。此外数据库变量可按标准 Huginn 文档用以下变量覆盖对应setup_env中HUGINN_DATABASE_HOST/PORT的读取DATABASE_ADAPTER # 必须是 postgresql 或 mysql2 DATABASE_HOST DATABASE_PORT如果使用的数据库用户没有创建 Huginn 库的权限请确保库已存在并设置DO_NOT_CREATE_DATABASE跳过rake db:create。3.3 非链接的外部数据库直接给HUGINN_DATABASE_HOST/HUGINN_DATABASE_PORT等变量即可setup_env中DATABASE_HOST默认值来自HUGINN_DATABASE_HOST未指定链接容器时兜底为localhost。四、Usage全部官方部署命令以下命令完整继承自 README 的 Usage 一节镜像统一使用ghcr.io/huginn/huginn。4.1 单机试验仅测试/评估docker run -it -p 3000:3000 ghcr.io/huginn/huginn4.2 用卷导出内置 MySQL 数据docker run --rm -it -p 3000:3000 -v /home/huginn/mysql-data:/var/lib/mysql ghcr.io/huginn/huginn4.3 链接独立 MySQL 容器docker run --name huginn_mysql \ -e MYSQL_DATABASEhuginn \ -e MYSQL_USERhuginn \ -e MYSQL_PASSWORDsomethingsecret \ -e MYSQL_ROOT_PASSWORDsomethingevenmoresecret \ mysql docker run --rm --name huginn \ --link huginn_mysql:mysql \ -p 3000:3000 \ -e HUGINN_DATABASE_NAMEhuginn \ -e HUGINN_DATABASE_USERNAMEhuginn \ -e HUGINN_DATABASE_PASSWORDsomethingsecret \ ghcr.io/huginn/huginn4.4 链接 PostgreSQL 容器docker run --name huginn_postgres \ -e POSTGRES_PASSWORDmysecretpassword \ -e POSTGRES_USERhuginn -d postgres docker run --rm --name huginn \ --link huginn_postgres:postgres \ -p 3000:3000 \ -e HUGINN_DATABASE_USERNAMEhuginn \ -e HUGINN_DATABASE_PASSWORDmysecretpassword \ -e HUGINN_DATABASE_ADAPTERpostgresql \ ghcr.io/huginn/huginn4.5 连接非链接的独立 MySQLdocker run --rm --name huginn \ -p 3000:3000 \ -e HUGINN_DATABASE_NAMEhuginn \ -e HUGINN_DATABASE_USERNAMEhuginn \ -e HUGINN_DATABASE_PASSWORDmysecretpassword \ -e HUGINN_DATABASE_HOSTmyname.mydomain \ -e HUGINN_DATABASE_PORT3306 \ ghcr.io/huginn/huginn4.6 Compose 示例develop.ymldocker/multi-process/develop.yml 给出了一套web mysql 8.0 独立数据卷容器的样例数据库凭据来自 docker/mysql.env其中通过MYSQL_PORT_3306_TCP_ADDRmysql模拟链接变量HUGINN_DATABASE_USERNAMEroot。运行方式cd docker/multi-process docker-compose -f develop.yml up该文件中还预留了两个可选项INTENTIONALLY_SLEEP10已启用让 web 等待数据库就绪注释掉的ENABLE_SMOKESCREENtrue则用于一键启用出站代理。4.7 已有 MySQL 5.7 数据卷时升级到 8.0若你已经有一个 MySQL 5.7 的数据卷在旧容器仍可用时执行以下序列让 MySQL 8.0 镜像在带既有数据卷启动时自动完成数据字典升级cd docker/multi-process docker-compose -f develop.yml stop web docker-compose -f develop.yml exec mysql sh -c mysql -uroot -p$MYSQL_ROOT_PASSWORD -e SET GLOBAL innodb_fast_shutdown 0 docker-compose -f develop.yml stop mysql docker-compose -f develop.yml pull mysql mysqldata docker-compose -f develop.yml up -d其原理与 2.3 节描述的 upgrade-mysql 脚本一致核心是用 5.7 的innodb_fast_shutdown0做一次干净停机再交给 8.0 自动升级。五、出站请求管控Smokescreen egress 代理两个官方镜像都内置了 Smokescreen一个拒绝私有地址、环回地址与链路本地地址的出站代理用于防止不可信用户创建的 Agent 借 Huginn 服务器探测内网或云元数据端点。启用方式设置ENABLE_SMOKESCREENtruebootstrap.sh 会启动该代理setup_env 自动写入OUTBOUND_PROXYhttp://127.0.0.1:4750容器内所有 Agent 的出站 HTTP(S) 请求经由它转发代理本体监听127.0.0.1:4750见 docker/scripts/smokescreenSMOKESCREEN_OPTS会把额外参数透传给进程用于放行内网服务例如SMOKESCREEN_OPTS--allow-addressintranet.example.com:443README 的建议是在不可信用户可以创建 Agent的实例上启用它。完整的默认拒绝规则环回、链路本地含169.254.169.254、RFC 1918、CGNAT、组播等与永不放行元数据地址段等注意事项见仓库内专文 doc/manual/outbound-requests.md。六、关键环境变量速查结合 README 说明与各脚本源码常用变量及其生效位置如下变量作用生效位置APP_SECRET_TOKENRails secret。未设置时容器启动时随机生成并持久化到容器内/tmp/secret容器重建后失效、会作废所有会话建议固定为openssl rand -hex 64的输出。setup_env还会主动拒绝一个曾在docker/secrets.env中公开泄露的固定值setup_envSEED_USERNAME/SEED_PASSWORD/SEED_EMAIL定制初始 admin 账号SEED_PASSWORD未设置时生成随机密码并仅在容器日志中打印一次setup_env、foreman.shDO_NOT_SEED跳过rake db:seed。README 提醒若不想要默认 6 个 Agent应在首次部署之后设置否则之后任何指向该数据库的容器都会重新补种foreman.shDO_NOT_CREATE_DATABASE跳过rake db:create用于外部数据库用户无建库权限的场景foreman.shDO_NOT_MIGRATE跳过rake db:migrateforeman.shDO_NOT_RUN_JOBS注释 Procfile 的jobs:行容器只跑 web 进程initHUGINN_DATABASE_NAME/USERNAME/PASSWORD/HOST/PORT覆盖数据库连接参数setup_env中优先级高于同名的裸变量setup_envHUGINN_DATABASE_ADAPTER/DATABASE_ADAPTERpostgresql或mysql2内置数据库仅支持 mysql2setup_env、bootstrap.shSTART_MYSQL未探测到外部数据库时默认为true可显式关闭内置 MySQLbootstrap.shENABLE_SMOKESCREEN/SMOKESCREEN_OPTS/OUTBOUND_PROXY出站代理开关与放行规则bootstrap.sh、setup_envINTENTIONALLY_SLEEP/DATABASE_INITIAL_CONNECT_MAX_RETRIES数据库连接等待/重试策略foreman.shDATABASE_URL最高优先级的连接串可覆盖全部数据库变量setup_env补充两条 README 的通用规则新版 Docker 支持用--env-file直接向容器传入你自己的.env文件.env.example中被注释掉的变量默认不会出现在生成的.env中。七、自行构建镜像仓库已有 Docker Hub 自动构建一般无需自建。若确需构建在 Huginn 仓库根目录执行注意构建上下文是仓库根目录而非docker/multi-processdocker build --rmtrue --tag{yourname}/huginn -f docker/multi-process/Dockerfile .小结Huginn 的多进程 Docker 镜像把数据库 后台任务 Web 服务 出站代理收敛进单一容器setup_env 负责把 12-factor 风格的环境变量归一化为.envbootstrap.sh 负责按依赖顺序拉起 Smokescreen 与 MySQLforeman.sh 负责幂等的建库、迁移、种子与主进程启动supervisord 则保证进程级的崩溃自恢复。理解了这条脚本链内置 MySQL、链接数据库容器、外部数据库三种部署方式及其全部环境变量开关就不再是黑盒需要进一步控制 Agent 出站行为时按 doc/manual/outbound-requests.md 启用 Smokescreen 即可。【免费下载链接】huginnCreate agents that monitor and act on your behalf. Your agents are standing by!项目地址: https://gitcode.com/gh_mirrors/hu/huginn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表