Akkoma 3.20.1 Docker Compose 部署指南
Akkoma 3.20.1 官方 Docker Compose 源码构建路线全纪实:从克隆构建、实例生成、数据库初始化、迁移与前端安装到 Web 登录与 API 闭环验证,含 root 宿主 addgroup 撞 gid、依赖网络重试等排障实录,全部命令回显 2026-11-02 实测。
Akkoma 3.20.1 Docker Compose 部署指南
目标:在一台 Linux 主机上,用 Akkoma 官方仓库自带的 Docker Compose 编排,把 Akkoma 3.20.1 从零部署到「浏览器可登录、API 可发贴」的可用状态。本文全部命令与回显均为 2026-11-02 实测记录,包括 root 权限下官方构建脚本必失败的坑与修复方法。认知与选型背景见 《Akkoma 3.20.1 介绍与选型指南》,配置参数逐项解说见 《Akkoma 3.20.1 配置参数详解》,日常运维命令见 《Akkoma 3.20.1 常用 CLI 命令与工具详解》。
一、环境信息
本章为实测环境口径,供读者复核。
- 组件与版本:Akkoma 3.20.1(
mix.exs声明version("3.20.1"),stable 分支 HEAD 为bc62dd80,2026-09-27 "Merge branch 'develop' into stable";运行时自报版本字符串3.20.1-0-gbc62dd8)。 - 运行时:Elixir 1.15.4(OTP 26)、Erlang/OTP 26 [erts-14.0.2]、PostgreSQL 14.24(均为实测回显,见 12.4 节)。
- 编排:官方仓库根目录
docker-compose.yml+docker-resources/构建脚本,Compose v2(docker compose子命令形态)。 - 宿主:Linux x86_64,Docker Engine + Compose v2 可用;本实测宿主端口段 8128-8132 分配给 Akkoma(4000 端口被占用,Web 入口实测用 8129)。
- 重要事实(实测确证):Akkoma 3.20.1 不再需要 Redis。官方 compose 只有
db与akkoma两个服务;对源码mix.exs/mix.lock/config/lib全文检索redis零命中。 - 重要事实(实测确证):Docker Hub 上的
akkoma/akkoma预构建产物不可用于 3.20.1——其标签只有buildx/latest/next/test(无stable),且latest的创建时间停留在 2023-07-27(约 v3.9/3.10 时代)。官方 Docker 路线 = 用仓库内docker-resources/build.sh从源码构建,本文即按该路线实测。
二、部署架构总览
官方 compose 定义两个服务,职责如下:
| 服务名 | 构建来源 | 角色 | 关键参数 |
|---|---|---|---|
db | ./docker-resources/database(基于 postgres:14-alpine 加建 akkoma 用户) | PostgreSQL 14 数据服务 | shm_size: 4gb,数据 bind 到 ./pgdata,库/用户/密码均为 akkoma |
akkoma | 仓库根 Dockerfile(基于 hexpm/elixir:1.15.4-erlang-26.0.2-alpine-3.18.2) | Akkoma 应用服务 | 源码树 bind 挂载到 /opt/akkoma,nofile ulimit 524288,Web 监听 4000 |
源码 bind 挂载(. → /opt/akkoma)意味着:配置、依赖、编译产物、上传文件、静态前端全部落在宿主源码树里,构建产物只是「依赖壳」,升级时重新拉代码即可,这与预构建产物打包代码的路线根本不同。
三、获取源码
git clone --depth 1 -b stable https://akkoma.dev/AkkomaGang/akkoma.git akkoma-src
实测回显:
Cloning into 'akkoma-src'...
CLONE_RC=0
克隆后目录约 32M。确认版本:
grep version\( mix.exs
回显含 version("3.20.1")。
四、Compose 编排文件核对
官方 docker-compose.yml 原文(实测部署所用文件,仅端口映射一行按宿主占用情况从 127.0.0.1:4000:4000 改为 127.0.0.1:8129:4000,另按环境加了 name/container_name/子网,均不影响流程):
services:
db:
image: akkoma-db:latest
build: ./docker-resources/database
shm_size: 4gb
restart: unless-stopped
user: ${DOCKER_USER}
environment: {
POSTGRES_DB: akkoma,
POSTGRES_USER: akkoma,
POSTGRES_PASSWORD: akkoma,
}
env_file:
- .env
volumes:
- type: bind
source: ./pgdata
target: /var/lib/postgresql/data
akkoma:
image: akkoma:latest
build: .
restart: unless-stopped
env_file:
- .env
links:
- db
ports: [
"127.0.0.1:8129:4000",
]
volumes:
- .:/opt/akkoma
ulimits:
nofile: 524288
注意三点:
version: "3.7"属性在 Compose v2 下已废弃,每次调用都会打印一行警告the attribute version is obsolete, it will be ignored,无害,后文回显中该行不再重复摘录。- 数据库口令在 compose 里明文写死为
akkoma,官方注释说明该库只在编排内部网络可达、不对外暴露,建议保持默认。 - 没有 Redis 服务,也没有任何队列/缓存服务——单应用服务 + 单数据库即完整拓扑。
五、准备 .env
cd akkoma-src
cp docker-resources/env.example .env
echo DOCKER_USER=$(id -u):$(id -g) >> .env
env.example 实测内容:
MIX_ENV=prod
ERL_EPMD_ADDRESS=127.0.0.1
DB_NAME=akkoma
DB_USER=akkoma
DB_PASS=akkoma
本实测环境为 root 宿主(uid/gid=0),不能直接用 id -u 的结果,原因见下一章;最终 .env 追加行为 DOCKER_USER=1000:1000。
六、构建:官方脚本在 root 宿主必失败(排障实录)
直接执行官方 docker-resources/build.sh:
#!/bin/sh
docker compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) akkoma
docker compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g) db
root 下 id -u/id -g 均为 0,构建在创建 akkoma 用户步骤失败,实测回显(节选):
#6 [2/6] RUN apk add git gcc g++ musl-dev make cmake file-dev exiftool ffmpeg imagemagick libmagic ncurses postgresql-client
...
#6 45.30 OK: 572 MiB in 184 packages
#6 DONE 45.5s
#7 [3/6] RUN addgroup -g 0 akkoma
#7 0.222 addgroup: gid '0' in use
#7 ERROR: process "/bin/sh -c addgroup -g $GID $UNAME" did not complete successfully: exit code: 1
------
Dockerfile:25
25 | >>> RUN addgroup -g $GID $UNAME
------
failed to solve: process "/bin/sh -c addgroup -g $GID $UNAME" did not complete successfully: exit code: 1
BUILD_RC=1
db 服务同样卡死在 addgroup -g 0 akkoma。根因:gid 0 已被 root 组占用,无法再建同名组。官方文档的 DOCKER_USER=$(id -u):$(id -g) 写法隐含「非 root 宿主」前提。
修复:显式传非特权 UID/GID,并让宿主源码树对该 UID 可写(bind 挂载后应用进程要写 _build/deps/config/uploads/static):
chown -R 1000:1000 .
docker compose build --build-arg UID=1000 --build-arg GID=1000 akkoma
docker compose build --build-arg UID=1000 --build-arg GID=1000 db
实测成功回显(节选):
#7 [3/6] RUN addgroup -g 1000 akkoma
#7 DONE 0.2s
#8 [4/6] RUN adduser -u 1000 -G akkoma -D -h /opt/akkoma akkoma
#8 DONE 0.3s
#10 [6/6] RUN mix local.hex --force && mix local.rebar --force
#10 3.985 * creating .mix/archives/hex-2.6.0
#10 7.385 * creating .mix/elixir/1-15/rebar3
#11 naming to docker.io/library/akkoma:latest done
Image akkoma:latest Built
AKKOMA_RC=0
#6 [2/3] RUN addgroup -g 1000 akkoma
#6 DONE 0.6s
#7 [3/3] RUN adduser -u 1000 -G akkoma -D -h $HOME akkoma
#7 DONE 0.2s
#8 naming to docker.io/library/akkoma-db:latest done
Image akkoma-db:latest Built
DB_RC=0
顺带实测结论:db 的 Dockerfile 里 adduser ... -h $HOME 的 $HOME 在 postgres:14-alpine 基础上并未定义,但 adduser -D 对此不报错(回显 DONE 0.2s),疑点排除。
构建完成后两个产物的大小(实测):
akkoma-db:latest 414MB
akkoma:latest 911MB
七、拉取应用依赖(deps.get,含网络踩坑)
后续所有 mix 任务都通过官方 docker-resources/manage.sh 进入应用服务执行:
#!/bin/sh
docker compose run --rm akkoma $@
第一步拉依赖:
./docker-resources/manage.sh mix deps.get
首次实测失败——从 GitHub 拉 search_parser 时传输层中断:
* Getting search_parser (https://github.com/FloatingGhost/pleroma-contrib-search-parser.git - origin/main)
fatal: unable to access 'https://github.com/FloatingGhost/pleroma-contrib-search-parser.git/': Error in the HTTP2 framing layer
** (Mix) Command "git --git-dir=.git fetch --force --quiet --progress" failed
DEPS_RC=1
直接重试即成功(瞬时网络故障,非仓库问题):
* Getting cowboy (Hex package)
* Getting cowboy_telemetry (Hex package)
* Getting websock_adapter (Hex package)
* Getting websock (Hex package)
Found retired packages, see above for details
Found packages with security advisories, see above for details
You have added/upgraded packages you could sponsor, run `mix hex.sponsor` to learn more
DEPS_RC=0
值得留意的实测细节:mix deps.get 会顺带做安全审计,本次输出列出了若干带 CVE 的依赖(节选):
Unchanged:
cowboy 2.17.0 VULNERABLE!
EEF-CVE-2026-65624 (MEDIUM)
Cowboy HTTP/1.1 max_headers Bypass via Duplicate Header Names Enables Memory Exhaustion
decimal 3.1.1 VULNERABLE!
EEF-CVE-2026-97853 (MEDIUM)
Unbounded allocation in decimal Decimal.round/3 driven by the places argument enables DoS
earmark 1.4.46 RETIRED! VULNERABLE!
(deprecated) Earmark is no longer maintained. Migrate to a replacement, for example MDEx
这与 3.20.1 本身是「随依赖安全更新的重构建补丁」的定位一致:上游补丁未合并前,这些告警属于已知状态。
八、编译
./docker-resources/manage.sh mix compile
顺序陷阱(实测):若在 deps.get 未完成时抢跑 compile,会得到一长串未满足依赖清单后中止:
Unchecked dependencies for environment prod:
* bcrypt_elixir (Hex package)
the dependency is not available, run "mix deps.get"
...
* search_parser (https://github.com/FloatingGhost/pleroma-contrib-search-parser.git - origin/main)
lock mismatch: the dependency is out of date. To fetch locked version run "mix deps.get"
...
** (Mix) Can't continue due to errors on dependencies
COMPILE_RC=1
依赖齐全后正式编译(605 个 .ex 文件,含 NIF/C 扩展,约 2 分钟):
==> restarter
Compiling 2 files (.ex)
Generated restarter app
make: Entering directory '/opt/akkoma/deps/eblurhash/c_src'
cc -o /opt/akkoma/deps/eblurhash/c_src/../priv/blurhash blurhash_stb.c encode.c -lm
...
01:56:37.497 [debug] Elixir.Pleroma.Web.ActivityPub.MRF.NoOpPolicy is excluded from config descriptions, because does not implement `config_description/0` method.
Compiling lib/pleroma/web/gettext.ex (it's taking more than 10s)
Generated pleroma app
COMPILE_RC=0
九、生成实例配置
mkdir -p pgdata
./docker-resources/manage.sh mix pleroma.instance gen
该任务交互式询问实例域名、名称、管理员邮箱、数据库参数等(若数据库服务尚未建库,口令就填 compose 里的 akkoma;数据库主机填 db;监听 IP 必须改成 0.0.0.0,否则 bind 挂载环境下应用只监听回环地址,宿主端口映射进不去)。实测回显:
fatal: No names found, cannot describe anything.
warning: `config/prod.secret.exs` not found. You may want to create one by running `mix pleroma.instance gen`
Writing config to config/generated_config.exs.
Writing the postgres script to config/setup_db.psql.
Writing /opt/akkoma/static/robots.txt.
All files successfully written! Refer to the installation instructions for your platform for next steps.
生成物要点(实测核对):
config/generated_config.exs(权限 0640):含url: [host: "localhost", scheme: "https", port: 8129]、http: [ip: {0, 0, 0, 0}, port: 4000]、随机生成的secret_key_base/signing_salt/vapid密钥对、config :pleroma, Pleroma.Repo, hostname: "db"、configurable_from_database: false等。config/setup_db.psql:两行建角色/建库 + 连接 + 三个CREATE EXTENSION。static/robots.txt:按「允许索引」生成,实测内容User-Agent: */Disallow:(空值即允许)。
按官方流程改名为正式配置:
cp config/generated_config.exs config/prod.secret.exs
十、初始化数据库
先单独起一个数据库连接会话执行建库脚本(官方文档写法):
./docker-resources/manage.sh psql -h db -U akkoma -f config/setup_db.psql
实测回显:
psql:config/setup_db.psql:1: ERROR: role "akkoma" already exists
psql:config/setup_db.psql:2: ERROR: database "akkoma" already exists
You are now connected to database "akkoma" as user "akkoma".
CREATE EXTENSION
CREATE EXTENSION
CREATE EXTENSION
前两行的 ERROR 不是故障:db 服务的环境变量(POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB=akkoma)在首次启动时已经自动建好了角色和库,脚本重复执行自然冲突;关键是后面三个扩展(pg_trgm、btree_gist、plpgsql 一类)成功创建。全新环境首次执行时这两行则会是 CREATE ROLE / CREATE DATABASE。
十一、执行数据迁移
./docker-resources/manage.sh mix ecto.migrate
实测回显(首尾节选,全量迁移从 2017 年第一张表一路跑到 2021 年,数百条):
02:11:12.827 [info] == Running 20170320193800 Pleroma.Repo.Migrations.CreatePleroma.User.change/0 forward
02:11:12.829 [info] create table if not exists users
02:11:12.837 [info] == Migrated 20170320193800 in 0.0s
02:11:12.850 [info] == Running 20170321074828 Pleroma.Repo.Migrations.CreatePleroma.Activity.change/0 forward
02:11:12.850 [info] create table if not exists activities
02:11:12.854 [info] create index if not exists activities_data_index
...
02:11:13.970 [info] == Running 20210222183840 Pleroma.Repo.Migrations.RemoveHashtagsObjectsDuplicateIndex.up/0
02:11:13.970 [info] drop index if exists hashtags_objects_hashtag_id_object_id_index
02:11:13.970 [info] index "hashtags_objects_hashtag_id_object_id_index" does not exist, skipping
02:11:13.971 [info] == Running 20210222184616 Pleroma.Repo.Migrations.ChangeHashtagsNameToText.up/0
02:11:13.971 [info] alter table hashtags
十二、安装前端并启动服务
12.1 安装前端
主前端 pleroma-fe 与管理端 admin-fe(实测回显):
./docker-resources/manage.sh mix pleroma.frontend install pleroma-fe --ref stable
Downloading pleroma-fe (stable)...
02:12:22.102 [info] Downloading pre-built bundle for pleroma-fe
02:12:22.113 [debug] Outbound: get https://akkoma-updates.s3-website.fr-par.scw.cloud/frontend/stable/akkoma-fe.zip
Installing pleroma-fe (stable) to /opt/akkoma/static/frontends/pleroma-fe/stable
Frontend pleroma-fe (stable) installed to /opt/akkoma/static/frontends/pleroma-fe/stable
./docker-resources/manage.sh mix pleroma.frontend install admin-fe --ref stable
Downloading admin-fe (stable)...
02:12:29.640 [info] Downloading pre-built bundle for admin-fe
02:12:29.646 [debug] Outbound: get https://akkoma-updates.s3-website.fr-par.scw.cloud/frontend/stable/admin-fe.zip
Installing admin-fe (stable) to /opt/akkoma/static/frontends/admin-fe/stable
Frontend admin-fe (stable) installed to /opt/akkoma/static/frontends/admin-fe/stable
Mastodon 风格前端踩坑(排障实录):按配置里 mastodon: %{"name" => "mastodon-fe", ...} 直觉执行 install masto-fe 会失败:
** (RuntimeError) Configured third-party frontend without a bugtracker; refusing install.
(pleroma 3.20.1-0-gbc62dd8) lib/pleroma/frontend.ex:37: Pleroma.Frontend.install/2
masto-fe 是仓库名不是安装名;用 available 表里的键 mastodon-fe 即成功:
Downloading mastodon-fe (akkoma)...
03:18:44.375 [info] Downloading pre-built bundle for mastodon-fe
03:18:44.382 [debug] Outbound: get https://akkoma-updates.s3-website.fr-par.scw.cloud/frontend/akkoma/masto-fe.zip
Installing mastodon-fe (akkoma) to /opt/akkoma/static/frontends/mastodon-fe/akkoma
Frontend mastodon-fe (akkoma) installed to /opt/akkoma/static/frontends/mastodon-fe/akkoma
12.2 启动
docker compose up -d
实测回显:
Container akkoma-3.20.1-db Running
Container akkoma-3.20.1-app Creating
Container akkoma-3.20.1-app Created
Container akkoma-3.20.1-app Starting
Container akkoma-3.20.1-app Started
应用服务入口脚本 docker-entrypoint.sh 的行为(实测源码):先 pg_isready 轮询等库就绪,再自动跑一遍 mix ecto.migrate(幂等),最后以 elixir --erl "+sbwt none +sbwtdcpu none +sbwtdio none" -S mix phx.server 启动。BEAM 不是 JVM,无需任何堆内存参数。
12.3 Web 验证
curl -sI http://127.0.0.1:8129/
实测回显(节选):
HTTP/1.1 200 OK
access-control-allow-credentials: true
access-control-allow-origin: *
cache-control: max-age=0, private, must-revalidate
content-length: 7283
content-security-policy: upgrade-insecure-requests;style-src 'self' 'nonce-0mTOjrzCzBmbML-';...
server: Cowboy
x-frame-options: DENY
curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8129/web
实测回显:
302
<html><body>You are being <a href="/web/login">redirected</a>.</body></html>
/web 302 到 /web/login 即前端 bundle 正常、实例可用。
12.4 运行时核对
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
akkoma-3.20.1-app akkoma:latest "/opt/akkoma/docker-…" akkoma About an hour ago Up 32 minutes 127.0.0.1:8129->4000/tcp
akkoma-3.20.1-db akkoma-db:latest "docker-entrypoint.s…" db 2 hours ago Up 32 minutes 5432/tcp
版本与资源实测:
Erlang/OTP 26 [erts-14.0.2] [source] [64-bit] [smp:6:6] [ds:6:6:10] [async-threads:1] [jit]
Elixir 1.15.4 (compiled with Erlang/OTP 26)
postgres (PostgreSQL) 14.24
NAME CPU % MEM USAGE / LIMIT
akkoma-3.20.1-app 0.67% 212.7MiB / 15.57GiB
akkoma-3.20.1-db 0.37% 101MiB / 15.57GiB
空闲态应用服务仅 ~213MiB 常驻,印证 A1 里「BEAM 单机轻量」的选型结论。
十三、创建管理员账号
./docker-resources/manage.sh mix pleroma.user new root root@localhost --password q1w2e3r4 --admin -y
实测回显(节选,SQL debug 行略):
A user will be created with the following information:
- nickname: root
- email: root@localhost
- password: q1w2e3r4
- name: root
- bio:
- moderator: false
- admin: true
...
User root created
...
Admin status of root: true
要点:-y 跳过交互确认;带 --password 时不再随机生成口令;CLI 建的用户 is_confirmed: true,免邮箱确认。至此可用 root / q1w2e3r4 在 /web/login 登录。
十四、部署后功能验证(API 实测)
实例元数据(GET /api/v1/instance 节选):
{"version":"2.7.2 (compatible; Akkoma 3.20.1-0-gbc62dd8)","description":"Akkoma: The cooler fediverse server","title":"Akkoma Test","stats":{"domain_count":0,"remote_user_count":1,"status_count":0,"user_count":0},"uri":"localhost","max_toot_chars":5000,"upload_limit":16000000,"registrations":true,"poll_limits":{"max_options":20,"max_option_chars":200,"min_expiration":0,"max_expiration":31536000},"post_formats":["text/plain","text/html","text/markdown","text/bbcode","text/x.misskeymarkdown"]}
NodeInfo 2.0(GET /nodeinfo/2.0.json 节选):
{"software":{"name":"akkoma","version":"3.20.1-0-gbc62dd8"},"protocols":["activitypub"],"openRegistrations":true,"metadata":{"features":["pleroma_api","akkoma_api","mastodon_api","mastodon_api_streaming","polls","quote_posting","editing","pleroma_emoji_reactions","profile_directory"]}}
OAuth 口令授权 → 发贴 → 时间线闭环实测:
=== token ===
{"id":2,"scope":"read write follow","me":"https://localhost:8129/users/by-id/BC1W3JR9LKovXVNMoq","refresh_token":"9T0VM6LKeAGoybONFyck68Oo4bo0TPY-powbe0MSFuU","access_token":"hG0rbSU5O9pyWu5sHAY5A4LMCd16VCN6SGrb0b7nxbY","created_at":1793587571,"expires_in":3153600000,"token_type":"Bearer"}
=== verify ===
{"id": "BC1W3JR9LKovXVNMoq", "username": "root", "acct": "root", "statuses_count": 1, "created_at": "2026-11-02T02:12:08.000Z"}
=== post ===
{"id": "BC1Z71dW94SZBwHhK4", "created_at": "2026-11-02T02:46:25.000Z", "content": "Akkoma 3.20.1 deploy verified: OAuth password grant timeline OK", "visibility": "public", "url": "https://localhost:8129/notice/BC1Z71dW94SZBwHhK4"}
=== public tl ===
BC1Z71dW94SZBwHhK4 Akkoma 3.20.1 deploy verified: OAuth password grant timeline OK
BC1WA8mX5CkB09Dxbs Hello Akkoma from quzuo test <a class="hashtag" data-tag="akkomatest" href="http
发贴、公开时间线、主页时间线全部返回真实数据,部署验证通过。
十五、更新流程
官方文档给出的升级序列(与首次部署同序,实测可复用):
git pull
./docker-resources/build.sh # root 宿主换成第六章的显式 --build-arg 写法
./docker-resources/manage.sh mix deps.get
./docker-resources/manage.sh mix compile
./docker-resources/manage.sh mix ecto.migrate
docker compose restart akkoma
改配置(config/prod.secret.exs)后同样以 docker compose restart akkoma 生效,实测回显:
Container akkoma-3.20.1-app Restarting
Container akkoma-3.20.1-app Started
十六、排障实录汇总
| # | 现象 | 根因 | 处置 |
|---|---|---|---|
| 1 | build.sh 两路构建均挂:addgroup: gid '0' in use | root 宿主 id -u/id -g=0,无法建 gid 0 组 | 显式 --build-arg UID=1000 --build-arg GID=1000 + .env DOCKER_USER=1000:1000 + 源码树 chown -R 1000:1000 |
| 2 | mix deps.get 失败:Error in the HTTP2 framing layer(GitHub 源) | 瞬时网络故障 | 原样重试即过 |
| 3 | mix compile 报一长串 the dependency is not available | 跳过了 deps.get | 严格按 deps.get → compile 顺序 |
| 4 | setup_db.psql 报 role/database already exists | compose 环境变量已自动建库 | 非故障,确认三个 CREATE EXTENSION 成功即可 |
| 5 | mix pleroma.frontend install masto-fe 报 refusing install | 用了仓库名而非 available 键名 | 改用 mastodon-fe |
| 6 | 应用起不来 / Web 打不开 | instance gen 监听 IP 保持默认 127.0.0.1 | 生成后改 http: [ip: {0, 0, 0, 0}] 并重启 |
| 7 | 每次 compose 调用刷 version is obsolete 警告 | Compose v2 废弃 version 属性 | 无害,可删该行消警 |
十七、小结与关联
Akkoma 的官方 Docker 路线本质是「依赖壳 + 源码 bind 挂载」:构建一次成型,之后代码、配置、数据全在宿主目录,升级即 git pull 重编译。拓扑只有应用与 PostgreSQL 两个服务(3.20.1 已彻底移除 Redis),空闲态常驻内存 200MiB 级,单机小实例成本极低。
- 选型与架构背景:《Akkoma 3.20.1 介绍与选型指南》
- 配置参数逐项详解:《Akkoma 3.20.1 配置参数详解》
- CLI 任务与运维命令:《Akkoma 3.20.1 常用 CLI 命令与工具详解》