Gerbera Docker Compose 部署实战

Gerbera 3.3.0 + MariaDB 11.8 双服务 Compose 编排 0→1 实测:config.xml 首启生成与最小定制、Web UI 三步登录握手(admin/q1w2e3r4)、inotify 自动扫描验证、桥接网络 SSDP 受限对比实测与 CDS SOAP Browse 接口级验证,附数据库地址写错导致崩溃-重启循环的完整排障复盘。

GerberaGerberaUPnPDLNA媒体服务器2026/10/28

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)均为本次部署实例值,读者复现时请按自身环境替换。