贝利信息

mysql Docker容器持久化数据目录配置方式

日期:2026-01-11 00:00 / 作者:P粉602998670
MySQL容器挂载/var/lib/mysql必须用宿主机绝对路径,相对路径会导致匿名卷覆盖数据;需提前创建目录并chown 999:999、chmod 700;Docker Compose应使用bind mount而非命名卷;自定义datadir时须同步修改配置、挂载点和权限。

MySQL 容器启动时挂载 /var/lib/mysql 目录必须用绝对路径

宿主机目录没写成绝对路径(比如写成 ./mysql-data)会导致 Docker 自动创建匿名卷,容器重启后数据看似“还在”,实则新卷覆盖旧数据,实际已丢失。Docker 不会把相对路径自动解析为当前 shell 路径,而是按 daemon 工作目录处理,极不可控。

正确做法是显式声明完整路径:

docker run -d \
  --name mysql-dev \
  -v /home/user/mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -p 3306:3306 \
  mysql:8.0

挂载前必须修正宿主机目录的属主和权限

MySQL 容器默认以 UID 999(mysql 用户)运行 mysqld,若宿主机目录属主不是 999 或权限不足(如无写权限),容器会卡在初始化阶段并报错:mysqld: Can't create/write to file '/var/lib/mysql/is_writable' 或直接退出。

修复方式(在挂载前执行):

mkdir -p /home/user/mysql-data
chown -R 999:999 /home/user/mysql-data
chmod -R 700 /home/user/mysql-data

Docker Compose 中配置数据卷要避开命名卷自动初始化陷阱

volumes: 声明命名卷(如 mysql-data:)时,Docker 会自动创建空卷,即使你同时写了 driver_opts 指向本地路径,也可能因初始化顺序问题导致数据目录被清空。

最稳方案是显式使用绑定挂载(bind mount)并禁用命名卷:

version: '3.8'
services:
  mysql:
    image: mysql:8.0
    volumes:
      - /home/user/mysql-data:/var/lib/mysql:rw
    environment:
      MYSQL_ROOT_PASSWORD: "123456"
    ports:
      - "3306:3306"

容器内修改 datadir 配置后挂载点必须同步调整

如果自定义了 MySQL 的 datadir(比如改到 /data/mysql),就不能再挂载 /var/lib/mysql——否则配置与挂载冲突,mysqld 启动失败并报错:Can't find messagefile '/usr/share/mysql/errmsg.sys' 或更隐蔽的权限拒绝。

此时必须同步调整三处:

datadir 是少数需要同时动配置、挂载、权限三处的地方,漏任一环都会让容器反复崩溃。