OliveTin 3000.21.0 Docker Compose 部署实战
OliveTin v3000.21.0 实机部署实战:Compose 编排与最小配置、控制通道挂载权限修复、强制登录与 ACL、裸机 systemd 对照、6 类真实踩坑排障与升级回滚。
OliveTin 3000.21.0 Docker Compose 部署实战
目标:在一台真实 Linux 服务器上,用 Docker Compose 把 OliveTin v3000.21.0 跑起来并完成生产化加固:从编排文件编写、启动验证,到挂载宿主机 Docker 控制通道、强制登录、裸机 systemd 形态对照,再到踩坑实录与升级路径。所有命令与回显均为 2026-10-28 在 x86_64 Linux 实机上的实测记录;组件定位与选型背景见 《OliveTin 3000.21.0 介绍与选型指南》,配置项逐节语义见 《OliveTin 3000.21.0 配置参数详解》,命令与 API 运维见 《OliveTin 3000.21.0 常用命令与运维实战(核心篇)》。
一、环境信息
| 项 | 值 |
|---|---|
| 服务器系统 | Linux x86_64(内核 6.x,时区 Asia/Shanghai) |
| 容器运行时 | Docker Engine(Compose v2 插件,docker compose 子命令) |
| OliveTin 版本 | 3000.21.0(2026-10-24 发布,官方镜像 ghcr.io/olivetin/olivetin:3000.21.0) |
| 宿主端口 | 8130(部署前 ss -ltn 实测未被占用),映射到编排内固定端口 1337 |
| 编排项目名 | olivetin-3000.21.0-stack(compose 顶层 name: 显式指定) |
| 服务目录 | /opt/olivetin/(编排文件 + 配置目录均在此,bind mount) |
| 访问方式 | http://<服务器IP>:8130 |
| 实测日期 | 2026-10-28 |
二、部署方式选择
官方文档给出的部署形态有五类:裸机包(.deb/.rpm/Alpine/Arch/Windows)、tar.gz 手工安装、Docker Compose、Kubernetes(Helm Chart 与 Manifest 双路径)、BSD/Windows 服务。本文选 Docker Compose 作为主路径,理由:
- 官方一等公民:官方文档首页安装步骤即 Compose,官方镜像
ghcr.io/olivetin/olivetin(同版本也发布docker.io/jamesread/olivetin,双源等价); - 配置与进程分离:OliveTin 的全部状态就是一个
config.yaml,bind mount 出来后,升级、回滚、备份都只围绕「一个 YAML + 一个镜像 tag」; - 便于挂载宿主机控制通道:OliveTin 最常见的进阶用法是「管理宿主机上的其他服务」,这需要把宿主机的 Docker 控制通道挂进编排,Compose 文件一行事。
端口面只需记住一个数字:1337。OliveTin 把 Web 界面、REST 网关、gRPC 全部收敛在 Single HTTP Frontend 这一个端口上(端口拆分属高级部署,见官方 Network ports 文档),因此编排里只映射 1337 即可。
三、快速部署
3.1 编排文件与最小配置
创建服务目录与两份文件。目录结构:
/opt/olivetin/
├── docker-compose.yml
└── config/
└── config.yaml
编排文件 /opt/olivetin/docker-compose.yml:
name: olivetin-3000.21.0-stack
services:
olivetin:
container_name: olivetin-3000.21.0-web
image: ghcr.io/olivetin/olivetin:3000.21.0
ports:
- "8130:1337"
volumes:
- ./config:/config
restart: unless-stopped
四个关键点:
image用ghcr.io/olivetin/olivetin:3000.21.0,tag 固定到具体版本而不是latest——升级是显式换 tag 的动作,而不是不可预期的自动漂移;./config:/config是 bind mount:宿主机上直接编辑配置文件,编排内进程热重载(官方容器约定配置目录为/config,文件名必须是config.yaml,写成config.yml不识别);- 端口映射
"8130:1337":宿主侧 8130 是为了避开宿主机上已被占用的端口,编排内侧固定 1337; restart: unless-stopped:进程崩溃自动拉起(第五节会看到它「帮倒忙」的一面)。
最小配置 /opt/olivetin/config/config.yaml(官方文档首页原样示例):
actions:
- title: Hello World
icon: "\U0001F44B"
shell: echo 'Hello World from OliveTin!'
3.2 启动与验证
$ cd /opt/olivetin && docker compose up -d
[+] Running 12/12
✔ olivetin 11 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled
✔ ebe40f7563ba Pulled
✔ 9d4ad21ba58b Pulled
...
✔ Network olivetin-3000.21.0-stack_default Created
✔ Container olivetin-3000.21.0-web Started
启动序列日志(docker logs olivetin-3000.21.0-web,实测逐行摘录关键部分):
time="2026-10-28T12:34:56+08:00" level=info msg="Starting OliveTin"
time="2026-10-28T12:34:56+08:00" level=info msg="Starting webserver" version="3000.21.0" ...
level=info msg="Adding action" title="Hello World"
level=info msg="Web UI" address=":1337"
三层验证(实测):
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
olivetin-3000.21.0-web ghcr.io/olivetin/olivetin:3000.21.0 "/usr/bin/OliveTin" olivetin 10 seconds ago Up 9 seconds 0.0.0.0:8130->1337/tcp
$ curl -s http://127.0.0.1:8130/ | grep -oE '<title>[^<]*</title>'
<title>OliveTin</title>
$ curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8130/assets/index-MKHN2igo.js
200
状态 Up、标题正常、静态资源 200——Web 界面已在 http://<服务器IP>:8130 可访问,点 Hello World 按钮即执行。
⚠️ 第一个真实坑(本机实测踩中):此时看完整启动日志会多一行——
level=warning msg="Could not create themes directory: mkdir /config/custom-webui: permission denied"容器内进程默认以非 root 用户(uid=1000,用户名 olivetin)运行,而 bind mount 进来的
./config目录在宿主机上属 root。进程写不进配置目录(主题目录、自定义 CSS、执行日志落盘都会受影响)。这个告警不影响 Hello World 跑通,但会在四.2 的强制登录配置环节变成硬故障,生产部署请直接按四.2 处理权限。
四、生产化配置
4.1 挂载宿主机控制通道(管理宿主机服务的场景)
OliveTin 在编排内只能操作编排自己的命名空间;要「点按钮管理宿主机上的其他服务」,官方文档(Container Control Panel 方案)的做法是把宿主机控制通道挂进编排,配置文件里写管理命令:
services:
olivetin:
container_name: olivetin-3000.21.0-web
image: ghcr.io/olivetin/olivetin:3000.21.0
user: root
ports:
- "8130:1337"
volumes:
- ./config:/config
- /var/run/docker.sock:/var/run/docker.sock
restart: unless-stopped
新增两行的事实依据(均为本机实测):
user: root:宿主机控制通道是 root 权限 660 的套接字,容器内默认 uid=1000 无权访问。官方文档对这一场景的推荐写法就是user: root(官方 issues 中作者也确认这是文档化做法);- 挂载控制通道:让编排内的
docker命令实际作用于宿主机。
实测权限差异(同一条 docker ps 动作,修复前后的执行日志回显):
修复前(默认 uid=1000):
exitCode: 1
output: |
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock
修复后(user: root):
exitCode: 0
output: |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9c2f1a... ghcr.io/olivetin/olivetin:3000.21.0 "/usr/bin/OliveTin" 8 minutes ago Up 8 minutes 0.0.0.0:8130->1337/tcp olivetin-3000.21.0-web
⚠️ 权衡提示:
user: root等于给这个面板的执行者间接开放宿主机 root 能力——docker ps只读无害,但config.yaml里任何 action 都能执行任意命令。如果开这个口子,强制登录(四.3)不再是可选项而是底线;若不想 root,替代路径是把宿主机套接字所属组 gid 加入编排(group_add),权限粒度更细但步骤多,按需取舍。
4.2 解决配置目录权限(bind mount 属主)
上一节 user: root 顺带解决了 /config 写权限(root 写 root 属主目录天经地义)。如果不采用 user: root(比如不挂控制通道的纯按钮面板),两种正规解法任选:
- 解法 A(推荐,改属主):宿主机上把配置目录属主改为 uid 1000——
chown -R 1000:1000 /opt/olivetin/config。容器内 olivetin 用户可写,权限告警消失; - 解法 B(官方样例风格,命名卷):官方 Compose 样例用命名卷
OliveTin-config:/config代替 bind mount,命名卷首挂时自动以镜像内目录属主初始化,天然可写。代价是配置编辑要docker compose exec进编排或先复制出来,不如 bind mount 直观。
本机实测采用解法 A(在未加 user: root 的初始状态下):
$ chown -R 1000:1000 /opt/olivetin/config
$ docker logs olivetin-3000.21.0-web 2>&1 | grep -c "permission denied"
0
4.3 强制登录(公网/多人使用的底线)
匿名面板只适合单人在可信内网使用。官方认证链:本地用户(authLocalUsers,Argon2id 哈希)→ OAuth2(Authelia/Authentik/Pocket ID)→ JWT → 反代头。最小可用的是本地用户三件套:
authRequireGuestsToLogin: true
authLocalUsers:
enabled: true
users:
- username: admin
usergroup: admins
password: $argon2id$v=19$m=65536,t=4,p=6$vkLLzzuwc/tozfVhYKJUWg$1zzMPLQfJ4eZ14M2kS/gsZrIuPQBgFHjP4NB/pSsMkI
accessControlLists:
- name: admin-full
matchUsergroups:
- admins
permissions:
view: true
exec: true
logs: true
addToEveryAction: true
policy:
showDiagnostics: true
showLogList: true
三点说明(详细参数语义见配置篇):
password存 Argon2id 哈希而非明文,哈希值由官方 APIPOST /api/olivetin.api.v1.OliveTinApiService/PasswordHash生成(传明文返回哈希),也可以用系统argon2工具生成;authRequireGuestsToLogin: true会把默认权限全部收回,必须再显式配 ACL 把 view/exec/logs 授回去,否则登录后什么也做不了(本机实测踩中:未配 ACL 时登录成功但按钮不可点、日志为空);- ACL 的
matchUsergroups: [admins]与上面usergroup: admins对应。
配置保存后无需重启——OliveTin 监听文件变更并热重载,日志确认:
level=info msg="config file changed: WRITE \"/config/config.yaml\"" ... live-reload
浏览器访问 http://<服务器IP>:8130 会被重定向到登录页,以 admin 登录后恢复正常界面。本机实测还顺带验证了两个拒绝路径:匿名调用日志接口返回 403 {"code":"permission_denied","message":"guests are not allowed to access the dashboard"};匿名触发按钮 HTTP 层返回受理、执行层被拦截(执行日志标记 blocked)。
4.4 裸机 systemd 形态对照
不跑编排的裸机形态,官方 tar.gz 发行包内直接带了 systemd unit(var/systemd/OliveTin.service,原文全文):
[Unit]
Description=OliveTin
Wants=network-online.target
After=network-online.target
[Service]
User=olivetin
ExecStart=/usr/local/bin/OliveTin
Restart=always
[Install]
WantedBy=multi-user.target
手工安装四步(官方 tar.gz 安装文档与本机解包实查一致):
$ tar xzf OliveTin-linux-amd64.tar.gz
$ cp OliveTin-linux-amd64/OliveTin /usr/local/bin/ && chmod +x /usr/local/bin/OliveTin
$ mkdir -p /etc/OliveTin && cp OliveTin-linux-amd64/config.yaml /etc/OliveTin/ # 471 行官方注释版模板
$ useradd -r -s /usr/sbin/nologin olivetin && chown -R olivetin: /etc/OliveTin
$ cp OliveTin-linux-amd64/var/systemd/OliveTin.service /etc/systemd/system/
$ systemctl daemon-reload && systemctl enable --now OliveTin
裸机形态要点(与编排形态差异对照):
| 维度 | 编排形态 | 裸机 systemd 形态 |
|---|---|---|
| 配置目录 | /config(bind mount) | /etc/OliveTin/ |
| 进程身份 | 编排内默认 uid 1000(或 user: root) | User=olivetin 专用低权账户 |
| 托管 | restart: unless-stopped | Restart=always |
| 升级 | 换镜像 tag 重拉 | 替换单个二进制文件 + 重启服务 |
| 端口 | 映射宿主端口 | 直接监听 1337 |
两种形态的 config.yaml 完全一致,迁移只是搬文件。裸机形态的启动参数、CLI 工具与 API 实测见命令篇。
五、验证清单
逐项打勾,全部通过才算交付:
- 编排状态
docker compose ps显示Up,端口映射8130->1337存在; - 启动日志无
permission denied(或已按四.2 修复); -
curl http://127.0.0.1:8130/返回<title>OliveTin</title>; - Web 界面点击 Hello World 按钮有回显;
- (若挂载控制通道)控制通道类动作 exitCode 0;
- (若启用登录)匿名访问被重定向登录页、匿名 API 返回 403、登录后可执行;
- 改配置触发热重载日志行出现,无需重启编排;
-
restart策略生效:docker compose restart与杀进程两种方式都能自动恢复。
六、常见问题排障(本机实测实录)
Q1:启动日志报 mkdir /config/custom-webui: permission denied
bind mount 目录在宿主机属 root,编排内 uid 1000 写不进。按四.2:chown -R 1000:1000 或 user: root 或改用命名卷。这是官方镜像默认非 root 运行的必然结果,不是 bug。
Q2:配置改了不生效 / 启动报找不到动作
文件名必须是 config.yaml——config.yml 不被识别(YAML 扩展名全称与缩写在大小写敏感文件系统上是两个文件,官方配置文档明确只认 config.yaml)。确认路径:编排形态在 bind mount 的 /config/config.yaml,裸机形态在 --configdir 指向的目录。
Q3:宿主端口被占 / 想换端口
ports: ["8130:1337"] 左侧换任意空闲宿主端口即可(本机用 ss -ltn 预检)。编排内侧的 1337 不建议改——它是镜像内写死的监听地址(配置项 listenAddressSingleHTTPFrontend),除非同步修改。
Q4:配置写错后进程反复重启
restart: unless-stopped + 坏配置 = 崩溃循环。本机实测:把 config.yaml 改成缩进错误的 YAML 后,日志出现:
level=fatal msg="error loading config from /config/config.yaml: yaml: line 3: did not find expected '-' indicator"
进程退出、编排自动拉起、再次崩溃,循环往复。恢复方法:修复宿主机上的 ./config/config.yaml(坏配置在宿主侧,编排重建不影响它),保存即自动恢复——本机实测改回正确配置后约 6 秒内回到 Up 状态。预防方法:改配置前先在临时目录跑语法检查(命令篇 -syntaxcheck 实测)。
Q5:控制通道动作报 permission denied while trying to connect to the docker API
套接字权限未解决就挂了通道。按四.1 加 user: root(或 group_add 套接字组)。注意挂通道路径写 /var/run/docker.sock,不要写成符号链接的目标路径。
Q6:登录成功但按钮不可点、日志页为空
authRequireGuestsToLogin: true 收回了默认权限,而 ACL 没配或 matchUsergroups 与用户的 usergroup 值不一致。按四.3 的 ACL 三权限(view/exec/logs)检查,并确认 addToEveryAction: true(否则要给每个 action 单独挂 ACL)。
七、升级与回滚
升级(编排形态,三步):
$ cd /opt/olivetin
$ sed -i 's|olivetin:3000.20.0|olivetin:3000.21.0|g' docker-compose.yml # 换 tag
$ docker compose pull && docker compose up -d # 拉新镜像、重建编排
$ docker image ls ghcr.io/olivetin/olivetin # 旧镜像保留,便于回滚
配置与执行历史都在 bind mount 的 ./config 里,编排重建不动它们。跨大版本(如 "2k" 2024.x.x → "3k" 3000.x.x)官方另有迁移文档,tag 直跳前先读。
回滚:把 tag 改回旧版本再 up -d(旧版本层仍在本地存储未清理的情况下秒级完成),等价于按第七节流程对旧 tag 重建。
裸机形态升级:下载新版 tar.gz → 替换 /usr/local/bin/OliveTin 单文件 → systemctl restart OliveTin。配置目录 /etc/OliveTin 与版本无关,不动。
八、参考链接
- 官方安装文档(Compose / 裸机 / K8s 全形态):https://docs.olivetin.app/installation/docker.html
- 官方容器镜像(GHCR):https://github.com/OliveTin/OliveTin/pkgs/container/olivetin
- 官方 Compose 样例(named volume 风格):https://docs.olivetin.app/installation/docker.html#docker-compose
- 官方 Network ports 文档:https://docs.olivetin.app/configuration/ports.html
- 官方 systemd 安装文档:https://docs.olivetin.app/installation/targz.html
- 版本发布流(3000.21.0,2026-10-24):https://github.com/OliveTin/OliveTin/releases
- 本专栏相关篇目:《OliveTin 3000.21.0 介绍与选型指南》、《OliveTin 3000.21.0 配置参数详解》、《OliveTin 3000.21.0 常用命令与运维实战(核心篇)》