惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyberwarzone
Cyberwarzone
C
CXSECURITY Database RSS Feed - CXSecurity.com
C
CERT Recently Published Vulnerability Notes
The Hacker News
The Hacker News
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
D
Docker
H
Hacker News: Front Page
Recent Announcements
Recent Announcements
GbyAI
GbyAI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Proofpoint News Feed
Security Latest
Security Latest
AI
AI
I
InfoQ
Google DeepMind News
Google DeepMind News
阮一峰的网络日志
阮一峰的网络日志
S
Secure Thoughts
Attack and Defense Labs
Attack and Defense Labs
P
Proofpoint News Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Scott Helme
Scott Helme
N
News | PayPal Newsroom
Y
Y Combinator Blog
V
Visual Studio Blog
Latest news
Latest news
大猫的无限游戏
大猫的无限游戏
Microsoft Security Blog
Microsoft Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
WordPress大学
WordPress大学
V
Vulnerabilities – Threatpost
C
Cyber Attacks, Cyber Crime and Cyber Security
TaoSecurity Blog
TaoSecurity Blog
S
Security @ Cisco Blogs
D
DataBreaches.Net
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
N
Netflix TechBlog - Medium
T
Troy Hunt's Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
H
Heimdal Security Blog
美团技术团队
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Security Affairs
T
Threat Research - Cisco Blogs
Webroot Blog
Webroot Blog
G
Google Developers Blog
aimingoo的专栏
aimingoo的专栏

云野开源志

OpenClaw npm 升级踩坑记:从版本冲突到模块丢失 Posts 免责声明 Site-Disclaimers openclaw(moltbot、Clawdbot)常见异常 大模型配置-千问免费版 初始化OpenClaw 安装openclaw记录 大年初一桃花谷 CheckSSL.sh - SSL证书到期时间监控脚本 g.sh - Go语言环境管理工具安装脚本 install-cri-docker.sh - cri-dockerd安装脚本 install-docker.sh - Docker Engine快速安装脚本 install-docker2.sh - Docker 交互式安装脚本 install-nginx.sh - Nginx官方源快速安装脚本 install-zerotier.sh - ZeroTier 虚拟网络快速安装脚本 mng.sh - Nginx配置文件合并脚本 OpenSSL.sh - 自签名 SSL 证书生成脚本 SystemInfoMonitor.sh - 系统资源监控告警脚本 UpdateImages.sh - Docker 镜像批量更新脚本 解忧杂货铺 - 云野开源志 为Hugo Next主题添加Umami统计支持 解忧杂货铺 - 栏目声明 Certd - 解决多平台SSL证书管理难题的神器 轻量级网络端口监控工具 GeoLite2 自动搬运仓库使用手册 MaxMind 免费账号注册 CloudFlare Accel Docker 搭建私有 DNS 服务器 hugo-theme-stack集成Umami openresty编译添加geoip2模块支持 GPU加速云原生应用,开启高性能计算新纪元 5. K8S Service与Ingress 4. K8S 控制器 Rancher搭建 3. K8S Pod 资源管理 2. K8S 基础资源管理 1. K8S 简介和认证介绍 Rancher集成AzureAD认证 Harbor 部署搭建 站点留言板 关于 友情链接
排查 Docker Compose PWD 变量导致 Waline 数据库挂载异常
云野开源志 · 2026-07-03 · via 云野开源志

记录一次因 Docker Compose 的 ${PWD} 变量在不同运行目录下解析值不同,导致 Waline 评论系统 Volume 挂载路径错误、数据库丢失的排查过程。

问题描述

最近发现博客评论系统(Waline v3)的后台管理页面可以正常打开,但登录时一直提示“用户名或密码错误”。试了试密码重置功能,页面显示“请稍后再试”,也搞不定。前台评论区域也不显示已有评论,整个系统看起来像是丢了所有数据一样。

这种情况在自部署项目中不算少见,我去 GitHub 和技术社区搜了一圈,发现类似问题还真不少——大都是因为 SQLite 数据库文件被意外清空或者指向了空文件,应用启动时自动创建了空表结构,导致原有用户数据全部“消失”,所以才会出现登录失败、重置失败这些看起来莫名其妙的问题。

问题原因

排查下来发现,根本原因是 Docker Compose 中 ${PWD} 变量在不同运行目录下解析出的值不同,导致 Volume 挂载路径异常。

我的 docker-compose 配置是这样的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
services:
  waline:
    container_name: waline
    image: lizheming/waline
    restart: always
    ports:
      - 8360:8360
    volumes:
      - ${PWD}/data:/app/data
    environment:
      # ...

注意这个 ${PWD}/data${PWD} 是一个预定义的环境变量,它的值取决于你执行 docker compose 命令时所在的目录,而不是 compose 文件所在的目录。

  • 在正确目录下执行(/docker/data/waline/)→ ${PWD} 解析为 /docker/data/waline → 挂载 /docker/data/waline/data:/app/data → 数据库正常
  • 在其他目录下执行(比如 /data)→ ${PWD} 解析为 /data → 挂载 /data:/app/data → 但 /data 目录下只有一个 0 字节的空 waline.sqlite,容器读到的就是个空数据库

这就能解释为什么数据“丢了”——不是文件没了,而是挂载到了错误的位置。

根据 Docker 官方文档,Compose 在解析变量时遵循以下规则:

当没有显式设置 --env-file 时,Compose 会按以下顺序确定项目目录:

  1. --project-directory 如果设置了的话
  2. 否则,第一个通过 -f/--file 指定的 Compose 文件所在的目录
  3. 否则,当前 shell 的工作目录(PWD

来源: Docker Docs - Variable Interpolation

同时,环境变量优先级如下(从高到低):

  1. docker compose run -e 命令行传入
  2. environmentenv_file 属性中从 shell 或 .env 文件插值的变量
  3. Compose 文件中 environment 属性直接设置的值
  4. Compose 文件中 env_file 属性引用的值
  5. Dockerfile 中 ENV 指令设置的值

来源: Docker Docs - Environment Variables Precedence

也就是说,${PWD} 的值完全取决于你在哪个目录敲下 docker compose up。如果 compose 文件里用了 ${PWD},但每次执行的目录不固定,挂载路径就会飘忽不定,这就埋下了隐患。

排查过程

先确认后台地址

我去 Waline 官方文档(waline.js.org)查了一下,确认了:

  • 管理后台路径是 <serverURL>/ui/register
  • 第一个注册的用户自动成为管理员
  • 支持邮箱密码登录,也支持 GitHub、微博、Twitter、Facebook、QQ 等第三方 OAuth

SSH 上服务器看看

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
ssh root@<内网IP>

# 查看 Waline 容器状态
docker ps | grep waline

# 查看容器日志
docker logs waline --tail 20

# 搜索错误日志
docker logs waline | grep -E 'error|Error|ERROR' | tail -10

日志里发现了关键线索:

1
2
NotFoundError: url `/__api__/admin` not found.
NotFoundError: url `/__api__/config` not found.

这些 404 错误说明数据库中的管理相关表不存在或为空,API 路由找不到对应的数据。

对比数据库文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 检查文件体积
ls -la /data/waline.sqlite                        # 0 字节 ❌
ls -la /docker/data/waline/data/waline.sqlite     # 49KB ✅

# 用 sqlite3 查看表结构
sqlite3 /docker/data/waline/data/waline.sqlite ".tables"
# 输出:wl_Comment  wl_Counter  waline-Migrations  wl_Users

# 查看用户数据
sqlite3 /docker/data/waline/data/waline.sqlite \
  -header -csv "SELECT mail,nick,type FROM wl_Users;"

正确的数据库里有 4 个用户(1 个管理员 + 3 个访客),而 /data/waline.sqlite 虽然存在但是空的。

验证 API 连通性

1
2
3
4
5
6
# 测试管理后台页面
curl -s http://localhost:8360/ui/register

# 测试 API 端点
curl -s http://localhost:8360/api/me
# 返回:{"errno":404,"errmsg":"url `/api/me` not found."}

404 进一步确认了数据库虽然加载了,但没有用户数据。

分析 docker-compose 配置

1
cat /docker/data/waline/docker-compose.yml

看到 volumes 里用的是 ${PWD}/data:/app/data${PWD} 在执行 docker compose up 时会被替换为当前 shell 的工作目录。如果之前在某次操作时不在 compose 文件所在目录执行命令,${PWD} 就解析到了其他路径,Volume 也就挂载到了错误的地方。

解决过程

找到原因就好办了。先在正确目录下执行一次,确保 ${PWD} 解析到正确路径:

1
2
3
cd /docker/data/waline
docker-compose down
docker-compose up -d

验证一下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 确认容器在跑
docker ps | grep waline

# 确认数据库用户都在
sqlite3 /docker/data/waline/data/waline.sqlite -header -csv "SELECT mail,nick,type FROM wl_Users;"
# 输出:
# mail,nick,type
# <管理员邮箱>,elisky,administrator
# <QQ用户>,维尼🍯,guest
# <163用户>,测试注册,guest
# <QQ用户>,学的慢,guest

数据全在,问题解决。后台地址还是 https://<博客域名>/ui/,用管理员邮箱密码登录就行。

经验总结

  1. Compose 文件中慎用 ${PWD}${PWD} 依赖执行命令时的当前目录,不够稳定。更推荐用相对路径(Compose 会自动以 compose 文件所在目录为基准),或者用 .env 文件固定变量值。
  2. Docker volume 挂载要特别注意:挂载点下的文件如果被意外覆盖或清空,数据说没就没了。以后得给 SQLite 数据库做个定时备份,不能裸奔。
  3. 排查问题先看日志docker logs 是最直接的线索来源,比瞎猜效率高多了。
  4. sqlite3 挺好用的:对于 SQLite 数据库,直接查询表结构和数据,一目了然。
  5. 现象分析很重要:登录失败 + 重置失败 + 评论消失,这些现象凑在一起,基本就是数据库层面的问题了,而不是密码记错了或者认证服务故障。