资讯动态

AFFiNE 内网离线部署:镜像导入 + 编排 + 常见报错排查

发布时间:2026/10/31 6:35:19 来源:尧图企业网站定制
第 1 章 名词认一遍名词一句话解释Docker运行容器的引擎镜像程序打包好的毛坯房容器镜像跑起来的实例Compose用一个 YAML 管理多个容器bind mount宿主机目录挂进容器删容器不删目录named volumeDocker 管理的卷down -v会删migration启动前一次性升级数据库的任务退出码必须 0externalUrlAFFiNE 对外地址影响附件与登录回调healthcheck容器的健康检查healthy才算就绪第 2 章 准备机器、材料、变量2.1 检查机器uname -m nproc free -h df -h / ip -o -4 addr show scope global【你应该看到】x86_64CPU ≥ 2建议 4内存total≥ 3.5Gi根分区可用 ≥ 30G一个全局 IPv4抄下来2.2 确认系统. /etc/os-release echo $PRETTY_NAME【你应该看到】Ubuntu 22.04.x LTS。2.3 检查材料cd ~/offline ls -lh affine-images.tar affine/docker-compose.yml affine/config/config.json //这里主要是检查镜像包是不是大约468mb如果只有几kb说明下载的时候文件损坏了同时确定docker的启动脚本docker-compose.yml和 AFFiNE 的配置文件config.json在正确的位置 ls -d docker-debs //因为我们的要求是进行离线下载所以我们需要提前下载好docker的离线安装包放在这个文件夹里这一步就是检查这个宝箱在不在 ls ~/offline/docker-debs/*.deb | wc -l //统计我们的宝箱的数量【你应该看到】affine-images.tar 约 468M affine/docker-compose.yml affine/config/config.json docker-debs/ 64镜像条目tar -xOf affine-images.tar manifest.json | python3 -c //找到一个叫manifest.json的文件打印上面的文字 import json,sys djson.load(sys.stdin) //接过前面递过来的上面的json代码数一数有几个物品 print(条目数:, len(d)) //打印物品的个数 for x in d: print( , , .join(x.get(RepoTags) or [])) 【你应该看到】条目数: 4包含ghcr.io/toeverything/affine:stable、redis:7.2.4、redis:latest、pgvector/pgvector:pg16。2.4 确认基础命令这里主要是用来检查我们的工具全不全如bash curl ,tar和gzip, ss , ipbash (命令行外壳) 你的地基。你现在敲打所有命令的黑框框环境就是它提供的。 curl (网络探测器) 用来模拟浏览器发请求。 tar和gaip (打包/解压工具) ss(端口雷达) 巡逻兵。文档里用它来检查本机的 3010 端口 ipfor t in bash curl tar gzip python3 ss ip; do printf %-10s $t command -v $t || echo MISSING done【你应该看到】没有MISSING。2.5 变量块每新开终端都要执行把LAN_IP改成你的内网 IP然后整段复制执行export指令在这里的作用主要是将这些变量的属性改为全局变量export OFFLINE$HOME/offline export AFFINE_DIR$OFFLINE/affine export AFFINE_CFG$AFFINE_DIR/config/config.json export AFFINE_PORT3010 export LAN_IP192.168.72.128逐行解释变量作用能不能改OFFLINE材料根目录材料换路径时改AFFINE_DIRAFFiNE 部署目录一般不改AFFINE_CFG配置文件路径一般不改AFFINE_PORT对外端口与 compose 的端口映射一起改LAN_IP本机内网 IP必须改成你的【判据】echo $LAN_IP / $AFFINE_PORT ls -d $AFFINE_DIR $AFFINE_CFG【你应该看到】192.168.72.128 / 3010 /home/你的用户名/offline/affine /home/你的用户名/offline/affine/config/config.json2.6 断网建议sudo ip route del default curl -I --max-time 5 https://ghcr.io 21 | head -3【你应该看到】Could not resolve host/Network is unreachable之类失败。【注意】浏览器要访问内网 IP 时不要停网卡只删默认路由。第 3 章 离线安装 Docker手工3.1 确认 deb 包ls ~/offline/docker-debs/*.deb | wc -l【你应该看到】64至少 ≥ 4。3.2 用 apt 本地安装cd ~/offline/docker-debs sudo apt-get install -y --no-download ./*.deb【你应该看到】Setting up docker.io ...、Setting up docker-compose-v2 ...等。--no-download的作用禁止 apt 联网补包本地包不全时会直接失败而不是偷偷下载。3.3 如果 apt 失败用 dpkg 回退dpkgDebian Package Manager是 Ubuntu 系统里最底层的软件安装工。它专门负责把.deb后缀的安装包解压、写进系统。【这里为什么要装3次呢】因为dpkg是按字母顺序盲装的所以一定会遇到“依赖顺序颠倒”的问题。cd ~/offline/docker-debs sudo dpkg -i ./*.deb || true sudo dpkg -i ./*.deb || true sudo dpkg -i ./*.deb || true装 3 轮是因为包的依赖顺序未必刚好后面几轮会把前面缺的依赖补上。【你应该看到】最后一轮基本没有dependency problems。3.4 启动服务这里是将containerd和 docker进行启动并常驻后台sudo systemctl enable --now containerd //systemctl 它是 Linux 系统的“大管家”专门负责管理后台程序。 //enable开机自启 //--now立即生效 sudo systemctl enable --now docker sleep 33.5 验证docker version docker compose version【你应该看到】Client: Docker Engine ... Server: Docker Engine ... ... Docker Compose version v2.40.x【如果当前用户 permission denied】Docker 是一个权限极高的底层系统软件。为了安全Linux 默认只允许超级管理员root去碰这个发动机。newgrp docker或者重新登录一次。3.6 加入 docker 组新用户需要sudo usermod -aG docker $USER newgrp docker【判据】这里的ps是用来查看进程相关的信息的docker ps【你应该看到】空表或已有容器列表不再报 permission denied。第 4 章 导入镜像【这一步做什么】把 tar 里的 4 个镜像导入本机 Docker。【为什么】离线环境不能联网拉取不导入启动时会报pull access denied。【命令】docker load -i $OFFLINE/affine-images.tar //docker load是docker专用的离线安装的指令 //-i 这里是input输入的意思后面跟的是文件路径 //$OFFLINE/affine-images.tar这就是提前准备好的、装了 4 个核心镜像的那个 468MB 的大压缩包的完整路径。【你应该看到】Loaded image: ghcr.io/toeverything/affine:stable Loaded image: redis:7.2.4 Loaded image: redis:latest Loaded image: pgvector/pgvector:pg16【判据】docker images --format {{.Repository}}:{{.Tag}}\t{{.Size}} \ | grep -E affine|pgvector|redis【你应该看到】至少这 3 类ghcr.io/toeverything/affine:stable 895MB pgvector/pgvector:pg16 ... redis:7.2.4 ... redis:latest ...【如果不对】重新docker load确认 tar 没损坏大小约 468M。第 5 章 改写对外地址【这一步做什么】把config.json的externalUrl从localhost改成你的内网 IP。【为什么】AFFiNE 用它生成分享链接、附件地址、登录回调写 localhost 时别的电脑打不开。【命令先备份】cd $AFFINE_DIR cp -a config/config.json config/config.json.bak.$(date %Y%m%d-%H%M%S) ls -1t config/config.json.bak.* | head -3【你应该看到】至少一个config.json.bak.2026...文件。【命令改写】python3 - $AFFINE_CFG http://$LAN_IP:$AFFINE_PORT PY import re, sys path, url sys.argv[1], sys.argv[2] raw open(path, encodingutf-8).read() new, n re.subn(r(externalUrl\s*:\s*)[^]*, r\1%s % url, raw) if n 0: sys.exit(config.json 里没找到 externalUrl 字段) open(path, w, encodingutf-8).write(new) print(f已改写 {n} 处 - {url}) PY【你应该看到】已改写 1 处 - http://192.168.72.128:3010【判据】grep -n externalUrl $AFFINE_CFG【你应该看到】5: externalUrl: http://192.168.72.128:3010,【如果不对】报没找到 externalUrl打开文件确认字段名与格式grep -n external $AFFINE_CFG手工改也可以用编辑器把http://localhost:3010改成http://LAN_IP:3010。第 6 章 启动容器【这一步做什么】用docker compose up启动 4 个容器。【为什么】--pull never是离线死命令只用本地镜像缺镜像立刻报错不会联网卡住。【命令】cd $AFFINE_DIR mkdir -p data docker compose up -d --pull never // up启动 // -d: 后台运行 // --pull never离线护身符 强制命令 Docker “永远不要never去网上拉取pull镜像”【你应该看到】Network affine_default Created Container affine_postgres Started Container affine_redis Started Container affine_migration_job Started Container affine_server Started【判据容器状态】docker compose ps【你应该看到】NAME IMAGE STATUS affine_migration_job ghcr.io/toeverything/affine:stable exited (0) affine_postgres pgvector/pgvector:pg16 running (healthy) affine_redis redis:latest running (healthy) affine_server ghcr.io/toeverything/affine:stable running第 7 章 验证7.1 迁移任务docker inspect -f {{.State.ExitCode}} affine_migration_job【你应该看到】0。7.2 容器健康docker compose ps【你应该看到】affine_postgresrunning (healthy)affine_redisrunning (healthy)affine_serverrunningaffine_migration_jobexited (0)7.3 入口层curl -s -o /dev/null -w AFFiNE:3010 - %{http_code}\n http://127.0.0.1:3010/【你应该看到】AFFiNE:3010 - 302或200。7.4 日志层for c in affine_server affine_postgres affine_redis; do n$(docker logs $c 21 \ | grep -ciE dial tcp|no such host|i/o timeout|ENOTFOUND|getaddrinfo || true) printf %-24s 网络失败线索: %s\n $c $n done【你应该看到】基本为 0。【例外】127.0.0.1:587连接拒绝 SMTP 探测假警报。7.5 数据落盘检查ls -la $AFFINE_DIR/data du -sh $AFFINE_DIR/data/storage $AFFINE_DIR/data/postgres 2/dev/null【你应该看到】两个目录存在postgres 目录里有内容说明数据库初始化成功。第 8 章 浏览器首次初始化8.1 打开http://LAN_IP:3010注意是http不是https。8.2 首次向导设置管理员邮箱与密码。邮箱必须是合法域名example.com可以test.local会被拒。点Continue。看到All Settings Done后再点一次 Continue。8.3 验证数据持久化新建文档输入文字刷新页面内容还在8.4 用命令行确认数据真的落盘ls -la ~/offline/affine/data/storage【你应该看到】出现新的目录/文件按时间排序最新。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑