问题
如果我们使用 SQL Server 的容器镜像运行 SQL Server,并且希望使用 Docker Volume 来持久化我们的数据库文件,保证在重启数据库以后,数据库也不会丢失,我们会使用类似于下面的命令:
docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>' -p 1433:1433 -v <host directory>/data:/var/opt/mssql/data -v <host directory>/log:/var/opt/mssql/log -v <host directory>/secrets:/var/opt/mssql/secrets -d mcr.microsoft.com/mssql/server:2019-latest
其中 host directory 是容器外的文件夹,但是在实际执行的时候,我们可能会看到类似于下面的错误。
SQL Server 2019 will run as non-root by default.
This container is running as user mssql.
To learn more visit https://go.microsoft.com/fwlink/?linkid=2099216.
2022-11-07 13:26:54.40 Server Setup step is copying system data file 'C:\templatedata\master.mdf' to '/var/opt/mssql/data/master.mdf'.
2022-11-07 13:26:54.43 Server ERROR: Setup FAILED copying system data file 'C:\templatedata\master.mdf' to '/var/opt/mssql/data/master.mdf': 5(Access is denied.)
ERROR: BootstrapSystemDataDirectories() failure (HRESULT 0x80070005)
原因
这是因为 SQL Server 在容器中是使用 mssql 这个用户来运行的,不是 root,所以权限受到了限制。我们可以使用以下命令进入容器查看 mssql 这个用户的 ID,方便我们修改主机文件夹的权限来给 mssql 赋权。
解决方案
执行以下命令进入MSSQL 的容器
docker run -it --entrypoint /bin/sh mcr.microsoft.com/mssql/server:2019-latest
然后执行下面的命令查看 mssql 的用户 ID
id mssql
我们会看到以下的结果
uid=10001(mssql) gid=0(root) groups=0(root)
接下来我们把目标文件夹的所有者改为 10001
sudo chown -R 10001 <host-directory>
再次执行以下命令 SQL Server 就可以正常运行了:
docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=<YourStrong!Passw0rd>' -p 1433:1433 -v <host directory>/data:/var/opt/mssql/data -v <host directory>/log:/var/opt/mssql/log -v <host directory>/secrets:/var/opt/mssql/secrets -d mcr.microsoft.com/mssql/server:2019-latest
结论
由于 SQL Server 容器使用 mssql 用户执行,造成了使用 docker volume 持久化失败。解决方案是把主机的指定文件夹的所有者改为 mssql 的 ID 10001,我们就可以成功使用 docker volume 来持久化我们的数据文件了。