Docker Compose启动后无法附加SQL Server数据库sm3的问题
我有两个Docker镜像:Web API和SQL Server。测试数据库sm3位于容器的/var/opt/mssql/data/目录下(仅用于测试,生产数据库通过volume挂载在服务器上)。
我的docker-compose配置如下:
version: "3.9" # optional since v1.27.0 services: web_api: image: web_api container_name: web_api_application volumes: - /root/smData/uploads:/app/uploads ports: - "80:80" - "443:443" depends_on: - sql sql: image: "mcr.microsoft.com/mssql/server:2022-latest" container_name: sql_server2022 ports: - "1433:1433" volumes: - /root/smData:/app environment: - ACCEPT_EULA=y - SA_PASSWORD=MyVery$trogPas$ - attach_dbs=[{"dbName":"sm3","dbFiles":["/var/opt/mssql/data/sm3.mdf","/var/opt/mssql/data/sm3_log.ldf"]}]
sm3数据库是通过连接到服务器的SSMS创建后分离的,且已确认sm3.mdf和sm3_log.ldf存在于容器的/var/opt/mssql/data目录中。
执行docker compose up后,预期在数据库资源管理器中能看到已附加的sm3数据库,但实际并未出现。容器日志无法正常读取,示例如下:
sql_server2022 | D sql_server2022 | a sql_server2022 | t sql_server2022 | a sql_server2022 | b sql_server2022 | a sql_server2022 | s sql_server2022 | e sql_server2022 | sql_server2022 | ' sql_server2022 | m sql_server2022 | s sql_server2022 | d sql_server2022 | b sql_server2022 | ' sql_server2022 | sql_server2022 | r sql_server2022 | u sql_server2022 | n sql_server2022 | n sql_server2022 | i sql_server2022 | n sql_server2022 | g sql_server2022 | sql_server2022 | t sql_server2022 | h sql_server2022 | e sql_server2022 | sql_server2022 | u sql_server2022 | p sql_server2022 | g sql_server2022 | r sql_server2022 | a sql_server2022 | d sql_server2022 | e sql_server2022 | sql_server2022 | s sql_server2022 | t sql_server2022 | e sql_server2022 | p sql_server2022 | sql_server2022 | f sql_server2022 | r sql_server2022 | o sql_server2022 | m sql_server2022 | sql_server2022 | v sql_server2022 | e sql_server2022 | r sql_server2022 | s sql_server2022 | i sql_server2022 | o sql_server2022 | n sql_server2022 | sql_server2022 | 9 sql_server2022 | 5 sql_server2022 | 4
查看var/opt/mssql/log下的SQL Server日志,未发现数据库附加相关的执行记录,请问我哪里操作有误?
1. 修复attach_dbs环境变量格式
SQL Server容器的attach_dbs变量要求严格的JSON格式,在docker-compose中直接写未转义的JSON会被shell解析出错,导致容器无法识别该配置。
修正方式二选一:
- 转义JSON内部的双引号:
- attach_dbs="[{\\"dbName\\":\\"sm3\\",\\"dbFiles\\":[\\"/var/opt/mssql/data/sm3.mdf\\",\\"/var/opt/mssql/data/sm3_log.ldf\\"]}]" - 用单引号包裹整个JSON字符串(适配bash环境):
- attach_dbs='[{"dbName":"sm3","dbFiles":["/var/opt/mssql/data/sm3.mdf","/var/opt/mssql/data/sm3_log.ldf"]}]'
2. 检查数据库文件权限
SQL Server容器内以mssql用户(UID=10001)运行,如果数据库文件权限不是该用户可读写,会导致附加失败且无明确报错。
修正操作:
进入容器修改文件权限:
docker exec -it sql_server2022 bash chown mssql:mssql /var/opt/mssql/data/sm3.mdf /var/opt/mssql/data/sm3_log.ldf
或者在宿主机复制文件时直接设置权限:
chown 10001:10001 /path/to/sm3.mdf /path/to/sm3_log.ldf
3. 确保数据库文件在容器初始化前存在
如果是首次启动容器,SQL Server会先初始化数据目录,之后才会处理attach_dbs配置。如果数据库文件是容器启动后才复制进去的,attach_dbs不会触发。
测试场景下可以直接挂载包含数据库文件的目录到容器的/var/opt/mssql/data:
volumes: - /root/smData/mssql-data:/var/opt/mssql/data
4. 排查日志乱码问题
日志每行一个字符是编码问题,用以下命令查看完整日志:
docker logs sql_server2022 2>&1 | cat -v
或者直接进入容器查看SQL Server原生日志:
docker exec -it sql_server2022 cat /var/opt/mssql/log/errorlog
5. 手动附加验证
如果以上步骤无效,手动进入容器执行附加命令,获取具体错误信息:
docker exec -it sql_server2022 /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "MyVery$trogPas$"
然后执行SQL命令:
CREATE DATABASE sm3 ON (FILENAME = '/var/opt/mssql/data/sm3.mdf'), (FILENAME = '/var/opt/mssql/data/sm3_log.ldf') FOR ATTACH; GO
根据返回的错误信息针对性排查即可。
内容的提问来源于stack exchange,提问作者eg01st

