sql-server - 使用纯粹的 Dockerfile 创建带有恢复的备份数据库的 SQL Server docker 映像
问题描述
以下 docker 文件使用从备份 (rmsdev.bak) 恢复的数据库创建自定义 SQL 服务器映像。
FROM mcr.microsoft.com/mssql/server:2019-latest
ENV MSSQL_PID=Developer
ENV SA_PASSWORD=Password1?
ENV ACCEPT_EULA=Y
USER mssql
COPY rmsdev.bak /var/opt/mssql/backup/
# Launch SQL Server, confirm startup is complete, restore the database, then terminate SQL Server.
RUN ( /opt/mssql/bin/sqlservr & ) | grep -q "Service Broker manager has started" \
&& /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P $SA_PASSWORD -Q 'RESTORE DATABASE rmsdev FROM DISK = "/var/opt/mssql/backup/rmsdev.bak" WITH MOVE "rmsdev" to "/var/opt/mssql/data/rmsdev.mdf", MOVE "rmsdev_Log" to "/var/opt/mssql/data/rmsdev_log.ldf", NOUNLOAD, STATS = 5' \
&& pkill sqlservr
CMD ["/opt/mssql/bin/sqlservr"]
问题是,一旦恢复完成,就不再需要备份文件,我想将其从映像中删除。
不幸的是,由于 docker 图像的形成方式(层),我不能像我想的那样简单地“rm”文件。
多阶段 Dockerfile 在这种情况下并不像在构建场景中那样容易应用。另一种方法是运行容器,恢复备份,然后提交一个新图像,但我想做的是只使用 docker build 和正确的 Dockerfile。
有人知道方法吗?
解决方案
如果您知道数据目录在映像中的位置,并且映像没有将该目录声明为VOLUME
,那么您可以为此使用多阶段构建。如您所见,第一阶段将设置数据目录。第二阶段将从第一阶段复制填充的数据目录,但不复制备份文件。这个技巧可能取决于运行相同构建的底层软件的两个阶段。
对于 SQL Server,Docker Hub 页面和GitHub存储库都很难找到,而且令人惊讶的是,它们都没有谈到数据存储问题(正如 @HansKillian 在评论中指出的那样,您几乎总是希望以某种形式存储数据库数据体积)。GitHub 存储库确实包含一个围绕Kubernetes StatefulSet构建的Helm 图表,从中我们可以发现数据目录将安装在./var/opt/mssql
所以我可能会像这样编写一个多阶段构建:
# Put common setup steps in an initial stage
FROM mcr.microsoft.com/mssql/server:2019-latest AS setup
ENV MSSQL_PID=Developer
ENV SA_PASSWORD=Password1? # (weak password, easily extracted with `docker inspect`)
ENV ACCEPT_EULA=Y # (legally probably the end user needs to accept this not the image builder)
# Have a stage specifically to populate the data directory
FROM setup AS data
# (copy-and-pasted from the question)
USER mssql
COPY rmsdev.bak / # not under /var/opt/mssql
RUN ( /opt/mssql/bin/sqlservr & ) | grep -q "Service Broker manager has started" \
&& /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P $SA_PASSWORD -Q 'RESTORE DATABASE rmsdev FROM DISK = "/rmsdev.bak" WITH MOVE "rmsdev" to "/var/opt/mssql/data/rmsdev.mdf", MOVE "rmsdev_Log" to "/var/opt/mssql/data/rmsdev_log.ldf", NOUNLOAD, STATS = 5' \
&& pkill sqlservr
# Final stage that actually will actually be run.
FROM setup
# Copy the prepopulated data tree, but not the backup file
COPY --from=data /var/opt/mssql /var/opt/mssql
# Use the default USER, CMD, etc. from the base SQL Server image
标准的 Docker Hub 开源数据库镜像喜欢mysql
并且postgres
通常VOLUME
在其 Dockerfile 中为数据库数据声明一个,这会强制将数据存储在一个卷中。这意味着重要的是您不能像这样在图像中设置数据;您必须在外部填充数据,然后将数据树复制到 Docker 映像系统之外。
推荐阅读
- c# - 仅用于一个控制器的 Web API 缓存 DLL 和符号文件
- java - 流的收集功能中组合器的用途是什么?
- r - 如何让 R 代码等待后台 R 会话完成?
- javascript - 模态关闭后停止 jQuery 函数
- pandas - 我想拆分字符串并只保留第一个单词
- swift - 如何从 SwiftUI 中的导航栏按钮单击导航到新视图
- java - 错误:针对 Android API 28 时找不到符号变量 CLIP_SAVE_FLAG
- jquery - 如何仅捕获文本但忽略带有元素的文本?
- xml - 如何将以下标签中的所有文本项收集到以名称为键、年份为值的字典中?
- c# - 报告查看器中的部分