OSSN 10.1 Docker Compose 部署指南
OSSN 10.1 Docker Compose 部署:官方部署仓库改造为 PHP 8.2 + MySQL 8.0 双服务栈,curl 非交互跑通三步安装向导并完成管理员登录验证,沉淀 build.zip 不可达、AllowOverride 缺失、安装器自环检查失败三则排障实录,全部命令与回显实测。
OSSN 10.1 Docker Compose 部署指南
目标:以官方部署仓库
opensource-socialnetwork/docker为基线,构建 OSSN 10.1 的 Docker Compose 生产栈(Apache PHP 8.2 应用 + MySQL 8.0 双服务),用 curl 非交互跑通官方三步安装向导(install → account → finish)并完成管理员登录验证;同时完整记录官方镜像路径的三个坑(build.zip 不可达、AllowOverride 缺失、安装器自环检查失败)与本地化改造方案。已在 Ubuntu 24.04.5 LTS + Docker 29.9.2 + Compose v5.6.1 环境全量实测通过,文中所有命令与回显均为实测原文。
一、环境信息
本文所有命令与输出均在以下环境实测采集:
- 操作系统:Ubuntu 24.04.5 LTS(x86_64,kernel 7.0.0-38-generic)
- Docker:29.9.2(含 Docker Compose v5.6.1 插件)
- OSSN:10.1(GitHub tag
10.1;源码包ossn-10.1.tar.gz,sha256c4e68e7b44d0e2bfc9a983d4d81f0e39398ffd5da669124f59849ba53f876506) - 应用运行时:PHP 8.2.35(
php:8.2-apache基底)+ gd mysqli zip mbstring pdo_mysql opcache exif,Apache 开 mod_rewrite - 数据库:MySQL 8.0.46(
mysql:8.0) - 部署目录:
/opt/ossn(本文示例路径;实测宿主目录为/opt/data/quzuo/tmp/ossn/compose,compose 内挂载全部为./相对路径,不影响回显内容) - 站点地址:
http://127.0.0.1:8139/(端口槽位 8128–8152 中已占 8128/8133/8138/8143/8144/8147/8148,本栈取空闲的 8139) - 管理员账号:
admin/q1w2e3r4(演示口令) - 数据库账号:库/用户/口令
ossn/ossn/q1w2e3r4,root 口令q1w2e3r4;3306 不对外发布,仅自定义网络内访问 - 自定义网络:
ossn-101-stack_ossn-net(子网10.89.60.0/24,网关10.89.60.1;静态 IP:db10.89.60.10、web10.89.60.11;注意项目名中的点号被 Compose 规范化剔除,见 11.2) - 两服务常驻内存实测(安装完成并浏览若干页面后采样,
docker stats --no-stream):
| 服务 | 内存占用 | 说明 |
|---|---|---|
| ossn-10.1-web | 49.15MiB | Apache + PHP 8.2(OSSN 本体) |
| ossn-10.1-db | 423.1MiB | MySQL 8.0(11 张表) |
| 合计 | 约 472MiB | 1GB 内存宿主即可运行(MySQL 为主要开销,可继续调低缓冲池) |
二、镜像选型说明
OSSN 官方提供部署仓库但不发布预构建镜像——官方仓库 opensource-socialnetwork/docker(main 分支)只有三个文件:Dockerfile、docker-compose.yml、settings.php,官方 compose 的 web 服务写作 build: context: https://github.com/opensource-socialnetwork/docker.git,即每次部署都要从 Git 仓库现场构建,Docker Hub 上没有 opensourcesocialnetwork/* 之类的官方组织镜像(Docker Hub 检索实查,2026-11-02)。
官方 Dockerfile 的逐行逻辑(2026-11-02 实查):
- 基础
php:8.1-apache,apt 装libpng-dev libjpeg-dev libfreetype6-dev libzip-dev libonig-dev libxml2-dev等编译依赖,docker-php-ext-install gd mysqli zip mbstring pdo_mysql opcache exif,a2enmod rewrite; ADD https://www.opensource-socialnetwork.org/download_ossn/latest/build.zip下载官方发布包解压到/var/www/html;- 用
curl从 GitHub raw 拉仓库内settings.php替换installation/pages/settings.php:安装页的数据库四字段改为按环境变量MYSQL_USER/MYSQL_PASSWORD/MYSQL_DATABASE预填且readonly,dbhost 固定为db(compose 服务名),datadir 固定/var/www/ossn_data/——这是实现"环境变量驱动安装"的关键机制; mkdir /var/www/ossn_data属www-data、EXPOSE 80、CMD ["apache2-foreground"];- 官方 compose:web(
80:80、命名卷ossn_data:/var/www/ossn_data、envOSSN_DATA/MYSQL_*)+ db(mysql:8.0、命名卷db_data)。
官方路径在本实测环境存在三个不可用/不完整点,本文 Dockerfile 针对性改造(改动全部标注于 4.1):
| # | 官方做法 | 问题 | 本文改造 |
|---|---|---|---|
| 1 | ADD .../build.zip 构建期下载官网 | 官网被 Cloudflare 拦截,容器内直连亦不可达(实测超时) | 宿主先取 GitHub codeload 包并 sha256 校验,构建时 COPY 本地包 |
| 2 | 仅 a2enmod rewrite | Debian 默认 AllowOverride None,根 .htaccess 不生效,伪静态与内部路径屏蔽全部失效 | 追加 conf:<Directory /var/www/html> AllowOverride All,并预置 .htaccess |
| 3 | 基础镜像 php:8.1-apache | PHP 8.1 已于 2024-12 停止安全维护 | 升级 php:8.2-apache(满足 OSSN ≥8.0 要求) |
💡 技术拓展:PHP 社交/社区类软件的容器交付形态主要有三类——
形态 代表 取舍 官方组织预构建镜像 + 版本 tag MyBB(mybb/mybb)、Grafana 拉取即用、升级改 tag 官方部署仓库本地构建 OSSN(opensource-socialnetwork/docker)、Misago 应用与编排同仓库演进;首次构建耗时、依赖构建期网络 无官方容器化、社区 compose phpBB 灵活但质量参差,供应链风险自担 OSSN 属第二类:官方给 Dockerfile 但不给镜像,构建期还要从官网拉包——这正是本文把"下载"前置到宿主、把"构建"留在本地的原因。
三、前置条件
3.1 Docker 与 Compose 插件
宿主机需 Docker 24+ 与 docker compose v2+ 插件。验证:
docker --version && docker compose version
实测回显:
Docker version 29.9.2, build a82e528
Docker Compose version v5.6.1
3.2 端口规划
官方 compose 示例发布 80;本实测宿主在 8128–8152 规划段内取 8139。确认空闲:
ss -tlnp | grep ':8139'
实测回显:无输出(= 空闲)。部署完成后监听:
ss -ltn | grep 8139
实测回显:
LISTEN 0 4096 0.0.0.0:8139 0.0.0.0:*
LISTEN 0 4096 [::]:8139 [::]:*
MySQL 3306 留在自定义网络内,不发布宿主端口。
3.3 网段规划
多栈共存建议显式声明子网。检查空闲:
ip route | grep '10.89.60'
实测回显:无输出(= 10.89.60.0/24 空闲,本栈独占)。
3.4 源码包准备
官方 build.zip 不可达(见第二章),改从 GitHub codeload 取 tag 10.1 源码包并校验:
curl -sL -o ossn-10.1.tar.gz https://codeload.github.com/opensource-socialnetwork/opensource-socialnetwork/tar.gz/refs/tags/10.1
sha256sum ossn-10.1.tar.gz
实测回显:
c4e68e7b44d0e2bfc9a983d4d81f0e39398ffd5da669124f59849ba53f876506 /opt/data/quzuo/tmp/ossn/compose/ossn-10.1.tar.gz
⚠️ 注意 GitHub 源码包与官网 build.zip 的一个实际差异:仓库
.gitignore排除了根目录.htaccess,源码包内没有该文件(官方 build.zip 有)。OSSN 安装器会在安装页首次加载时从installation/configs/htaccess.dist自动生成它,本文 Dockerfile additionally 预置一份(见 4.1),保证容器重建后伪静态不丢。
3.5 目录结构
mkdir -p /opt/ossn/data/{db,ossn}
data/db/:MySQL 数据目录(bind mount);data/ossn/:OSSN 用户数据目录(bind mount,对应容器内/var/www/ossn_data);configurations/:OSSN 配置目录(bind mount,必须预先播种,见 3.6);Dockerfile、docker-compose.yml、settings.php、ossn-10.1.tar.gz:编排四件套。
3.6 configurations 目录播种(关键前置)
OSSN 安装器生成配置的方式是读取 configurations/ossn.config.db.example.php 与 ossn.config.site.example.php 模板做占位符替换(OssnInstall.php 的 configurations_db()/configurations_site())。本文把 configurations/ 做成 bind mount 以持久化配置(见第八章),因此宿主机目录必须先从源码包复制初始内容,否则安装器读不到模板直接报 "all:files:required":
tar -xzf ossn-10.1.tar.gz
cp -a opensource-socialnetwork-10.1/configurations /opt/ossn/configurations
chown -R 33:33 /opt/ossn/configurations /opt/ossn/data/ossn
chown 33:33 即容器内 www-data 的 uid/gid——bind mount 保留宿主属主,Apache 子进程以 www-data 运行,安装器要往这个目录写两个配置文件。
四、部署步骤
4.1 应用镜像 Dockerfile
/opt/ossn/Dockerfile(基于官方 Dockerfile 改造,逐行注释标出改动):
# OSSN 10.1 应用镜像(基于官方 opensource-socialnetwork/docker 仓库 Dockerfile 改造)
# 改造点:php:8.1-apache -> php:8.2-apache;build.zip -> 本地源码包 COPY;
# settings.php 本地化 COPY;新增 AllowOverride All 与预置 .htaccess
FROM php:8.2-apache
# 系统依赖与 PHP 扩展(与官方一致)
RUN apt-get update && apt-get install -y \
unzip zip \
libpng-dev libjpeg-dev libfreetype6-dev libzip-dev libonig-dev libxml2-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install gd mysqli zip mbstring pdo_mysql opcache exif \
&& a2enmod rewrite \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# 允许 .htaccess 生效(OSSN 伪静态依赖根目录 .htaccess)
RUN printf '<Directory /var/www/html>\n AllowOverride All\n Require all granted\n</Directory>\n' \
> /etc/apache2/conf-available/ossn.conf \
&& a2enconf ossn
# 源码包本地构建(官方路径为下载 build.zip,其官网被 CDN 拦截时不可用)
COPY ossn-10.1.tar.gz /tmp/ossn.tar.gz
RUN mkdir -p /tmp/ossnsrc \
&& tar -xzf /tmp/ossn.tar.gz -C /tmp/ossnsrc \
&& cp -a /tmp/ossnsrc/opensource-socialnetwork-10.1/. /var/www/html/ \
&& rm -rf /tmp/ossnsrc /tmp/ossn.tar.gz
# 预置根 .htaccess(安装器本应在安装页首次加载时生成,预置后容器重建不丢伪静态)
RUN cp /var/www/html/installation/configs/htaccess.dist /var/www/html/.htaccess
# 用官方 docker 仓库 settings.php 替换安装页(DB 字段按环境变量预填、dbhost=db)
COPY settings.php /var/www/html/installation/pages/settings.php
# 数据目录(必须位于安装目录之外)
RUN mkdir -p /var/www/ossn_data \
&& chgrp www-data /var/www/ossn_data && chmod g+w /var/www/ossn_data \
&& chown -R www-data:www-data /var/www/html /var/www/ossn_data \
&& chmod -R 755 /var/www/html
EXPOSE 80
CMD ["apache2-foreground"]
其中 settings.php 直接取官方仓库同名文件(安装页替换件,见第二章),保存为 /opt/ossn/settings.php:
curl -sL -o settings.php https://raw.githubusercontent.com/opensource-socialnetwork/docker/main/settings.php
4.2 编排文件 docker-compose.yml
name: ossn-10.1-stack
networks:
ossn-net:
driver: bridge
ipam:
config:
- subnet: 10.89.60.0/24
gateway: 10.89.60.1
services:
db:
image: mysql:8.0
container_name: ossn-10.1-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: q1w2e3r4
MYSQL_DATABASE: ossn
MYSQL_USER: ossn
MYSQL_PASSWORD: q1w2e3r4
volumes:
- ./data/db:/var/lib/mysql
networks:
ossn-net:
ipv4_address: 10.89.60.10
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-pq1w2e3r4"]
interval: 10s
timeout: 5s
retries: 12
web:
build: .
container_name: ossn-10.1-web
restart: unless-stopped
ports:
- "8139:80"
environment:
MYSQL_DATABASE: ossn
MYSQL_USER: ossn
MYSQL_PASSWORD: q1w2e3r4
OSSN_DATA: /var/www/ossn_data
volumes:
- ./data/ossn:/var/www/ossn_data
- ./configurations:/var/www/html/configurations
networks:
ossn-net:
ipv4_address: 10.89.60.11
depends_on:
db:
condition: service_healthy
关键项逐项说明:
name: ossn-10.1-stack:显式项目名,防止与其他组件的 compose 目录互相down误删;- db:
MYSQL_DATABASE/USER/PASSWORD首次初始化时预建库与业务账号,安装向导直接连用;healthcheck 用mysqladmin ping把关,web 以condition: service_healthy依赖,避免 Apache 起来时数据库未就绪; - web:
build: .本地构建(对应官方build: context: https://github.com/...的现场构建形态);MYSQL_*三个变量不是给 OSSN 运行时读的——OSSN 核心不读任何环境变量,它们只被安装页settings.php的getenv()预填进表单(见 4.6 与第六章);OSSN_DATA同理仅为标注,真实数据目录由安装表单的datadir字段决定; - 两个 bind mount:
./data/ossn持久化用户数据(图片/附件),./configurations持久化安装生成的配置文件(播种要求见 3.6,机制见第八章); - 静态 IP 便于巡检对照(4.4 验证),非必需项。
语法校验:
cd /opt/ossn && docker compose config --quiet && echo "config OK"
实测回显:
config OK
4.3 构建应用镜像
cd /opt/ossn && docker compose build
实测回显(输出节选,构建尾部):
#10 [5/8] RUN mkdir -p /tmp/ossnsrc && tar -xzf /tmp/ossn.tar.gz -C /tmp/ossnsrc && cp -a /tmp/ossnsrc/opensource-socialnetwork-10.1/. /var/www/html/ && rm -rf /tmp/ossnsrc /tmp/ossn.tar.gz
#10 DONE 0.4s
#11 [6/8] RUN cp /var/www/html/installation/configs/htaccess.dist /var/www/html/.htaccess
#11 DONE 0.3s
#12 [7/8] COPY settings.php /var/www/html/installation/pages/settings.php
#12 DONE 0.1s
#13 [8/8] RUN mkdir -p /var/www/ossn_data && chgrp www-data /var/www/ossn_data && chmod g+w /var/www/ossn_data && chown -R www-data:www-data /var/www/html /var/www/ossn_data && chmod -R 755 /var/www/html
#13 DONE 1.1s
#14 exporting to image
#14 naming to docker.io/library/ossn-101-stack-web:latest done
#14 DONE 1.2s
#15 resolving provenance for metadata file
#15 DONE 0.0s
Image ossn-101-stack-web Built
镜像名由 Compose 按"项目名-服务名"自动生成(ossn-10.1-stack 中的点被剔除,故为 ossn-101-stack-web)。体积实测:
docker images ossn-101-stack-web --format '{{.Repository}}:{{.Tag}} {{.Size}}'
ossn-101-stack-web:latest 782MB
4.4 启动与网络验证
docker compose up -d
实测回显:
Container ossn-10.1-db Creating
Container ossn-10.1-db Created
Container ossn-10.1-web Creating
Container ossn-10.1-web Created
Container ossn-10.1-db Starting
Container ossn-10.1-db Started
Container ossn-10.1-db Waiting
Container ossn-10.1-db Healthy
Container ossn-10.1-web Starting
Container ossn-10.1-web Started
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
ossn-10.1-db mysql:8.0 "docker-entrypoint.s…" db 20 seconds ago Up 18 seconds (healthy) 3306/tcp, 33060/tcp
ossn-10.1-web ossn-101-stack-web "docker-php-entrypoi…" web 19 seconds ago Up 8 seconds 0.0.0.0:8139->80/tcp, [::]:8139->80/tcp
网络与 IP 验证:
docker network ls | grep ossn
docker inspect ossn-10.1-web --format '{{range $k,$v := .NetworkSettings.Networks}}{{$k}} => {{$v.IPAddress}}{{end}}'
实测回显:
ef09c60ec787 ossn-101-stack_ossn-net bridge local
ossn-101-stack_ossn-net => 10.89.60.11
4.5 安装器前置检查页
OSSN 安装向导是 Web 表单(installation/),官方文档没有 CLI 安装器;但三步提交的全部字段都在表单里,用 curl 即可非交互等价执行。先看 Prerequisites 检查页:
curl -s http://127.0.0.1:8139/installation/ | grep -oE 'ossn-installation-(success|fail)">[^<]*'
实测回显:
ossn-installation-success">PHP 8.2.35
ossn-installation-success">PHP allow_url_fopen ENABLED
ossn-installation-success">PHP ZipArchive ENABLED
ossn-installation-success">PHP CURL
ossn-installation-success">PHP GD LIBRARY
ossn-installation-success">PHP openssl
ossn-installation-success">PHP SimpleXML
ossn-installation-success">PHP json
ossn-installation-success">PHP fileinfo
ossn-installation-success">PHP mbstring
ossn-installation-success">PHP exif
ossn-installation-success">MYSQLI ENABLED
ossn-installation-success">APACHE ENABLED
ossn-installation-fail">Failed to connect to 127.0.0.1 port 8139 after 0 ms: Could not connect to server
ossn-installation-success">CONFIGURATION DIRECTORY WRITEABLE
倒数第二行的 fail 是 mod_rewrite 自检项——安装器在容器内用 curl 回访站点 URL http://127.0.0.1:8139/rewrite.php,而 8139 只在宿主发布、容器内 Apache 监听 80,所以自环连接失败。这是端口映射部署的固有现象,不影响安装(检查项为提示性),排障与消除方法见 11.1。
4.6 第一步:写配置 + 导入 SQL(action=install)
先建会话并取安装表单(settings.php 替换件把 DB 字段按环境变量预填为 readonly):
curl -s -c cj.txt 'http://127.0.0.1:8139/installation/' -o /dev/null
curl -s -b cj.txt 'http://127.0.0.1:8139/installation/?page=settings' | grep -E 'form action|input type|name=|value='
实测回显:
<div><div class="layout-installation"><h2>Site Settings</h2><form action="http://127.0.0.1:8139/installation/?action=install" method="post">
<input type="text" name="dbuser" placeholder="Database User" value="ossn" readonly="readonly"/>
<input type="password" name="dbpwd" placeholder="Database Password" value="q1w2e3r4" readonly="readonly"/>
<input type="text" name="dbname" placeholder="Database Name" value="ossn" readonly="readonly"/>
<input type="text" name="dbhost" placeholder="Database Host" value="db" readonly="readonly" />
<input type="text" name="sitename" placeholder="Website name"/>
<input type="text" name="owner_email" placeholder="Site Owner Email"/>
<input type="text" name="notification_email" placeholder="Notification Email" value=""/>
<input type="hidden" name="url" value="http://127.0.0.1:8139/"/>
<input type="text" name="datadir" value="/var/www/ossn_data/" readonly="readonly" />
<input type="submit" value="Install" class="button-blue primary">
提交安装(字段与浏览器表单完全一致):
curl -s -b cj.txt -c cj.txt -X POST 'http://127.0.0.1:8139/installation/?action=install' \
-d 'dbuser=ossn' -d 'dbpwd=q1w2e3r4' -d 'dbhost=db' -d 'dbname=ossn' \
-d 'url=http://127.0.0.1:8139/' -d 'datadir=/var/www/ossn_data/' \
-d 'owner_email=admin@quzuo.net' -d 'notification_email=noreply@quzuo.net' \
-d 'sitename=OSSN Demo' -L | grep -oE '<title>[^<]*</title>|Admin Account|name="[a-z_]+"' | sort -u
实测回显(返回 Account 步骤页即安装成功):
Admin Account
name="birthday"
name="birthm"
name="birthy"
name="email"
name="email_re"
name="firstname"
name="lastname"
name="password"
name="username"
<title>Account settings</title>
Username
此步做了三件事:连接 db 服务导入 installation/sql/opensource-socialnetwork.sql(替换 <<owner_email>> <<notification_email>> <<sitename>> <<secret>> 占位符,建 11 张表)、把两个 .example.php 模板渲染成 configurations/ossn.config.db.php 与 ossn.config.site.php(见第八章回显)、执行 post_install/ 钩子。
4.7 第二步:创建管理员(action=account)
curl -s -b cj.txt -c cj.txt -X POST 'http://127.0.0.1:8139/installation/?action=account' \
-d 'username=admin' -d 'firstname=Admin' -d 'lastname=User' \
-d 'email=admin@quzuo.net' -d 'email_re=admin@quzuo.net' -d 'password=q1w2e3r4' \
-d 'gender=male' -d 'birthday=2' -d 'birthm=11' -d 'birthy=1990' -L | grep -oE '<title>[^<]*</title>|Finish'
实测回显:
<title>Installed</title>
Finish
finish
Finish
十个字段全部必填。提交后直接渲染 Installed 完成页(会话此时已以 admin 身份登录)。
4.8 第三步:锁定安装器(action=finish)
curl -s -b cj.txt -c cj.txt -L 'http://127.0.0.1:8139/installation?action=finish' -o /dev/null -w 'finish -L => %{http_code} %{url_effective}\n'
实测回显:
finish -L => 200 http://127.0.0.1:8139/administrator
finish 写入 installation/INSTALLED 文件后 301 跳 /administrator;安装器被永久锁定:
curl -s http://127.0.0.1:8139/installation/
实测回显:
It seems the Open Source Social Network is already installed
4.9 管理员登录验证(干净会话)
curl -s -c lj.txt 'http://127.0.0.1:8139/login' -o login.html
grep -oE 'name="ossn_token" value="[^"]*"' login.html
登录表单带 CSRF 令牌(ossn_token + ossn_ts),POST 到伪静态端点 /action/user/login:
TOKEN=$(grep -oE 'name="ossn_token" value="[^"]*"' login.html | sed 's/.*value="//;s/"//')
TS=$(grep -oE 'name="ossn_ts" value="[^"]*"' login.html | sed 's/.*value="//;s/"//')
curl -s -b lj.txt -c lj.txt -X POST 'http://127.0.0.1:8139/action/user/login' \
-d "username=admin" -d "password=q1w2e3r4" -d "ossn_token=$TOKEN" -d "ossn_ts=$TS"
实测回显(JSON):
{"redirect":"http:\/\/127.0.0.1:8139\/home"}
curl -s -b lj.txt -o /dev/null -w 'administrator => %{http_code}\n' 'http://127.0.0.1:8139/administrator'
curl -s -b lj.txt 'http://127.0.0.1:8139/administrator' | grep -oE '<title>[^<]*</title>'
实测回显:
administrator => 200
<title>Dashboard : OSSN Demo</title>
后台仪表盘 200,登录验证通过。伪静态与匿名行为一并确认:
curl -s -o /dev/null -w '/home(匿名) => %{http_code} -> %{redirect_url}\n' http://127.0.0.1:8139/home
curl -s http://127.0.0.1:8139/rewrite.php
实测回显:
/home(匿名) => 302 -> http://127.0.0.1:8139/login
1
/home 未登录 302 到 /login(路由重写生效);rewrite.php 输出 1(.htaccess → installation/tests/apache_rewrite.php 重写链路正常)。
五、数据持久化说明
本栈三个 bind mount 的分工与内容:
| 宿主路径 | 容器路径 | 内容 | 实测体积(安装后) |
|---|---|---|---|
./data/db | /var/lib/mysql | MySQL 全部数据(11 张表) | 常规 ibdata/binlog |
./data/ossn | /var/www/ossn_data | OSSN 用户数据(图片、附件、组件缓存) | du -sh 实测 1.1M |
./configurations | /var/www/html/configurations | 安装生成的两个配置文件 + 装配清单 + dcache | 6 个文件 |
数据目录结构(安装后 find 实测):
/var/www/ossn_data
/var/www/ossn_data/system
/var/www/ossn_data/system/plugins_paths
/var/www/ossn_data/system/locales
不在持久化范围内的:/var/www/html 应用代码本体(烧在镜像里,升级镜像即换代码)、cache/(css/js 压缩缓存,可再生)、installation/INSTALLED 锁定文件(镜像层,容器重建后消失——但站点以 configurations/ 两文件存在与否判断是否已安装,不受影响;重装风险见 11.4)。
备份口径:停栈后打包 data/db + data/ossn + configurations 三目录即可完整恢复;configurations 里含数据库明文口令,注意权限。
六、环境变量表
先说透一个容易误解的点:OSSN 应用本体不读取任何环境变量(核心配置全部来自 configurations/*.php 与数据库 ossn_site_settings 表)。本编排里的 env 分两类:
db 服务(mysql:8.0 镜像标准初始化变量,真实生效):
| 变量 | 实测值 | 作用 |
|---|---|---|
MYSQL_ROOT_PASSWORD | q1w2e3r4 | root 口令,初始化必需 |
MYSQL_DATABASE | ossn | 首次启动预建库 |
MYSQL_USER | ossn | 预建业务账号 |
MYSQL_PASSWORD | q1w2e3r4 | 业务账号口令 |
web 服务(仅供安装页 settings.php 预填与标注,非运行时配置):
| 变量 | 实测值 | 消费方 |
|---|---|---|
MYSQL_DATABASE / MYSQL_USER / MYSQL_PASSWORD | 同 db 侧 | getenv() 渲染进安装表单 readonly 字段(4.6 回显可见) |
OSSN_DATA | /var/www/ossn_data | 官方 compose 遗留标注;真实 datadir 由表单 datadir 字段决定(settings.php 中 readonly,值来自 OssnInstallation::DefaultDataDir() 计算) |
安装完成后,这些变量对站点行为不再有任何影响;改站点 URL、数据目录要动配置文件(见 7.2 与 11.5)。
七、配置参数说明
安装生成的两份配置全文(容器内 cat 实测回显):
docker exec ossn-10.1-web cat /var/www/html/configurations/ossn.config.db.php /var/www/html/configurations/ossn.config.site.php
$Ossn->host = 'db';
$Ossn->port = '3306';
$Ossn->user = 'ossn';
$Ossn->password = 'q1w2e3r4';
$Ossn->database = 'ossn';
$Ossn->url = 'http://127.0.0.1:8139/';
$Ossn->userdata = '/var/www/ossn_data/';
文件层配置就这七个参数(另有 ossn.config.dcache.php 动态缓存默认 disabled),其余站点参数全部在数据库 ossn_site_settings 表(实测安装后 14 行:theme=goblue、site_name、language=en、cache=1、owner_email、notification_email、upgrades(38 个升级脚本记账)、display_errors、site_key、site_version=10.1 等)。逐项详解、修改方式与生产模板见《OSSN 10.1 配置参数详解》。
八、配置文件挂载
为什么把 configurations/ 做成 bind mount:官方形态下它随代码烧进镜像,容器重建(升级镜像、down && up)后安装器生成的两个配置文件丢失,站点回到"未安装"状态,必须重跑安装向导。bind mount + 播种(3.6)后:
- 安装器写入的
ossn.config.db.php/ossn.config.site.php落在宿主,重建容器零影响; - ACP"动态缓存"页保存设置时回写的
ossn.config.dcache.php(actions/administrator/cache/dynamic.php用file_put_contents写该文件)同样持久化; - 代价:挂载遮蔽镜像内同名目录,镜像升级时该目录的新模板文件不会自动同步,大版本升级需人工比对
configurations/内容(新增.php清单文件要手动合并)。
权限要点:宿主目录属主必须 chown -R 33:33(容器内 www-data),否则安装器写配置报 "CONFIGURATION DIRECTORY WRITEABLE" 检查失败(该项在 4.5 回显中为 success 即权限正确)。
九、等价 docker run
compose 的 web 服务可翻译为一条 docker run(复用同一网络与挂载)。实测:先 docker compose stop web,再:
docker run -d --name ossn-10.1-web-run \
--network ossn-101-stack_ossn-net -p 8139:80 \
-e MYSQL_DATABASE=ossn -e MYSQL_USER=ossn -e MYSQL_PASSWORD=q1w2e3r4 \
-e OSSN_DATA=/var/www/ossn_data \
-v $(pwd)/data/ossn:/var/www/ossn_data \
-v $(pwd)/configurations:/var/www/html/configurations \
ossn-101-stack-web:latest
实测回显:
7268015b4af8c9745ffa974c3ec6e78552e8396b78fcad7beeb31d733e684dee
等价形态首页 => 200
<title>Welcome : OSSN Demo</title>
站点在裸 run 形态下完整可用(复用 bind mount 的配置与数据)。验证后清理并复原 compose 托管:
docker rm -f ossn-10.1-web-run
docker compose up -d web
实测回显:
ossn-10.1-web-run
Container ossn-10.1-db Running
Container ossn-10.1-db Waiting
Container ossn-10.1-db Healthy
Container ossn-10.1-web Starting
Container ossn-10.1-web Started
compose 复原 => 200
十、常用运维命令
# 状态与端口
docker compose ps
# 应用日志(Apache access/error)
docker compose logs --tail=50 web
# 滚动重启应用(配置改动后)
docker compose restart web
# 进入 PHP 运行时执行 CLI 入口(见[《OSSN 10.1 常用 CLI 命令与工具详解》](https://www.quzuo.net/document/t6y1VFz3w78H))
docker compose exec web php /var/www/html/system/handlers/cli --handler=EnableCache
# 查库
docker compose exec db mysql -uossn -pq1w2e3r4 ossn -e "SHOW TABLES;"
# 资源占用
docker stats --no-stream ossn-10.1-web ossn-10.1-db
# 完整下线(数据在 bind mount 中保留)
docker compose down
docker compose restart web 实测回显:
Container ossn-10.1-web Restarting
Container ossn-10.1-web Started
restart 后站点即恢复(GET / 200)。MySQL 11 张表实测:
docker compose exec db mysql -uossn -pq1w2e3r4 ossn -N -e "SHOW TABLES;"
ossn_annotations ossn_components ossn_entities ossn_entities_metadata ossn_likes ossn_messages ossn_notifications ossn_object ossn_relationships ossn_site_settings ossn_users
十一、常见问题
11.1 Prerequisites 页 mod_rewrite 自检失败
现象:4.5 回显中 ossn-installation-fail">Failed to connect to 127.0.0.1 port 8139 after 0 ms: Could not connect to server。原因:安装器在容器内 curl 站点 URL 的 rewrite.php 做端到端验证,而站点 URL 是宿主映射地址(url 表单字段),容器内没有 8139 监听。影响:仅提示性检查,实测安装与伪静态均正常(4.9 的 /home 302 与 rewrite.php 输出 1 证明重写已生效)。消除方法:安装提交前在 web 服务加 extra_hosts 不可行(127.0.0.1 是容器自身回环);实用做法是安装期间临时把站点 URL 表单值提交为 http://localhost/(容器内 80),装完再改 ossn.config.site.php 的 $Ossn->url 回宿主地址——或者接受这一行 fail,不影响任何功能。
11.2 项目名中的点号被剔除
name: ossn-10.1-stack 声明后,实际网络/镜像名是 ossn-101-stack_ossn-net、ossn-101-stack-web——Compose 将项目名规范化为 [a-z0-9] 字符集(点号被删除)。按官方 compose 的 docker compose down 无感知,但手工 docker network rm/docker rmi 时要用规范化后的名字(4.4 回显为准),别拿声明名去猜。
11.3 configurations bind mount 未播种导致安装失败
空目录直接挂载会遮蔽镜像内的 .example.php 模板,action=install 抛 "all:files:required" 类错误。必须按 3.6 先 cp -a 播种再挂载。若坚持用官方"配置烧镜像"形态,删掉该 volume 行即可,代价见第八章。
11.4 容器重建后能否重装
docker compose down && up 后 installation/INSTALLED(镜像层)消失,/installation/ 重新可达 Prerequisites 页;但只要 configurations/ 两个配置文件还在(bind mount),站点本体照常运行,切勿误点重装——重装会重跑 SQL 导入(表已存在多数语句报错被安装器吞掉)并覆盖配置。若需彻底重装,先清 data/db 与 configurations/ossn.config.*.php。
11.5 官网 build.zip 不可达
官方 Dockerfile 的 ADD https://www.opensource-socialnetwork.org/download_ossn/latest/build.zip 在本实测环境(容器内直连与宿主直连均)超时——官网全站 Cloudflare 强校验。替代源即 3.4 的 GitHub codeload tag 包(注意 3.4 的 .htaccess 差异说明)。若你的服务器可直连官网,官方 Dockerfile 原样可用。
十二、参考链接
- OSSN 源码仓库:https://github.com/opensource-socialnetwork/opensource-socialnetwork (tag
10.1,查询日期 2026-11-02) - 官方 Docker 部署仓库(本文基线):https://github.com/opensource-socialnetwork/docker
- 官方安装 wiki:https://www.opensource-socialnetwork.org/wiki/view/706/how-to-install-open-source-social-network
- 官方下载页:https://www.opensource-socialnetwork.org/download
- 站内系列:《OSSN 介绍与选型指南》 、《OSSN 10.1 配置参数详解》 、《OSSN 10.1 常用 CLI 命令与工具详解》