Gerbera Docker Compose 部署实战
Gerbera 3.3.0 + MariaDB 11.8 双服务 Compose 编排 0→1 实测:config.xml 首启生成与最小定制、Web UI 三步登录握手(admin/q1w2e3r4)、inotify 自动扫描验证、桥接网络 SSDP 受限对比实测与 CDS SOAP Browse 接口级验证,附数据库地址写错导致崩溃-重启循环的完整排障复盘。
Gerbera Docker Compose 部署实战
本文在一台真实 Linux 服务器上完成 Gerbera 3.3.0(UPnP/DLNA 媒体服务器)从 0 到 1 的完整部署实录:MariaDB 11.8 后端双服务编排、config.xml 首启生成与定制、Web UI 账号初始化(admin/q1w2e3r4)、媒体目录导入与 inotify 自动扫描验证、绕过 SSDP 限制直接用 CDS SOAP Browse 接口验证媒体树,并完整复盘一次因数据库地址写错导致的崩溃-重启循环排障过程。全部命令与输出均为 2026-10-28 实测逐行照抄。
前置阅读:不了解 Gerbera 的定位、协议架构与选型结论,先看 《Gerbera 介绍与选型指南》;config.xml 各节参数含义见本专栏《Gerbera 配置参数详解》,日常运维命令见本专栏《Gerbera 常用命令与运维实战(核心篇)》。
一、环境信息与规划
Gerbera 是单进程 C++ 守护进程,一个进程同时承担 SSDP 发现宣告、HTTP 描述/媒体传输、Web UI 与数据库访问,因此编排上只需要「Gerbera 主服务 + 数据库」两个服务实例。本章先交代本次实测的软硬件环境与端口、网络规划。
- 服务器:Linux x86_64(内核 7.0.0-38-generic),已安装 Docker 与 Compose 插件,宿主机局域网地址
192.168.146.128 - 分发包:
gerbera/gerbera:3.3.0(官方分发,内含 pupnp 22.1.0、taglib、libffmpegthumbnailer 等全套依赖)+mariadb:11.8 - 部署根目录:
/opt/data/quzuo/tmp/gerbera/(下文命令均以此目录为工作目录,读者可替换为自己的路径如/opt/gerbera) - Web 端口规划:宿主
8136→ 服务内4949(Gerbera 的 HTTP 服务端口,Web UI、UPnP 描述文档、媒体流传输三合一)。选端口前先确认未被占用:
ss -ltn | grep 8136
实测无输出,即 8136 空闲可用。UPnP 的 SSDP 发现走 UDP 1900 组播,同步确认 ss -lun | grep 1900 无冲突(若宿主上已有其他 UPnP 服务占用 1900/udp,需错开或合并规划)。
- 网络规划:为整个栈建独立桥接网络
10.89.56.0/24,主服务固定10.89.56.10、数据库固定10.89.56.20。固定 IP 的意义在后文排障实录中会体现——数据库地址写死成错误 IP 正是本次部署踩到的最大的坑。
💡 技术拓展:UPnP MediaServer 对外要两类端口——TCP 4949(HTTP:描述文档 + CDS 控制 + 媒体流 + Web UI)与 UDP 1900(SSDP 组播发现,组播地址 239.255.255.250)。前者是「客户端找上门来取内容」的通道,后者是「服务主动告诉局域网我存在」的通道;桥接网络模式下后者的组播很难透出到宿主局域网,本文第六章有对比实测与替代验证方案。
二、目录规划与编排文件
Gerbera 需要持久化三类数据:运行数据目录(配置、缓存)、媒体目录、数据库数据。规划如下目录结构:
/opt/data/quzuo/tmp/gerbera/
├── docker-compose.yml # 编排文件
├── config/
│ └── config.xml # 自定义主配置(以只读方式挂入服务实例)
├── db/ # Gerbera 运行数据目录(首启自动生成的文件落在这里)
├── media/ # 媒体库(音频/视频/照片,只读挂入)
└── backup/ # 数据库备份输出目录
创建目录并放入测试媒体:
mkdir -p /opt/data/quzuo/tmp/gerbera/{config,db,media,backup}
# 准备 8 个测试文件:4 个带完整 ID3 标签的 MP3、1 个 FLAC、1 张 JPG、1 个 MP4
ls /opt/data/quzuo/tmp/gerbera/media/
实测输出:
clip.mp4 photo.jpg tone.flac tone220.mp3 tone440.mp3 tone660.mp3 tone880.mp3 tone990.mp3
编排文件 docker-compose.yml 全文(实测可直接使用):
name: gerbera-330-stack
services:
gerbera:
image: gerbera/gerbera:3.3.0
container_name: gerbera-3.3.0-main
restart: unless-stopped
networks:
gerbera-lan:
ipv4_address: 10.89.56.10
ports:
- "8136:4949" # Web UI + UPnP HTTP(描述文档与媒体流)
- "1900:1900/udp" # SSDP 组播发现
environment:
- TZ=Asia/Shanghai
- IMAGE_PORT=4949 # 启动参数以 --port 覆盖 config.xml 的 port,须同步
volumes:
- ./db:/var/run/gerbera # 运行数据(配置文件、缓存)
- ./config/config.xml:/var/run/gerbera/config.xml:ro # 自定义主配置
- ./media:/mnt/content:ro # 媒体库(只读)
depends_on:
db:
condition: service_healthy
db:
image: mariadb:11.8
container_name: gerbera-3.3.0-mariadb
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
- MARIADB_ROOT_PASSWORD: q1w2e3r4
- MARIADB_DATABASE: gerbera
- MARIADB_USER: gerbera
- MARIADB_PASSWORD: q1w2e3r4
volumes:
- gerbera-db-data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 5s
timeout: 5s
retries: 12
networks:
gerbera-lan:
ipv4_address: 10.89.56.20
networks:
gerbera-lan:
driver: bridge
ipam:
config:
- subnet: 10.89.56.0/24
volumes:
gerbera-db-data:
要点解说:
name: gerbera-330-stack显式指定项目名,避免 Compose 按目录名派生,多栈共存时不串。container_name显式命名两个实例为gerbera-3.3.0-main/gerbera-3.3.0-mariadb,运维命令(查日志、进实例)都靠这两个名字寻址。depends_on: condition: service_healthy让主服务等 MariaDB 健康检查通过后再启动——Gerbera 连不上数据库会直接异常退出(见第七章排障实录),启动顺序约束能挡住大部分首启竞争。./config/config.xml以:ro只读挂入:配置文件由宿主编辑管理,服务实例内不可写,杜绝运行时被意外改写。代价是启动脚本对配置文件做chown/chmod会报两条无害提示(后文有实测)。./media只读挂到实例内/mnt/content,这就是后文 config.xml 里 autoscan 监视的路径。IMAGE_PORT=4949是官方分发包的启动变量,会以--port参数覆盖 config.xml 中的端口设置,两边必须一致,否则 Web UI 与 UPnP 端口会分叉。
三、config.xml 的生成与最小定制
Gerbera 的所有行为由一份 XML 主配置驱动。本章说明首启时配置从哪来、最小可用配置长什么样。
3.1 配置的两种来源
不挂载任何配置直接启动时,Gerbera 会在运行数据目录下自动生成一份默认 config.xml(SQLite 后端、无账号)。也可以不启动服务、直接用 CLI 生成标准配置骨架(该命令只打印到标准输出,不影响在跑服务):
docker exec gerbera-3.3.0-main gerbera --create-config
实测输出(节选,全文 267 行):
2026-10-28 22:49:11 info: Home detected as: /root
<?xml version="1.0" encoding="UTF-8"?>
<config version="2" xmlns="http://gerbera.io/config/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://gerbera.io/config/2 http://gerbera.io/config/2.xsd">
<!--
See https://gerbera.io or read the docs for more
information on creating and using config.xml configuration files.
This file was generated by Gerbera 3.3.0
-->
<server>
<ui enabled="yes" show-tooltips="yes">
<accounts enabled="no" session-timeout="30">
<account user="gerbera" password="gerbera" />
</accounts>
</ui>
<name>Gerbera</name>
<udn>uuid:fc472017-02ba-423a-829c-c12801b01e4a</udn>
...
注意两个默认事实:默认配置 <accounts enabled="no">(Web UI 免登录直接可管),默认存储是 <sqlite3 enabled="yes">;<udn> 每次生成都是随机 UUID——它是 UPnP 设备的唯一标识,客户端靠它识别「这台服务器还是不是原来那台」,正式环境生成一次后就不要再变。
3.2 本文的最小定制
本文在默认骨架上改四处,得到挂载进实例的 config/config.xml(完整逐节详解见本专栏《Gerbera 配置参数详解》):
<server>
<port>4949</port>
<virtualURL>http://192.168.146.128:8136/</virtualURL>
<ui enabled="yes" show-tooltips="yes">
<accounts enabled="yes" session-timeout="30">
<account user="admin" password="q1w2e3r4" />
</accounts>
</ui>
<storage>
<sqlite3 enabled="no">
<database-file>gerbera.db</database-file>
</sqlite3>
<mysql enabled="yes">
<host>10.89.56.20</host>
<port>3306</port>
<username>gerbera</username>
<password>q1w2e3r4</password>
<database>gerbera</database>
</mysql>
</storage>
...
</server>
<import hidden-files="no">
<autoscan use-inotify="auto">
<directory location="/mnt/content" mode="inotify" recursive="yes" hidden-files="no" media-type="Any" />
</autoscan>
...
</import>
<virtualURL>填宿主对外地址:Gerbera 在 SSDP 宣告和媒体 URL 里默认用实例内地址(10.89.56.10:4949),桥接模式下局域网客户端够不到,显式写宿主地址后所有对外 URL 都以它为准。<accounts enabled="yes">+admin/q1w2e3r4:把默认的免登录改为账号保护(流程实测见第四章)。<mysql enabled="yes">:切到 MariaDB 后端,<host>必须填数据库实例在本栈网络里的真实地址 10.89.56.20。<autoscan>:声明对/mnt/content(即宿主 media 目录)做 inotify 实时监视,新文件落盘自动入库(实测见第五章)。
四、启动、首启初始化与 Web UI 账号
准备工作就绪,本章完成启动、观察首启初始化日志、并实测 Web UI 的登录握手。
4.1 启动栈
cd /opt/data/quzuo/tmp/gerbera
docker compose up -d
实测启动后状态:
$ docker compose ps
NAME STATUS PORTS
gerbera-3.3.0-main Up 2 hours 0.0.0.0:8136->4949/tcp, 0.0.0.0:1900->1900/udp
gerbera-3.3.0-mariadb Up 2 hours (healthy) 3306/tcp
4.2 首启初始化日志解读
首启日志是判断部署是否成功的第一手材料:
docker logs gerbera-3.3.0-main 2>&1 | head -30
实测回显(关键行):
chown: /var/run/gerbera/config.xml: Read-only file system
chown: /var/run/gerbera/config.xml: Read-only file system
chmod: /var/run/gerbera/config.xml: Read-only file system
Running as user gerbera instead of root
su-exec gerbera
2026-10-28 20:37:12 info: Gerbera UPnP Server 3.3.0 - https://gerbera.io/
2026-10-28 20:37:12 info: Loading configuration from: /run/gerbera/config.xml
2026-10-28 20:37:12 info: Parsing configuration...
2026-10-28 20:37:12 warning: Error in configuration, could not find command "ffmpeg" in $PATH for '/config/attribute::command'
2026-10-28 20:37:12 warning: Error in configuration, could not find command "vlc" in $PATH for '/config/attribute::command'
2026-10-28 20:37:12 info: Configuration load succeeded.
2026-10-28 20:37:12 info: Validating configuration...
2026-10-28 20:37:12 warning: Found extra config file entry '/config/server/storage/postgres/database'
2026-10-28 20:37:12 warning: Found extra config file entry '/config/server/storage/sqlite3/backup'
...
2026-10-28 20:37:12 info: Configuration check succeeded.
2026-10-28 20:37:12 info: Database doesn't seem to exist. Creating database...
2026-10-28 20:37:12 info: Database created successfully!
2026-10-28 20:37:12 info: 'grb_cds_resource': Adding column 'size'
2026-10-28 20:37:12 info: 'grb_cds_resource': Adding column 'duration'
...
2026-10-28 20:37:12 info: IPv4: Server bound to: 10.89.56.10:4949
2026-10-28 20:37:12 info: The Web UI can be reached by following this link: http://192.168.146.128:8136
逐条解读:
- 开头三条
chown/chmod ... Read-only file system:因为 config.xml 以:ro挂入,启动脚本调整属主失败,提示无害,服务随即降权到gerbera用户正常运行。 could not find command "ffmpeg"/"vlc":默认配置里 transcoding 节引用了 ffmpeg/vlc 外部命令做转码,分发包未预装这两个命令,校验器提出警告。不用转码可忽略;要用进程内转码见配置详解篇。Found extra config file entry .../postgres/...、.../sqlite3/backup:当前启用的是 MySQL 后端,postgres/sqlite3 两节不参与校验,被列为「多余条目」警告,同样无害。Database doesn't seem to exist. Creating database...:首次连接空库时 Gerbera 自动建表,随后一串Adding column是把资源表补齐到当前版本结构——这套自动建库/迁移机制也是将来版本升级时的数据迁移通道(运维篇展开)。- 最后两行宣告绑定成功:
10.89.56.10:4949是栈内地址,http://192.168.146.128:8136是宿主访问入口。
4.3 Web UI 登录握手实测
浏览器访问 http://192.168.146.128:8136/ 即见登录页。Web UI 的接口是单页应用调 REST 风格端点,登录是「取会话 → 取令牌 → 哈希登录」三步握手。用 curl 把整个过程实测一遍(这也是脚本化运维的基础):
# 第 1 步:取会话 ID
curl -s 'http://192.168.146.128:8136/interface?req_type=auth&action=get_sid'
实测回显:
{
"GerberaSID" : "4fe5d180-762e-440a-a9e9-af1969ceed34",
"logged_in" : false,
"sid_was_valid" : false,
"success" : true
}
# 第 2 步:带会话取一次性令牌(参数名是 GerberaSID)
SID=4fe5d180-762e-440a-a9e9-af1969ceed34
curl -s "http://192.168.146.128:8136/interface?req_type=auth&action=get_token&GerberaSID=$SID"
# 回显:{ "token" : "1793198933_adfa1d8e-cd92-4042-8dfb-368c59536838", ... }
# 第 3 步:口令 = md5(token + 明文密码),发起登录
PW=$(python3 -c "import hashlib; print(hashlib.md5(('1793198933_adfa1d8e-cd92-4042-8dfb-368c59536838'+'q1w2e3r4').encode()).hexdigest())")
curl -s "http://192.168.146.128:8136/interface?req_type=auth&action=login&username=admin&password=$PW&GerberaSID=$SID"
实测回显:
{
"success" : true,
"task" : null
}
登录成功。用错口令时接口回显(排障时据此区分「口令错」与「会话错」):
{
"error" : { "code" : 300, "text" : "Invalid username or password" },
"success" : false
}
💡 技术拓展:这套握手是「挑战-应答」机制——服务器发一次性 token,客户端用
md5(token+密码)应答,明文密码与密码本身的哈希都不上线。这意味着两点:一是直接拿password=q1w2e3r4明文调 login 一定失败(实测报No valid handler type之外的鉴权错误);二是 token 一次性且随会话轮换,脚本里必须严格按 get_sid → get_token → login 顺序串联。另外注意 3.3.0 的接口路径是/interface,老资料里的/content/interface已返回 404。
五、媒体导入与自动扫描实测
Gerbera 的媒体导入有两种入口:config.xml 静态声明 autoscan 目录(本文方式,服务启动即监视),以及 Web UI 的 Filesystem 视图手动添加(界面左侧定位目录后点「+」,适合临时目录)。两者的持久化行为有差异,运维篇有对比实测。本章验证静态声明路径下的导入与 inotify 实时捕获。
5.1 首启全量扫描
服务启动后对 autoscan 目录做全量扫描,8 个测试文件全部入库。直接查库核对(表结构详见运维篇):
docker exec gerbera-3.3.0-mariadb mariadb -ugerbera -pq1w2e3r4 gerbera \
-e 'SELECT object_type, COUNT(*) AS cnt FROM mt_cds_object GROUP BY object_type;'
实测回显:
object_type cnt
0 1
1 37
2 74
object_type 含义:0=根、1=目录(container)、2=条目(item)。74 个条目对应 8 个物理文件——一个文件会生成多条目:物理树(PC Directory)里 1 条实体记录,虚拟布局(按艺术家/专辑/年代等)里每个归口再生成 1 条引用记录(ref_id 指回实体)。
5.2 inotify 实时捕获实测
autoscan 用 mode="inotify" 声明后,目录下文件变动由内核 inotify 事件实时推送,无需重启或手动触发。往 media 目录丢一个新文件验证:
cp /opt/data/quzuo/tmp/gerbera/media/tone990.mp3 /opt/data/quzuo/tmp/gerbera/media/tone1100.mp3
sleep 4
docker exec gerbera-3.3.0-mariadb mariadb -ugerbera -pq1w2e3r4 gerbera \
-e "SELECT COUNT(*) AS items FROM mt_cds_object WHERE object_type=2;"
实测回显:
items
85
条目数 74 → 85(新增 1 个实体 + 10 条虚拟布局引用),新文件秒级入库:
id ref_id parent_id dc_title location
122 NULL 2 tone1100 /content/tone1100.mp3
💡 技术拓展:inotify 与 timed 是 autoscan 的两种模式。inotify 订阅内核文件系统事件,增删改秒级触发、零轮询开销,适合活跃媒体库;timed 按
interval秒数周期全量比对,事件可能遗漏但行为可预期,适合 inotify 不可用的网络挂载盘(NFS/SMB 上 inotify 收不到远端变动)。Gerbera 的use-inotify="auto"表示内核支持就启用。定时模式下扫描是「全量重扫该目录」,大库注意 io 压力。
六、绕过 SSDP 限制:CDS SOAP Browse 直接验证
DLNA 客户端「自动发现」依赖 SSDP 组播,而桥接网络下组播很难透出到宿主局域网。本章先用对比实测定量说明限制,再给出不依赖发现的接口级验证方法。
6.1 SSDP 组播发现对比实测
用 M-SEARCH 探测脚本(向 239.255.255.250:1900 组播搜索 UPnP 根设备)从宿主机默认接口发探:
python3 ssdp_probe.py
实测回显:
total devices: 0
绑定到栈所在桥接网络的宿主侧网关地址(10.89.56.1)再探:
python3 ssdp_probe.py 10.89.56.1 5
实测回显:
[+] 10.89.56.10 SERVER=Linux/7.0.0-38-generic, UPnP/1.0, Portable SDK for UPnP devices/22.1.0
LOCATION=http://10.89.56.10:4949/upnp/description.xml
total devices: 1
结论清晰:Gerbera 的 SSDP 宣告只活在桥接网络内部(10.89.56.0/24),宿主默认接口所在的局域网收不到——「服务正常但电视搜不到」正是这个机制。生产上要让局域网设备自动发现,两条路:主服务改用 host 网络模式(SSDP 直接走宿主接口,代价是端口与宿主共享命名空间),或者接受「手动输入服务器地址」的客户端连接方式。无论哪条路,内容目录本身都可用 SOAP 请求直接验证,不依赖发现环节。
6.2 设备描述文档验证
UPnP 客户端发现服务后第一步就是 GET 描述文档,直接 curl 等效验证:
curl -s 'http://192.168.146.128:8136/upnp/description.xml' | head -20
实测回显(节选):
<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:dlna="urn:schemas-dlna-org:device-1-0">
<device>
<friendlyName>Gerbera</friendlyName>
<manufacturer>Gerbera Contributors</manufacturer>
<modelDescription>Free UPnP AV MediaServer, GNU GPL</modelDescription>
<modelNumber>3.3.0</modelNumber>
<UDN>uuid:389848a0-d60d-4fe1-a83f-cdfc2bcd5a99</UDN>
<dlna:X_DLNADOC>DMS-1.50</dlna:X_DLNADOC>
<deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType>
<presentationURL>http://10.89.56.10:4949/</presentationURL>
deviceType=MediaServer:1 与 DMS-1.50(Digital Media Server)宣告了它的 UPnP/DLNA 角色;UDN 与首启生成的 config.xml 中 <udn> 一致。
6.3 CDS Browse 验证媒体树
ContentDirectory 服务是客户端浏览媒体的正式接口,端点 /upnp/control/cds,动作为 SOAP Browse。用脚本对根对象 0 发 BrowseDirectChildren:
python3 cds_browse.py http://127.0.0.1:8136 0
实测回显:
object.container PC Directory
object.container Audio
object.container Photos
object.container Video
object.container.dynamicFolder Music Recently Played
object.container.dynamicFolder Recently Modified
object.container.dynamicFolder Recently Added
根目录 7 个容器:PC Directory(物理目录树)、Audio/Photos/Video(按元数据组织的虚拟布局)、三个 dynamicFolder(config.xml 中 <containers> 节定义的动态筛选视图)。递归遍历可见物理树与虚拟布局双形态(节选):
[1] PC Directory (object.container)
[2] content (object.container)
[97] tone (object.item.audioItem.musicTrack)
res: http://192.168.146.128:8136/media/object_id/97/res_id/0/group/default/ext/file.flac
[3] tone660 (object.item.audioItem.musicTrack)
res: http://192.168.146.128:8136/media/object_id/3/res_id/0/group/default/ext/file.mp3
[32] photo (object.item.imageItem)
res: http://192.168.146.128:8136/media/object_id/32/res_id/0/group/default/ext/file.jpg
[90] clip (object.item.videoItem)
res: http://192.168.146.128:8136/media/object_id/90/res_id/0/group/default/ext/file.und.mp4
[4] Audio (object.container)
[17] Albums (object.container)
[18] Synth Lab (object.container.album.musicAlbum)
[74] Test Tone One (object.item.audioItem.musicTrack)
每条 item 的 res 就是媒体流 URL(宿主地址形态,因配置了 virtualURL),客户端拿到后直接 HTTP 拉流。至此部署闭环验证完成:文件 → 元数据 → 数据库 → 虚拟布局 → UPnP 目录 → 可拉流 URL。
七、排障实录:数据库地址写错引发的崩溃-重启循环
本次部署过程中主服务一度陷入反复重启(docker ps 状态在 Restarting 与 Up 之间抖动)。本章按「现象 → 取证 → 根因 → 修复 → 复核」完整复盘。
现象:docker compose ps 显示 gerbera-3.3.0-main 状态为 Restarting,Web UI 时通时断。
取证:看日志尾部,每次启动都倒在同一步:
docker logs gerbera-3.3.0-main 2>&1 | tail -20
实测回显(崩溃循环的关键行,20:44:10 起每次启动 3 秒后重演):
2026-10-28 20:44:13 info: Configuration check succeeded.
2026-10-28 20:44:13 error: Run: runtime error [/gerbera_build/src/database/mysql/mysql_database.cc:172] virtual void MySQLDatabase::run() Error: Connecting to database 10.89.56.99:3306/gerbera failed: mysql_error (2002): "Can't connect to server on '10.89.56.99' (115)"
随后进程退出、实例被 restart: unless-stopped 拉起、再倒在同一行,20:44:10 至 20:44:36 短短 26 秒内循环了 6 次。
根因:config.xml 的 <mysql><host> 被写成了 10.89.56.99——该地址在本栈网络里没有任何实例监听(MariaDB 实例固定在 10.89.56.20)。mysql_error (2002) 是 MySQL 客户端库的「连不上服务器」错误码,括号里的 115 是 Linux errno(EINPROGRESS,TCP 连接对端无响应超时)。Gerbera 的设计是数据库连接失败即抛异常终止进程,它与崩溃循环之间只差一个自动重启策略。这类「配置指向错误 + 自动重启」组合会把一次性配置错误放大成持续故障,日志量也会暴涨。
修复:把 <host> 改为 10.89.56.20(本栈 MariaDB 固定地址;若未固定 IP,应填服务名 db 让 Docker 内嵌 DNS 解析),保存后重启:
docker restart gerbera-3.3.0-main
docker logs gerbera-3.3.0-main 2>&1 | tail -5
实测回显:
2026-10-28 20:55:56 info: Initialising UPnP with interface: <unset>, port: 4949
2026-10-28 20:55:56 info: IPv4: Server bound to: 10.89.56.10:4949
2026-10-28 20:55:56 info: The Web UI can be reached by following this link: http://192.168.146.128:8136
绑定成功、不再退出,状态恢复稳定 Up。
复核与经验:
- 数据库类故障第一看
mysql_error四元组(错误码 + 目标地址 + 库名 + errno),2002/2003 是网络不可达,1045 是账号问题,1049 是库不存在(Gerbera 能自动建表但建库权限需预授)。 - IP 写死是本次根因的温床。栈内寻址优先用 Compose 服务名(DNS 自动跟随实例),固定 IP 只作为排除 DNS 因素时的备选。
- 观察循环崩溃用
docker logs --tail 50看「最后一条 error」即可定位,不必翻全量。
八、参考链接
- 官网:
https://gerbera.io - 官方文档站(部署/配置章节):
https://docs.gerbera.io/en/stable/ - 官方 Docker Hub 分发页:
https://hub.docker.com/r/gerbera/gerbera - GitHub 主仓库:
https://github.com/gerbera/gerbera - 本专栏认知篇:《Gerbera 介绍与选型指南》
免责声明:本文全部命令与输出于 2026-10-28 在 Gerbera v3.3.0 + MariaDB 11.8 环境实测,文中路径、地址、账号(admin/q1w2e3r4)均为本次部署实例值,读者复现时请按自身环境替换。