必须挂载/var/lib/mysql,否则容器重启或删除后数据必然丢失;推荐使用Docker命名卷(如mysql-data),因其自动处理权限与路径,生产环境最稳妥。

不挂载数据卷,MySQL容器一重启或删除,数据必然丢失。这不是MySQL的问题,而是Docker容器可写层的默认行为——它随容器生命周期销毁而清空。
为什么 /var/lib/mysql 必须挂载?
MySQL把所有数据库文件、日志、表结构都存在 /var/lib/mysql 目录下。Docker默认不会持久化这个路径,哪怕你只是 docker restart,只要容器重建(比如 docker rm && docker run),这个目录就变空了。
- 容器内写入的数据实际落在可写层,该层不跨容器实例保留
-
docker commit不会把可写层数据打包进镜像,所以打镜像也救不了数据 - 哪怕只改了配置重启,如果没挂载,
mysqld启动时发现/var/lib/mysql是空的,会初始化全新实例
用命名卷(docker volume)挂载最稳妥
命名卷由Docker管理,路径抽象、权限自动处理、跨容器复用方便,是生产环境首选。
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
- 先创建卷:
docker volume create mysql-data - 启动时挂载:
docker run -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=xxx mysql:8.0 - 验证是否生效:进容器执行
ls /var/lib/mysql,应看到ibdata1、mysql等原生文件,而非空目录 - 删掉容器再重跑同名命令,
mysql-data卷里的数据毫发无损
绑定挂载(bind mount)能用但要小心
把宿主机某个路径(如 /opt/mysql/data)直接挂进去,适合开发调试或需要手动干预文件的场景,但有坑:
- 宿主机路径必须提前
mkdir -p创建,且权限得对:MySQL容器以用户mysql(UID 999)运行,宿主机目录需chown 999:999 - 路径若含中文、空格或特殊符号,Docker可能解析失败,报错
invalid argument - Windows/macOS上用 Docker Desktop 时,绑定路径需在 Docker 设置里声明为共享目录,否则挂载失败
- 别挂载整个
/var/lib/mysql的父目录(比如/var/lib),否则可能覆盖容器内其他必要文件
docker-compose.yml 里怎么写才不出错?
YAML 对缩进和冒号后空格极其敏感,volumes 下的路径映射最容易写错。
- 命名卷写法(推荐):
volumes: ["mysql-data:/var/lib/mysql"],注意引号和冒号后必须有空格 - 绑定挂载写法:
volumes: ["./mysql-data:/var/lib/mysql:rw"],本地路径用相对路径时,.指的是docker-compose.yml所在目录 - 千万别漏掉
environment里的MYSQL_ROOT_PASSWORD,否则容器启动失败并反复重启 - 第一次启动前,确保
mysql-data卷为空或确实是旧数据;若已有数据但权限不对,容器会卡在Initializing database
真正容易被忽略的不是“要不要挂”,而是挂载后目录权限是否匹配、卷是否真被容器读写到——最简单的验证方式:建库、删容器、重跑、连上去查 SHOW DATABASES; 还在不在。

















