提交的SQL Server镜像挂载数据目录后丢失已提交变更求助
SQL Server镜像挂载数据目录后丢失已提交变更的问题
问题描述
我提交的SQL Server镜像在使用挂载时无法正常工作:未挂载时,镜像包含我所做的变更;但挂载数据目录后,无法看到已提交的变更。
复现步骤
- 运行SQL Server 2019容器:
docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=P@ssword123" -p 14350:1433 -d mcr.microsoft.com/mssql/server:2019-latest
- 连接该SQL Server并创建名为TestDB的数据库。
- 提交容器(ID为cabc3ac26dd0)并标记为testdb,随后删除原容器:
docker commit cabc3ac26dd0 testdb docker container stop cabc3ac26dd0 docker rm cabc3ac26dd0
- 使用新镜像运行容器:
docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=P@ssword123" -p 14350:1433 -d testdb
连接该容器可看到TestDB,说明提交成功。
5. 删除容器后,将数据目录挂载到本地文件系统运行testdb镜像:
docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=P@ssword123" -p 14350:1433 --mount type=bind,source=C:\Users\me\testdbfiles\mssql\data,target=/var/opt/mssql/data -d testdb
此时连接容器看不到TestDB。
补充信息
- 该docker run命令已使用数月,升级Docker Desktop 4.12.0后出现问题;
- 挂载目录包含SQL Server数据库文件(如master.mdf),挂载语法正确;
- 未挂载时查询sys.databases可见TestDB,挂载后无此数据库,说明master数据库不同;
- 未挂载时/var/opt/mssql/data目录含TestDB文件,挂载后无;
- 更新:镜像中新增的SQL Server登录,挂载后也无法看到,未挂载时正常。
排查与解决方法
核心原因
Docker的bind mount会直接将容器内的目标目录(/var/opt/mssql/data)替换为本地挂载目录的内容。你挂载的本地目录中的master.mdf是旧版本,未包含提交镜像时新增的TestDB和登录信息,因此容器启动后加载的是旧的master数据库,自然看不到变更。
排查步骤
- 检查本地挂载目录内容:直接查看
C:\Users\me\testdbfiles\mssql\data,确认其中是否包含TestDB的相关文件(如TestDB.mdf、TestDB_log.ldf),以及master.mdf的修改时间是否与提交镜像的时间匹配。 - 验证容器内目录状态:启动挂载后的容器,执行以下命令查看数据目录内容:
docker exec -it <容器ID> bash ls /var/opt/mssql/data
对比未挂载容器的/var/opt/mssql/data内容,确认挂载是否覆盖了镜像内的目录。
3. 检查权限问题:Docker Desktop 4.12.0可能调整了文件权限处理,确保本地目录的权限允许容器内的SQL Server进程(用户mssql)读取和写入文件。在Windows上,可检查目录的共享权限是否开放给Docker相关用户。
解决方法
方法1:同步本地挂载目录与镜像内容
将提交后镜像内的最新数据目录内容复制到本地挂载目录:
- 启动临时容器(不挂载本地目录):
docker run -d --name temp-sync testdb
- 复制容器内数据到本地目录:
docker cp temp-sync:/var/opt/mssql/data/ C:\Users\me\testdbfiles\mssql\data
- 停止并删除临时容器:
docker stop temp-sync && docker rm temp-sync
- 重新启动挂载容器,此时本地目录已包含最新的master数据库和TestDB文件。
方法2:改用Docker Volume管理数据
Docker Volume比bind mount更适合数据库场景,可避免手动同步的麻烦:
- 创建专用Volume:
docker volume create mssql-test-data
- 启动临时容器,将镜像内的数据同步到Volume:
docker run -d --name temp-volume-sync -v mssql-test-data:/var/opt/mssql/data testdb
等待容器启动完成后,停止并删除临时容器:
docker stop temp-volume-sync && docker rm temp-volume-sync
- 使用Volume启动容器:
docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=P@ssword123" -p 14350:1433 -v mssql-test-data:/var/opt/mssql/data -d testdb
内容的提问来源于stack exchange,提问作者Don Chambers
相关产品推荐
相关产品推荐

