Baikal 0.10.1 Docker Compose 部署指南
实测用 Docker Compose 部署 Baikal 0.10.1(ckulka/baikal 镜像 nginx-php8.2 形态):镜像选型、初始化向导、数据持久化、HTTPS 反代要点与常用运维命令全流程。
Baikal 0.10.1 Docker Compose 部署指南
目标:用 Docker Compose 把 Baikal 0.10.1 跑起来并完成初始化向导,覆盖镜像选型、数据持久化、HTTPS 反向代理接入与日常运维命令。全程在真实环境实测:容器 ckulka/baikal:0.10.1-nginx-php8.2、宿主端口 8134、初始化向导与 CalDAV/CardDAV 协议验证全部通过(协议层实测记录另见《Baikal 0.10.1 介绍与选型指南》)。
一、环境信息
- 操作系统:Linux(内核 5.15+,x86_64)
- Docker:Docker Engine 24+,Docker Compose v2(
docker compose子命令) - 部署镜像:
ckulka/baikal:0.10.1-nginx-php8.2(Baikal 0.10.1 + nginx + PHP 8.2) - 宿主端口:8134 → 容器 80
- 持久化:命名卷
config(挂载/var/www/baikal/config)、命名卷data(挂载/var/www/baikal/Specific) - Compose 项目名:
baikal-0101-stack - 实测账号:管理员
admin/q1w2e3r4,DAV 用户root/q1w2e3r4
二、镜像选型说明
Baikal 官方不发布镜像,社区事实标准是 ckulka/baikal(Baikal 官方文档「Installation using Docker (unofficial)」即指向该仓库)。该镜像按 Web 服务器与 PHP 版本提供四个变体系列,均为多架构构建(amd64 / arm32v7 / arm64v8 / i386),weekly 重建的无版本 tag 跟随最新基础镜像:
| Tag 形态 | Web 服务器 | 特点 |
|---|---|---|
ckulka/baikal:<版本>、<版本>-apache | Apache httpd | 最贴近官方部署指南的默认形态;自带 HTTPS 443 与自签名证书,可用 BAIKAL_SERVERNAME / BAIKAL_SERVERALIAS 消除启动警告 |
ckulka/baikal:<版本>-apache-php8.2 | Apache httpd + PHP 8.2 | 同上,锁定 PHP 8.2 |
ckulka/baikal:<版本>-nginx | nginx | 体积显著更小(官方 README:不到 Apache 形态的一半),开箱无警告日志 |
ckulka/baikal:<版本>-nginx-php8.2 | nginx + PHP 8.2 | 本文实测采用的形态 |
版本号 tag 与 Baikal 上游一一对应(0.10.1、0.10.0、0.9.5……最早可追溯到 0.2.7)。本文固定 0.10.1-nginx-php8.2 做可复现部署;生产若想让基础镜像自动获得安全更新,可改用 weekly 重建的 nginx-php8.2 无版本 tag。
💡 说明:镜像内已含 PHP 扩展 curl/mbstring/mysql/pgsql/sqlite3/xml 与 msmtp 邮件客户端,因此 SQLite(默认)、MySQL、PostgreSQL 三种后端与邀约邮件功能无需额外安装。
三、前置条件
- 宿主已安装 Docker Engine 与 Compose v2 插件:
docker compose version能正常输出版本号。 - 端口规划:本指南用 8134 做宿主端口,占用确认
ss -ltn | grep :8134无输出;换端口时同步改 compose 文件映射即可。 - 目录规划:本文所有文件放在
/opt/baikal/。
四、部署步骤
4.1 编写 Compose 文件
创建 /opt/baikal/compose.yaml:
name: baikal-0101-stack
services:
baikal:
image: ckulka/baikal:0.10.1-nginx-php8.2
restart: unless-stopped
ports:
- "8134:80"
volumes:
- config:/var/www/baikal/config
- data:/var/www/baikal/Specific
volumes:
config:
data:
说明:两个卷是 Baikal 的全部可变数据——config/ 放配置文件 baikal.yaml,Specific/ 放 SQLite 数据库文件与安装器禁用标记。程序本体随镜像分发,升级镜像不动这两个卷。
4.2 启动
cd /opt/baikal && docker compose up -d
实测回显:
[+] Running 3/3
✔ Network baikal-0101-stack_default Created
✔ Volume "baikal-0101-stack_config" Created
✔ Volume "baikal-0101-stack_data" Created
✔ Container baikal-0101-stack-baikal-1 Started
状态确认(实测):
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
baikal-0101-stack-baikal-1 ckulka/baikal:0.10.1-nginx-php8.2 "/docker-entrypoint.…" baikal 3 hours ago Up 3 hours (healthy) 0.0.0.0:8134->80/tcp, [::]:8134->80/tcp
启动日志(实测节选,首次启动会执行入口脚本建目录、修正属主、启动 php-fpm):
docker compose logs baikal | head -12
baikal-0101-stack-baikal-1 | 2026/10/30 08:11:00 [notice] 1#1: using the "epoll" event method
baikal-0101-stack-baikal-1 | 2026/10/30 08:11:00 [notice] 1#1: nginx/1.29.0
baikal-0101-stack-baikal-1 | 2026/10/30 08:11:00 [notice] 1#1: start worker processes
首页探活(实测):
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8134/
200
4.3 初始化向导
浏览器打开 http://<服务器IP>:8134/admin/install/(生产环境建议先完成 4.5 的 HTTPS 接入再走向导,让管理密码经加密通道提交)。向导共三步,实测页面流程如下:
- 管理员账号:设置 Web 管理后台密码。实测示例用
admin/q1w2e3r4。该登录名固定为admin,是后台专用账号,与 DAV 同步用户无关。 - 数据库配置(页面标题「Baïkal Database setup」):Database Backend 三选一
sqlite / mysql / pgsql,默认 SQLite 只需确认文件路径(默认/var/www/baikal/Specific/db/db.sqlite),点「Save changes」。MySQL/PostgreSQL 的接法见《Baikal 0.10.1 配置参数详解》数据库章节。 - 完成(实测回显):「Baïkal is now installed, and its database properly configured. For security reasons, this installation wizard is now disabled. Start using Baïkal」——向导随即自禁。实测容器内
Specific/目录出现INSTALL_DISABLED标记文件,此后再访问安装器只显示「Installation was already completed. Please head to the admin interface to modify any settings.」。
⚠️ 注意:
INSTALL_DISABLED与数据库同在Specific/卷中。若恢复备份时误删该标记,安装向导会重新暴露,任何能访问后台路径的人都能重设管理员密码——恢复备份务必带上这个文件。
4.4 验证 DAV 服务
curl -s -i -X PROPFIND -H 'Depth: 0' http://127.0.0.1:8134/dav.php/ | head -1
curl -s -i http://127.0.0.1:8134/.well-known/caldav | grep -iE '^HTTP|^location'
实测回显:
HTTP/1.1 401 Unauthorized
HTTP/1.1 302 Moved Temporarily
Location: http://127.0.0.1/dav.php
401 说明认证层已工作,.well-known 302 说明服务发现重写生效。建一个用户后带凭据重试:
curl -s -u root:q1w2e3r4 -o /dev/null -w '%{http_code}\n' \
-X PROPFIND -H 'Depth: 1' http://127.0.0.1:8134/dav.php/calendars/root/
实测回显:
207
4.5 HTTPS 反向代理要点
生产环境必须经 HTTPS 反向代理对外服务,实测与官方模板归纳出三个要点:
.well-known重定向必须落到/dav.php/。官方 ssl 模板(docker-compose.ssl.yaml)用 Traefik 时专门加了一条重定向中间件,并注明是 iOS 客户端必需(仓库 issue #37):
labels:
traefik.enable: true
traefik.http.routers.baikal.rule: Host(`dav.example.com`)
traefik.http.routers.baikal.tls: true
traefik.http.routers.baikal.middlewares: baikal-dav
traefik.http.middlewares.baikal-dav.redirectregex.regex: https://(.*)/.well-known/(card|cal)dav
traefik.http.middlewares.baikal-dav.redirectregex.replacement: https://$$1/dav.php/
traefik.http.middlewares.baikal-dav.redirectregex.permanent: true
- 反代透传 Host 与转发协议头。Baikal 生成重定向地址与绝对 URL 依赖 Host 头;nginx 反代最少配置:
server {
listen 443 ssl;
server_name dav.example.com;
location / {
proxy_pass http://127.0.0.1:8134;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
- 不想上反代时可用 Apache 变体自带 HTTPS:
ckulka/baikal:<版本>-apache监听 443 并内置自签名证书,挂载证书目录即可替换为自有证书(官方 ssl-certificates-guide 给出的通道,文件名固定baikal.public.pem/baikal.private.pem):
docker run --rm -it -p 80:80 -p 443:443 \
-v /etc/ssl/private/baikal:/etc/ssl/private/:ro ckulka/baikal:apache
💡 说明:仓库官方示例 docker-compose.ssl.yaml 即「Traefik 2.10 + Let's Encrypt(acme.json 挂载,需先
touch并chmod 600)+ baikal 服务」的完整模板,TLS 质量与证书续期都由 Traefik 托管,是官方推荐姿势。
五、数据持久化说明
- 卷布局:
config卷 =/var/www/baikal/config(baikal.yaml),data卷 =/var/www/baikal/Specific(SQLite 库、INSTALL_DISABLED 标记、用户上传附件目录)。备份两卷即备份全部状态,备份与恢复实操见《Baikal 0.10.1 管理与运维实战》。 - 改用宿主目录:官方提供 localvolumes 模板(docker-compose.localvolumes.yaml),把两个卷换成宿主 bind 目录,便于直接 rsync;镜像启动脚本会自动修正目录属主,可用环境变量
BAIKAL_SKIP_CHOWN=TRUE跳过该行为(宿主侧自管权限时使用)。 - MySQL 后端时的持久化:数据落外部 MySQL,
Specific/只剩配置与标记;建议在 compose 中一并声明 MySQL 服务并持久化其数据卷(官方 mariadb 模板:mariadb:10+MYSQL_DATABASE: baikal)。
六、环境变量表
| 变量 | 默认 | 作用 | 实测来源 |
|---|---|---|---|
BAIKAL_SERVERNAME | 空 | Apache 变体设置 ServerName,消除启动警告(如 dav.example.io) | 官方 README |
BAIKAL_SERVERALIAS | 空 | Apache 变体设置 ServerAlias(如 dav.example.org dav.example.com) | 官方 README |
BAIKAL_SKIP_CHOWN | 空(执行) | 设为任意非空值(如 FALSE)则启动时跳过数据目录属主修正 | 官方 README |
nginx 变体不依赖上述两个 Apache 专用变量;除这三个外镜像无需强制环境变量,Baikal 自身配置全部走 baikal.yaml 与管理后台。
七、配置参数说明
容器内配置文件位于 config 卷中:/var/www/baikal/config/baikal.yaml(实测该文件由向导生成,含 system 与 database 两大配置组)。查看:
docker compose exec baikal cat /var/www/baikal/config/baikal.yaml
实测回显(节选):
system:
configured_version: 0.10.1
timezone: Asia/Shanghai
card_enabled: true
cal_enabled: true
dav_auth_type: Basic
admin_passwordhash: 6d0d6c6b6555fbae363f90d862e8b11f8551196add2f99b1657e3759164bf2a5
database:
backend: sqlite
sqlite_file: /var/www/baikal/Specific/db/db.sqlite
全部参数逐项详解见《Baikal 0.10.1 配置参数详解》。
八、配置文件挂载
偏好直接管理配置文件时,可把 baikal.yaml 以 bind 方式挂入(替换 config 卷的该文件粒度):
volumes:
- ./baikal.yaml:/var/www/baikal/config/baikal.yaml
- data:/var/www/baikal/Specific
实测确认:配置文件每次请求时重新读取,修改后无需重启容器即可生效(包括数据库后端切换);但管理后台保存设置会整体重写该文件,bind 挂载时注意文件属主需可写(镜像内运行用户为 nginx)。
九、等价 docker run
与上节 compose 等价的最小启动命令:
docker run -d --name baikal \
-p 8134:80 \
-v baikal-config:/var/www/baikal/config \
-v baikal-data:/var/www/baikal/Specific \
--restart unless-stopped \
ckulka/baikal:0.10.1-nginx-php8.2
⚠️ 注意:生产建议仍用 Compose 管理生命周期(restart 策略、卷、后续接 MySQL 服务都由文件声明,可复核可迁移),docker run 仅用于临时验证。
十、常用运维命令
以下命令均在 /opt/baikal/ 目录内实测(项目名 baikal-0101-stack):
docker compose ps # 实例状态与健康检查
docker compose logs -f baikal # 实时日志(nginx 访问/错误、PHP-FPM)
docker compose restart baikal # 重启服务(配置改动后一般无需重启)
docker compose stop && docker compose up -d # 完整停起
docker compose exec baikal sh # 进入实例排障(nginx/php-fpm/sqlite3 都在)
docker compose down # 停止并移除(卷保留,数据不丢)
docker compose down -v # ⚠️ 连卷一起删除,数据全丢,慎用
升级版本时改 compose 中的镜像 tag 后:
docker compose pull && docker compose up -d
数据卷跨版本保留(config/data 不随镜像变化),升级前后行为核对与回滚见《Baikal 0.10.1 管理与运维实战》升级章节。
十一、常见问题
Q1:docker compose up 端口冲突。
回显 Error starting userland proxy: listen tcp4 0.0.0.0:8134: bind: address already in use。用 ss -ltnp | grep 8134 找到占用进程,或改 compose 端口映射左侧为空闲端口。
Q2:初始化向导打不开/被跳过。
Specific/INSTALL_DISABLED 存在时向导永久禁用(页面显示 Installation was already completed)。全新初始化需先删除该标记文件再重启容器;反之,想关闭向导又没走完向导流程时,手动 touch 一个同名文件即可。
Q3:iOS/DAVx⁵ 添加账号一直失败。
客户端先探测 /.well-known/caldav(carddav),HTTP 反代场景下确认该路径 302 到 /dav.php/(实测行为见 4.4 节);HTTPS 场景按 4.5 节第 1 点加 Traefik 重定向中间件,或 nginx 侧加等价 rewrite:rewrite ^/.well-known/(caldav|carddav) /dav.php permanent;(镜像内置 nginx 已含该规则,外层反代无需重复,只需别吞掉该路径)。
Q4:日志里出现 PHP warning(Apache 变体)。
Apache 形态开箱会产生 ServerName 相关告警,设 BAIKAL_SERVERNAME=dav.example.com 消除;或直接换 nginx 变体(官方 README 明确其开箱无警告且体积减半)。
Q5:向导完成但 admin 登不进后台。
管理员密码哈希存在 baikal.yaml 的 admin_passwordhash,算法为 sha256('admin:' + auth_realm + ':' + password);可用该算法核对是否改过 yaml 或 realm。重置方法见《Baikal 0.10.1 配置参数详解》常见问题节。
十二、参考链接
- ckulka/baikal-docker 仓库(镜像文档与 compose 模板):https://github.com/ckulka/baikal-docker
- 官方 ssl / mariadb / localvolumes / email compose 模板:https://github.com/ckulka/baikal-docker/tree/master/examples
- SSL 证书指南:https://github.com/ckulka/baikal-docker/blob/master/docs/ssl-certificates-guide.md
- Baikal 官方安装文档:https://sabre.io/baikal/install/
- Baikal 官方 Docker 安装指引(unofficial 通道):https://sabre.io/baikal/dockern/
- Traefik 文档(反代与 Let's Encrypt):https://doc.traefik.io/traefik/
站内相关阅读:
- 《Baikal 0.10.1 介绍与选型指南》:架构、协议行为与同类对比
- 《Baikal 0.10.1 配置参数详解》:baikal.yaml 逐参数详解
- 《Baikal 0.10.1 管理与运维实战》:用户管理、备份恢复、升级迁移
- 《Ubuntu 24.04 安装 Docker 指南》:宿主环境准备
- 《Ubuntu 22.04 安装 Radicale 3.9 指南(pip + venv + systemd)》:同领域非容器部署路线参照