结论是宿主机挂载目录UID/GID未匹配容器内mysql用户(8.0+默认999:999),需用sudo chown -R 999:999和chmod -R 750统一属主与权限,并处理SELinux/AppArmor拦截。

直接说结论:这不是MySQL配置错了,也不是镜像坏了,而是宿主机目录权限没对上容器内 mysql 用户的 UID/GID。最稳妥的解法是提前把挂载目录属主设成容器期望的用户 ID,而不是开 --privileged 或 chmod 777。
确认容器内 mysql 用户的 UID 和 GID
MySQL 官方镜像(8.0 系列)默认用 UID=999、GID=999 的 mysql 用户运行 mysqld 进程。这个值在不同版本可能微调,但 8.0.30+ 基本固定为 999。别猜,用命令实锤:
docker run -ti --rm --entrypoint="/bin/bash" mysql:8.0.33 -c "id -u mysql && id -g mysql"
输出应为两行 999。如果挂载的 /var/lib/mysql 目录在宿主机上属主不是 UID 999,chown 初始化就会失败。
给宿主机挂载目录设置正确属主
这是最干净、最安全的做法。假设你挂载的是 /home/zhangsan/mysql/data:
- 先确保该目录存在:
mkdir -p /home/zhangsan/mysql/data - 再用 UID 999 占位:
sudo chown -R 999:999 /home/zhangsan/mysql/data - 权限建议设为
750(目录可读写执行,组可读执行,其他无权):sudo chmod -R 750 /home/zhangsan/mysql/data
注意:不要用 chown zhangsan:mysql 这类名字映射——宿主机未必有同名组,且容器不认宿主机用户名,只认数字 UID/GID。
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
日志目录(/var/log/mysql)也要同步处理
错误日志、慢查询日志路径如果也挂载了(比如 -v /home/zhangsan/mysql/logs:/var/log/mysql),同样要设属主:
mkdir -p /home/zhangsan/mysql/logssudo chown -R 999:999 /home/zhangsan/mysql/logssudo chmod -R 750 /home/zhangsan/mysql/logs
否则即使数据目录 OK,log-error=/var/log/mysql/error.log 也会卡在 open 失败,报错里会明确出现 Permission denied 和路径。
SELinux 或 AppArmor 拦截时的绕过要点
在 CentOS/RHEL 或 Ubuntu 上,即使属主和权限都对了,仍可能被安全模块拦截。关键信号是:docker logs 里没看到明显权限错误,但 journalctl -u docker 或 ausearch -m avc 显示 AVC denial。
- 临时验证:在 CentOS 上执行
sudo setenforce 0,再启动容器;若成功,就是 SELinux 导致 - 永久修复(推荐):
sudo semanage fcontext -a -t mysqld_log_t "/home/zhangsan/mysql/logs(/.*)?",然后sudo restorecon -Rv /home/zhangsan/mysql/logs - Ubuntu 上检查
/etc/apparmor.d/usr.sbin.mysqld是否包含对应挂载路径的w权限规则
这类问题容易被忽略,因为错误不显式出现在 MySQL 日志里,而是在系统层被静默拒绝。

















