Baikal 0.10.1 Docker Compose 部署指南

实测用 Docker Compose 部署 Baikal 0.10.1(ckulka/baikal 镜像 nginx-php8.2 形态):镜像选型、初始化向导、数据持久化、HTTPS 反代要点与常用运维命令全流程。

BaikalBaikalDocker Compose自托管CalDAV2026/10/30

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:<版本>、<版本>-apacheApache httpd最贴近官方部署指南的默认形态;自带 HTTPS 443 与自签名证书,可用 BAIKAL_SERVERNAME / BAIKAL_SERVERALIAS 消除启动警告
ckulka/baikal:<版本>-apache-php8.2Apache httpd + PHP 8.2同上,锁定 PHP 8.2
ckulka/baikal:<版本>-nginxnginx体积显著更小(官方 README:不到 Apache 形态的一半),开箱无警告日志
ckulka/baikal:<版本>-nginx-php8.2nginx + 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 三种后端与邀约邮件功能无需额外安装。

三、前置条件

  1. 宿主已安装 Docker Engine 与 Compose v2 插件:docker compose version 能正常输出版本号。
  2. 端口规划:本指南用 8134 做宿主端口,占用确认 ss -ltn | grep :8134 无输出;换端口时同步改 compose 文件映射即可。
  3. 目录规划:本文所有文件放在 /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 接入再走向导,让管理密码经加密通道提交)。向导共三步,实测页面流程如下:

  1. 管理员账号:设置 Web 管理后台密码。实测示例用 admin / q1w2e3r4。该登录名固定为 admin,是后台专用账号,与 DAV 同步用户无关。
  2. 数据库配置(页面标题「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 配置参数详解》数据库章节。
  3. 完成(实测回显):「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 反向代理对外服务,实测与官方模板归纳出三个要点:

  1. .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
  1. 反代透传 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;
    }
}
  1. 不想上反代时可用 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 配置参数详解》常见问题节。

十二、参考链接

站内相关阅读: