Mobilizon Docker Compose 部署指南

Mobilizon 5.2.4 官方镜像 kaihuri/mobilizon + postgis/postgis:15-3.4 双服务栈在 Ubuntu 24.04/Docker 29.9.2 实测部署:entrypoint 自动迁移、.env 全键表与密钥生成、GraphQL 建活动/加入端到端、nodeinfo/webfinger/AS 对象联邦验证、docker stats 资源实测、升级备份与 7 条踩坑 FAQ(实测日期 2026-11-02)

MobilizonMobilizonDockerDocker Compose自托管2026/11/02

Mobilizon Docker Compose 部署指南

目标:在一台干净的 Ubuntu 24.04 服务器上,用 Docker Compose 从零部署 Mobilizon 5.2.4(当前最新稳定版)双服务栈(mobilizon + PostgreSQL/PostGIS),完成建管理员、建群组、发布活动、成员加入与联邦端点验证的端到端闭环。全部命令与回显均来自实测环境(Ubuntu 24.04.5 LTS / x86_64 / Docker 29.9.2 / Docker Compose v5.6.1,实测日期 2026-11-02)。组件功能与选型评估见站内文章 《Mobilizon 介绍与选型指南》。

⚠️ 验收方式说明:本次实测环境无浏览器自动化工具可用,前端页面验收降级为「HTTP 状态码 + 页面 <title> + GraphQL API 实测 + 联邦端点取证」组合验证,未做像素级 UI 走查;功能链路(登录/建组/建活动/加入/AS 对象)均通过 API 实测闭环。

⚠️ 镜像纠偏(最重要的一条):不要拉 framasoft/mobilizon——该 Docker Hub 镜像已废弃(实测镜像加速源上其所有 tag 均 404),现行官方镜像为 kaihuri/mobilizon。另外 Mobilizon 不需要 Redis,数据库只有 PostgreSQL+PostGIS(后台任务由 Oban 跑在 PG 上)。

一、环境信息

项目值
操作系统Ubuntu 24.04.5 LTS(x86_64)
Docker 引擎29.9.2
Docker Composev5.6.1
内存15GiB(部署后可用仍 >7GiB)
应用镜像kaihuri/mobilizon:5.2.4-amd64(2.16GB;arm64 用 5.2.4-arm64)
数据库镜像postgis/postgis:15-3.4(844MB;arm64 官方文档建议换 nickblah/postgis)
端口本实例宿主 8160 → 容器 4000(Mobilizon 默认监听容器内 4000)
镜像源本机 Docker daemon 配置了 registry mirror(如 docker.1ms.run);hub.docker.com 直连不可达时按同 tag 换前缀拉取

版本核对:docker.1ms.run/v2/kaihuri/mobilizon/tags/list 实测可用 tag 含 5.2.4 / 5.2.4-amd64 / 5.2.4-arm64 / 5.2.5-RC.1 / latest——生产选 5.2.4,5.2.5-RC.1 为预发布不建议。

二、官方 compose 仓库与本文重建说明

官方文档给出的标准路径是克隆 framagit.org/kaihuri/mobilizon-docker 仓库,cp env.template .env 后直接 docker compose up -d。本批次实测环境 framagit.org 不可达,故按官方 Docker 安装文档 + 镜像内 /etc/mobilizon/config.exs 模板(该模板逐行读取 System.get_env,即 .env 键的权威清单)手工重建 compose,结果与官方仓库等价。有外网条件的读者直接用官方仓库更省事;无外网/镜像源受限环境照本文走。

三、目录与文件

mobilizon/
├── docker-compose.yml
└── .env

3.1 docker-compose.yml(实测可用全文)

services:
  db:
    image: docker.1ms.run/postgis/postgis:15-3.4
    restart: unless-stopped
    environment:
      POSTGRES_DB: mobilizon
      POSTGRES_USER: mobilizon
      POSTGRES_PASSWORD: ${MOBILIZON_DATABASE_PASSWORD}
    volumes:
      - mobilizon-db:/var/lib/postgresql/data

  mobilizon:
    image: docker.1ms.run/kaihuri/mobilizon:5.2.4-amd64
    restart: unless-stopped
    ports:
      - "8160:4000"
    env_file: .env
    depends_on:
      - db
    volumes:
      - mobilizon-uploads:/var/lib/mobilizon/uploads

volumes:
  mobilizon-db:
  mobilizon-uploads:

要点:

  • 镜像 ENTRYPOINT 为 ./docker-entrypoint.sh,逻辑实测为:循环 pg_isready 等库就绪 → CREATE EXTENSION IF NOT EXISTS pg_trgm/unaccent → mobilizon_ctl migrate → exec mobilizon start。首次启动自动建扩展+跑迁移,无需手工初始化。
  • uploads 卷必须持久化(图片/导出文件),与 PG 数据卷构成全部状态。
  • 生产环境应把 ports 换成反向代理(镜像内 /support/nginx、/support/apache 有官方模板),并设 MOBILIZON_INSTANCE_PORT=4000 保持容器内监听。

3.2 .env(实测全文,密钥已脱敏示意)

MOBILIZON_INSTANCE_HOST=mobilizon.localhost        # 生产改为你的域名
MOBILIZON_INSTANCE_PORT=4000
MOBILIZON_INSTANCE_NAME=G25 Mobilizon Test
MOBILIZON_INSTANCE_DESCRIPTION=Mobilizon 5.2.4 取证实例
MOBILIZON_INSTANCE_EMAIL=noreply@mobilizon.localhost
MOBILIZON_REPLY_EMAIL=noreply@mobilizon.localhost
MOBILIZON_INSTANCE_REGISTRATIONS_OPEN=true
MOBILIZON_LOGLEVEL=info
MOBILIZON_DATABASE_HOST=db
MOBILIZON_DATABASE_PORT=5432
MOBILIZON_DATABASE_DBNAME=mobilizon
MOBILIZON_DATABASE_USERNAME=mobilizon
MOBILIZON_DATABASE_PASSWORD=<随机>
MOBILIZON_DATABASE_SSL=false
MOBILIZON_INSTANCE_SECRET_KEY_BASE=<96hex随机>
MOBILIZON_INSTANCE_SECRET_KEY=<64hex随机>
MOBILIZON_GEOSPATIAL_SERVICE=Nominatim
MOBILIZON_SMTP_SERVER=localhost
MOBILIZON_SMTP_PORT=25

密钥生成:官方文档建议 gpg --gen-random --armor 1 50;无 gpg 时等价命令实测可用:

MOBILIZON_DATABASE_PASSWORD=$(openssl rand -hex 12)
MOBILIZON_INSTANCE_SECRET_KEY_BASE=$(openssl rand -hex 48)
MOBILIZON_INSTANCE_SECRET_KEY=$(openssl rand -hex 32)

全部 MOBILIZON_* 环境键的权威清单来自镜像内 /etc/mobilizon/config.exs(263 行)的 System.get_env 调用;未设置的键走模板内默认值。完整参数语义见《Mobilizon 5.2.4 配置参数详解》。

四、启动与迁移观察

docker compose up -d
docker compose logs -f mobilizon   # 观察首启

实测日志序列(关键行):

Running Mobilizon.Web.Endpoint with Bandit 1.12.0 at 0.0.0.0:4000 (http)
Access Mobilizon.Web.Endpoint at https://mobilizon.localhost
  • 迁移自动逐条执行(== Migrated 20250911120910 … 20251111093015),Oban 提示 peer became leader;tzdata 自动下载 2026f。
  • GeoLite2-City.mmdb 缺失 仅 WARNING(GeoIP 可选功能),不影响启动。
  • 踩坑实录:首次 up -d 因宿主端口 8159 被并发服务占用报 bind: address already in use,改 8160:4000 后成功——多实例共存机器先用 ss -ltnp | grep <端口> 排查。
  • PG 扩展实测(docker compose exec db psql -U mobilizon -d mobilizon -c "\dx"):plpgsql, postgis, postgis_topology, postgis_tiger_geocoder, fuzzystrmatch, pg_trgm, unaccent——与 FAQ 要求一致。
  • 资源实测 docker stats:mobilizon 353MiB、db 173MiB,合计约 526MiB,印证 FAQ"512MB 可跑"口径。

五、功能验收(HTTP + CLI + GraphQL 实测)

5.1 页面与联邦端点

curl -s http://127.0.0.1:8160/ | grep '<title>'
# → <title>G25 Mobilizon Test - Mobilizon</title>(SPA 壳 2499B)

curl -s http://127.0.0.1:8160/.well-known/nodeinfo/2.0
# → software.name=Mobilizon, software.version=5.2.4,
#   protocols=[activitypub], openRegistrations=true,
#   services.outbound=[atom1.0], usage.users.total=0

5.2 创建管理员与群组(CLI,容器内工具为 mobilizon_ctl)

docker compose exec mobilizon mobilizon_ctl users.new admin@mobilizon.localhost \
  --admin --profile-username g25admin --profile-display-name G25Admin \
  --password 'YourP@ss1'
docker compose exec mobilizon mobilizon_ctl actors.new --type group \
  --username g25group --display-name G25Group --group-admin g25admin
  • 两条均实测成功;users.show 回显 status: Activated / Role: administrator / @g25admin。
  • 坑:--profile-display-name "带空格 名字" 经 mobilizon_ctl 参数转发后被 OptionParser 拆散报 MatchError(实测复现);用无空格名或确保引号穿透到容器内。

5.3 GraphQL 端到端(POST /api)

# 登录取 JWT
curl -s http://127.0.0.1:8160/api -H 'Content-Type: application/json' \
  -d '{"query":"mutation{login(email:\"admin@mobilizon.localhost\",password:\"YourP@ss1\"){accessToken refreshToken}}"}'
# → accessToken/refreshToken(JWT sub "User:1")

# 建活动(必须带 organizerActorId,且以群组名义发布需群组权限)
# createEvent 成功返回:id=1, uuid=0e9dfbac-…, status=CONFIRMED, joinOptions=FREE

实测细节:

  • 分页字段是 total / elements(不是 content/totalElements)。
  • createEvent 用 attributedToId 指向个人 actor 会被拒("Organizer profile doesn't have permission to create an event on behalf of this group")——先 actors.new --type group 建组、以组为 attributedTo。
  • 第二用户 joinEvent(eventId:1, actorId:<id>) 实测返回 role:PARTICIPANT;管理侧查询 event{participants{total}} → total=2(CREATOR+PARTICIPANT),ParticipantStats 含 going/participant/notConfirmed/rejected 等计数。

5.4 联邦对象验证

curl -s "http://127.0.0.1:8160/.well-known/webfinger?resource=acct:g25admin@mobilizon.localhost"
# → subject/aliases/self + ostatus subscribe template /interact?uri={uri}

curl -s -H 'Accept: application/activity+json' http://127.0.0.1:8160/events/<uuid>
# → 标准 AS Event 对象,attributedTo=https://mobilizon.localhost/@g25group

curl -s -H 'Accept: application/activity+json' http://127.0.0.1:8160/@g25admin
# → Person actor(publicKey/outbox);outbox @context 含 schema.org、mz:、joinpeertube.org/ns

六、升级、备份与日常运维

操作命令实测/出处
升级docker compose pull && docker compose up -d官方 Docker 页;entrypoint 自动跑新迁移
备份docker compose exec db pg_dump -U mobilizon mobilizon > mz.sql + 打包 config.exs + uploads 卷FAQ 三件套
PG 大版本升级必须 pg_dump → 换镜像 → pg_restore(不能只改 tag)FAQ 明确
手工迁移/回滚docker compose exec mobilizon mobilizon_ctl migrate / rollbackhelp 实测
孤儿媒体清理docker compose exec mobilizon mobilizon_ctl media.cleanorphan5.2.4 实测子命令(文档写 clean_orphan,以实测为准)
进容器调试docker compose exec mobilizon bash—
日志docker compose logs -f mobilizon;级别由 MOBILIZON_LOGLEVEL 控制—

高级配置(超出 .env 的参数,如 Oban 队列、CSP、反垃圾):官方路径是 docker cp mobilizon-mobilizon-1:/etc/mobilizon/config.exs ./config.exs,编辑后以卷挂载覆盖同路径并 docker compose up -d 重启。

七、FAQ / 踩坑清单

  1. 拉不到 framasoft/mobilizon:正常,该镜像已废弃;用 kaihuri/mobilizon(见文首纠偏)。
  2. 要不要装 Redis:不要。依赖只有 PostgreSQL+PostGIS;网上旧教程里的 redis 服务段可删。
  3. 首启卡在迁移/连库:entrypoint 会等 pg_isready;若 db 容器健康但应用仍报错,检查 .env 的 MOBILIZON_DATABASE_HOST 是否为 compose 服务名(本例 db)。
  4. mobilizon_ctl 参数含空格报错 MatchError:见 5.2 坑注。
  5. 页面能开但地图搜索无结果:MOBILIZON_GEOSPATIAL_SERVICE 默认 Nominatim 需外网可达 nominatim.openstreetmap.org;离线环境换自建 Photon/Addok 端点。
  6. 邮件不发:默认 SMTP localhost:25 是占位,必须配真实 MOBILIZON_SMTP_*;可用 mobilizon_ctl maintenance.testemails 实测发送(该子命令实测存在但文档 CLI 页未列)。
  7. 端口冲突:容器内固定 4000,宿主映射自选;多实例机器先查 ss -ltnp。

取证说明:本文所有命令、日志行、回显与资源数字来自 2026-11-02 实测部署(kaihuri/mobilizon:5.2.4-amd64 + postgis/postgis:15-3.4,宿主端口 8160);批次结束后测试容器/卷/镜像已清理。配置参数详解与 CLI 详解见同专栏另外两篇。

Mobilizon Docker Compose 部署指南 - Quzuo