Socialhome 0.24.0 Docker Compose 部署指南
Socialhome 0.24.0 容器化部署实录:按官方四层路线组装后端制品+PostgreSQL+Redis+nginx,前端 SPA 路由衔接、webfinger/nodeinfo/建号全链路实测,沉淀 7 条 2026-11-02 排障记录。
Socialhome 0.24.0 Docker Compose 部署指南
目标:在一台 Ubuntu 服务器上,用 Docker Compose 把 Socialhome 0.24.0 官方文档 Docker 安装页给出的路线(后端制品 + PostgreSQL + Redis + 负载均衡四层)完整落地,并逐条实测验证 Web、管理后台、API、webfinger、nodeinfo 与管理员建号流程。本文全部配置与回显均为 2026-11-02 真实部署记录;官方从未提供 compose 编排文件,本文的 compose 文件是按官方指南组装后的真实形态。产品背景与选型见 《Socialhome 0.24.0 介绍与选型指南》。
一、环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu(内核 7.0.0-38-generic) |
| Docker | Docker version 29.9.2, build a82e528 |
| Compose | Docker Compose version v5.6.1 |
| 硬件 | 6 vCPU / 15Gi 内存(官方按 4 vCPU 估算约需 3GB,见架构章) |
| 组件版本 | 后端 v0.24.0(Codeberg tag,2026-08-01);前端 socialhome-ui 0.12.2(Codeberg generic 制品) |
| 依赖服务 | PostgreSQL 17、Redis 7、nginx 1.27 |
| 对外端口 | 8135(HTTP,TLS 由外部反代终结后本层仅示例) |
| 私有网络 | 10.89.70.0/24(显式指定,避开已占用槽位) |
| 编排项目名 | socialhome-v0.24.0-stack(compose 顶层 name: 显式声明) |
| 部署目录 | /opt/data/quzuo/tmp/socialhome/ |
| 示例账号 | admin / q1w2e3r4 |
二、部署架构总览
官方文档 Docker 安装页(https://socialhome.readthedocs.io/en/latest/installation.html)给出的容器化路线由四个角色组成,本文的编排一一对应:
| 角色 | 本文实现 | 官方依据 |
|---|---|---|
| 后端应用 | 制品 codeberg.org/socialhome/socialhome:v0.24.0 | 官方容器制品库,可匿名拉取 |
| PostgreSQL | postgres:17 | 官方建议最新版,数据路径需持久化 |
| Redis | redis:7 | 同上 |
| 负载均衡(LB) | nginx:1.27 | 官方要求 LB 承担 TLS 终结与 /media 服务 |
后端进程内部由 Circus 统一守护四类进程(官方文档与制品内 config/circus_docker.ini):Daphne(HTTP+WebSocket,端口 23564)、RQ worker(highest/high/default/low/lowest 五级队列)、Dramatiq(进程数默认等于 vCPU 数)、APScheduler(runscheduler)。
官方文档给出的内存规划依据:基础约 650MB,Daphne 每 worker 约 320MB,Dramatiq 每 vCPU 约 500MB;4 vCPU 默认配置约 3GB。
后端有两个路径必须持久化(官方原文):
/app/socialhome/media(读写,上传的媒体文件)/app/var(读写,搜索索引等运行期数据)
关键认知:v0.23 起后端不再内置任何用户界面(官方原文「does not serve media and does not include any frontend」),前端是独立的 socialhome-ui 单页应用,由 LB 按路由规则分流——只起后端四件套你会看到首页 405,这是本部署最容易踩的结构性坑(见第十二章排障 2)。
三、获取前端制品
官方文档明确「Currently there are no Docker images for the frontend application. You will need to serve the extracted frontend files via your chosen web server」,前端制品在 Codeberg generic 包仓库。取 0.12.2 版并解压:
mkdir -p /opt/data/quzuo/tmp/socialhome/ui-dist
curl -sL -o socialhome-ui-0.12.2.tar.gz \
"https://codeberg.org/api/packages/socialhome/generic/socialhome-ui/0.12.2/socialhome-ui-0.12.2.tar.gz"
tar -xzf socialhome-ui-0.12.2.tar.gz -C ui-dist
解压后目录核对(实测):
$ ls ui-dist/dist
assets
favicon.ico
index.html
index.html、favicon.ico、/assets 正是官方文档「Routing to the frontend」一节要求由 LB 直接托管的内容。
四、Compose 编排文件
官方从未在现行仓库提供 compose 文件(2016 年 cookiecutter 脚手架遗留即删),以下是按官方指南组装、当天实际跑通的完整 docker-compose.yml:
name: socialhome-v0.24.0-stack
services:
backend:
image: codeberg.org/socialhome/socialhome:v0.24.0
restart: unless-stopped
env_file: .env
volumes:
- media:/app/socialhome/media
- var:/app/var
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
networks:
- shnet
db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_USER: socialhome
POSTGRES_PASSWORD: ${PG_PASSWORD}
POSTGRES_DB: socialhome
volumes:
- dbdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U socialhome -d socialhome"]
interval: 5s
timeout: 3s
retries: 10
networks:
- shnet
redis:
image: redis:7
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redisdata:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
networks:
- shnet
web:
image: nginx:1.27
restart: unless-stopped
ports:
- "8135:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- media:/srv/media:ro
- ./ui-dist:/srv/ui:ro
depends_on:
- backend
networks:
- shnet
networks:
shnet:
ipam:
config:
- subnet: 10.89.70.0/24
volumes:
dbdata:
redisdata:
media:
var:
要点对照官方要求:
- 后端不映射任何端口,只暴露给私有网络内的 LB——官方要求「TLS should be terminated by a load balancer before sending traffic to the application container」;
media/var两个卷对应官方「Backend container volumes」一节必须持久化的两个路径;web服务以只读方式共享media卷来履行「LB 负责 /media 服务」的职责;db/redis设健康检查,后端depends_on健康条件,避免迁移抢跑;- 顶层
name:显式声明项目名,防止多栈环境互删。
五、负载均衡路由配置
官方文档给出路由规则:12 个路径前缀 + 两类 Accept 头正则必须转后端 23564,其余落前端文件,LB 回写 X-Forwarded-Proto。实测跑通的 nginx.conf 全文:
map $http_accept$http_content_type $ap_request {
default 0;
"~*application/(activity|ld)\+json.*" 1;
"~*application/(xrd\+|magic-envelope\+)xml.*" 1;
}
upstream socialhome_backend {
server backend:23564;
}
server {
listen 80;
server_name _;
client_max_body_size 20m;
location /media {
alias /srv/media;
add_header X-Robots-Tag "noindex, nofollow";
}
location ~* /(admin|api|api-token-auth|django-rq|fetch|hcard|jsi18n|nodeinfo|receive|static|webfinger|\.well-known|ch) {
proxy_pass http://socialhome_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 3600s;
}
location / {
if ($ap_request = 1) {
proxy_pass http://socialhome_backend;
break;
}
root /srv/ui/dist;
try_files $uri $uri/ $uri.html /index.html;
}
}
三个易错点:
Accept头分流是联邦识别的命门:对端实例用application/activity+json抓取你的 profile,若这条map缺失,AP 对端会拿到 SPA 的index.html而非活动流 JSON;/media必须加X-Robots-Tag "noindex, nofollow":官方原文要求 LB「deny indexing of the files」;- WebSocket 升级头:Daphne 同时承载
/ch实时通道,缺Upgrade/Connection头则前端时间线不实时。
生产环境请再套一层 TLS 终结并把 X-Forwarded-Proto 固定为 https(官方要求),本示例以 8135 端口 HTTP 直连演示。
六、准备 .env
后端配置全部走环境变量,官方「Backend configuration」一节列出最小集。实测 .env 全文:
PG_PASSWORD=ShPg2026q1w2
DATABASE_URL=postgres://socialhome:ShPg2026q1w2@db:5432/socialhome
DJANGO_SECRET_KEY=0e371812caa290902b5e54501dad71a426116e35bf48c456e23ec8ac16fa7c0e80ceb6f42fa63f2bcb9a05b20ba20b202234
DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost
SOCIALHOME_DOMAIN=127.0.0.1:8135
SOCIALHOME_HTTPS=False
DJANGO_SECURE_SSL_REDIRECT=False
DJANGO_ACCOUNT_ALLOW_REGISTRATION=True
REDIS_HOST=redis
RQWORKER_NUM=1
DAPHNE_WORKER_NUM=1
SOCIALHOME_LOG_TARGET=console
DJANGO_SECRET_KEY用官方 django-extensions 的generate_secret_key命令生成(见 CLI 篇);官方强调「do NOT change this after setup」;SOCIALHOME_DOMAIN与DJANGO_ALLOWED_HOSTS都写成域名[:端口],联邦身份(handle)即用户名@SOCIALHOME_DOMAIN;SOCIALHOME_LOG_TARGET=console是官方 Docker 页的推荐值(裸机默认 file);- 其余全部可选变量与默认值,见 《Socialhome 0.24.0 配置参数详解》。
七、启动与数据迁移
cd /opt/data/quzuo/tmp/socialhome
docker compose up -d
后端启动脚本会自动执行 python manage.py migrate,无需手工初始化。启动日志(实测节选):
Operations to perform:
Apply all migrations: account, activities, admin, auth, authtoken, content, contenttypes, django_dramatiq, django_rq, dynamic_preferences, dynamic_preferences_users, federate, redisboard, reversion, robots, sessions, sites, socialaccount, socialhome, users
Running migrations:
Applying contenttypes.0001_initial... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0001_initial... OK
...
服务状态核对(实测):
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
socialhome-v0240-stack-backend-1 codeberg.org/socialhome/socialhome:v0.24.0 "/bin/sh -c /start_s…" backend 7 minutes ago Up 7 minutes
socialhome-v0240-stack-db-1 postgres:17 "docker-entrypoint.s…" db 7 minutes ago Up 7 minutes (healthy) 5432/tcp
socialhome-v0240-stack-redis-1 redis:7 "docker-entrypoint.s…" redis 7 minutes ago Up 7 minutes (healthy) 6379/tcp
socialhome-v0240-stack-web-1 nginx:1.27 "/docker-entrypoint.…" web 3 minutes ago Up 3 minutes 0.0.0.0:8135->80/tcp, [::]:8135->80/tcp
八、Web 与联邦端点验证
页面与 API(实测):
$ curl -s -o /dev/null -w "%{http_code} %{content_type} %{size_download}B\n" http://127.0.0.1:8135/
200 text/html 655B
$ curl -s -o /dev/null -w "%{http_code} %{content_type} %{size_download}B\n" http://127.0.0.1:8135/admin/login/
200 text/html; charset=utf-8 4256B
$ curl -s -o /dev/null -w "%{http_code} %{content_type} %{size_download}B\n" http://127.0.0.1:8135/api/
200 text/html; charset=utf-8 1029B
首页 655B 即前端 ui-dist/dist/index.html(SPA 壳,<title>Socialhome</title>),管理后台与 API 由后端响应——前后端分流生效。
webfinger(实测完整回显):
$ curl -s "http://127.0.0.1:8135/.well-known/webfinger?resource=acct:admin@127.0.0.1:8135"
{"subject": "acct:admin@127.0.0.1:8135", "aliases": ["http://127.0.0.1:8135/u/admin/", "http://127.0.0.1:8135/u/admin/"], "links": [{"rel": "http://microformats.org/profile/hcard", "type": "text/html", "href": "http://127.0.0.1:8135/hcard/users/0598121f-4e4d-4a8f-921c-aca8707ffccb"}, {"rel": "http://joindiaspora.com/seed_location", "type": "text/html", "href": "http://127.0.0.1:8135"}, {"rel": "http://webfinger.net/rel/profile-page", "type": "text/html", "href": "http://127.0.0.1:8135/u/admin/"}, {"rel": "salmon", "href": "http://127.0.0.1:8135/receive/users/0598121f-4e4d-4a8f-921c-aca8707ffccb"}, {"rel": "self", "href": "http://127.0.0.1:8135/u/admin/", "type": "application/activity+json"}, {"rel": "http://ostatus.org/schema/1.0/subscribe", "template": "http://127.0.0.1:8135/search/?q={uri}"}]}
注意 links 里同时出现 Diaspora 系(joindiaspora.com/seed_location、salmon、hcard)与 AP 系(rel: self 指向 application/activity+json)两套发现链接——双协议联邦的直观证据。
nodeinfo(实测):
$ curl -s "http://127.0.0.1:8135/nodeinfo/1.0/"
{"version": "1.0", "software": {"name": "socialhome", "version": "0.24.0"}, "protocols": {"inbound": ["diaspora"], "outbound": ["diaspora"]}, "services": {"inbound": [], "outbound": []}, "openRegistrations": true, "usage": {"users": {}}, "metadata": {"nodeName": "Socialhome"}}
$ curl -s -o /dev/null -w "%{http_code}\n" "http://127.0.0.1:8135/nodeinfo/2.0/"
404
nodeinfo/1.0 如实报出软件版本 0.24.0;nodeinfo/2.0 不存在(404 为 Django 版「Page Not found」页)——对外可见性登记时注意 2.0 探测会失败。
九、创建管理员账号
官方 running 文档给出的 shell 流程(邮件确认 + 超管授权)。本示例用 createsuperuser 直接建号(注册流程需要可用邮件服务,官方原文「email is required for signing up」,初始实例建议走命令行):
docker compose exec backend python manage.py createsuperuser
# 交互输入:Username: admin / Email: admin@quzuo.net / Password: q1w2e3r4(两次)
建号后按官方「Confirming user emails via the shell」一节跳过邮件确认:
docker compose exec backend python manage.py shell -c "
from allauth.account.models import EmailAddress
EmailAddress.objects.filter(email='admin@quzuo.net').update(verified=True)
"
核验结果(实测):
$ docker compose exec backend python manage.py shell -c "
from socialhome.users.models import User
u = User.objects.get(username='admin')
print('user id:', u.id, '| is_superuser:', u.is_superuser)
print('profile handle:', u.profile.handle)
print('profile uuid:', u.profile.uuid)
"
user id: 1 | is_superuser: True
profile handle: admin@127.0.0.1:8135
profile uuid: 0598121f-4e4d-4a8f-921c-aca8707ffccb
profile handle 即联邦身份 admin@127.0.0.1:8135。此时再查 webfinger 才会返回上面第八节的 200 JSON——建用户之前 webfinger 查任何账号都是 404(见排障 5)。
十、运行时核对
后端进程模型(制品内无 ps,借 /proc 核对,实测节选):
/proc/1: /usr/local/bin/python3.12 /usr/local/bin/circusd /app/config/circus.ini
/proc/29: /usr/local/bin/python manage.py rqworker highest high default low lowest
/proc/30: /usr/local/bin/python manage.py runscheduler
/proc/31: /usr/local/bin/python3.12 /usr/local/bin/dramatiq --path . --processes 6 --threads 8 ...
/proc/32: /usr/local/bin/python3.12 /usr/local/bin/daphne --fd 6 config.asgi:application -v1 --proxy-headers
/proc/50..55: dramatiq 子进程 ×6
与官方文档一致:Circus 守护 Daphne、RQ worker、Dramatiq、APScheduler 四类;Dramatiq 进程数 --processes 6 正等于本机 vCPU 数(默认行为,可用 DRAMATIQ_NPROCS 压低)。
任务队列水位(实测):
$ docker compose exec backend python manage.py rqstats
Django RQ CLI Dashboard
------------------------------------------------------------------------------------------
| Name | Queued | Active | Deferred | Finished | Failed | Workers |
------------------------------------------------------------------------------------------
| default | 0 | 0 | 0 | 0 | 0 | 1 |
| high | 0 | 0 | 0 | 0 | 0 | 1 |
| highest | 0 | 0 | 0 | 0 | 0 | 1 |
| low | 0 | 0 | 0 | 0 | 0 | 1 |
| lowest | 0 | 0 | 0 | 0 | 0 | 1 |
------------------------------------------------------------------------------------------
搜索索引落盘核对(/app/var 卷,rebuild_index 后实测):
$ docker compose exec backend ls -la /app/var
total 24
drwxrwxr-x 4 root root 4096 Nov 2 09:36 .
drwxr-xr-x 1 root root 4096 Nov 2 09:25 ..
-rw-rw-r-- 1 root root 14 Jan 10 2019 .gitignore
drwxrwxr-x 2 root root 4096 Nov 2 09:25 whoosh
drwxr-xr-x 2 root root 4096 Nov 2 09:36 xapian-index
十一、更新流程
- 到 Codeberg tags 页确认新版本(如 v0.25.0),不要追
latest标签制品(它落后于 tag,本次实查latest内是 0.23.0); - 修改 compose 中后端制品 tag,
docker compose pull backend; docker compose up -d backend——启动脚本自动跑增量迁移;- 前端独立升级:下载新版 generic 包解压替换
ui-dist/,docker compose exec web nginx -s reload; - 备份四件套(官方 running 章节口径):数据库、
.env、media路径、Redis 数据。
十二、排障实录汇总
以下 7 条全部为 2026-11-02 部署过程实际遇到并定位的问题:
- GitLab 旧 registry 制品陈旧:
registry.gitlab.com/jaywink/socialhome:latest内是 0.20.0(Python 3.10、还带 bower/Gruntfile 的旧构建)。核对版本的方法:进后端执行cat /app/socialhome/__init__.py。制品一律用 Codeberg 容器库 + 明确 tag。 - 只起后端时
GET /返回 405:回显Allow: OPTIONS——v0.23+ 后端首页视图是空实现(HomeView(View): pass),不再提供任何界面;必须配前端 SPA + 第五节 nginx 路由才有 200 首页。 - 每个进程日志刷
UserWarning: !!! No .env file found!:制品期望/app/.env存在,用 composeenv_file注入时该告警必然出现,无害,可忽略。 - 启动即报
ERROR ... get_user_private_key - no profile for http://127.0.0.1:8135/u/None/:FEDERATION_USER未设置导致联邦签名找不到 profile;建好用户并设置该变量后消失(见配置篇)。 - 建用户前 webfinger 全 404:属正常时序——
acct:<用户>@域名必须存在对应 profile 才能被解析,先完成第九节建号。 drf-haystack每次执行命令都打印大段 sunset 公告:上游弃用警告(2026-01-01 后归档),不影响功能,Socialhome 搜索栈仍可用。- 设置了
REDIS_URL会直接ImproperlyConfigured起不来:该环境变量已废弃,官方只认REDIS_HOST/REDIS_PORT/REDIS_DB/REDIS_PASSWORD(制品 settings 源码 80-84 行实查)。
十三、小结与关联
四层架构(后端制品 + PostgreSQL + Redis + nginx 双职责 LB)是官方 Docker 路线的全部要件;本指南的 compose、nginx、.env 三份文件均为当天跑通的原文。部署完成后:
- 配置项逐项语义与调优见 《Socialhome 0.24.0 配置参数详解》;
- 迁移、建号、队列、搜索索引等全部命令行操作见 《Socialhome 0.24.0 常用 CLI 命令与工具详解》;
- 产品定位与选型依据见 《Socialhome 0.24.0 介绍与选型指南》。