如何使Mac Docker支持SQL on Linux容器Volume特性

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 这篇文章解决了Docker容器中SQL on Linux实例数据库与容器本身同生死同命运的问题,提出了当Docker容器销毁后,容器中的数据库文件得以保留的方法。

问题引入

这天老鸟火急火燎的找到菜鸟:“鸟儿啊,按照你之前的文章SQL on Linux Run on Docker,当我销毁SQL on Linux Docker容器以后,我容器中的所有数据库数据丢失啦,怎么办,怎么办啊?”。
菜鸟一脸懵逼:“我是参照微软官方文档来的啊?难道这帮XX连这个问题都没有想到?”。于是,菜鸟开始了问题的重现和解决方法。

问题重现

按照上一篇文件启动的Docker容器,SQL on Linux实例中的数据库文件真的会随着Docker容器的销毁而消失,造成数据丢失的灾难吗?这一节进行问题重现和复盘。

启动Docker容器

使用Docker Run命令启动SQL on Linux服务,映射到母体机41433端口上。

$ docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=SQLOnLinux@123' -p 41433:1433 -d microsoft/mssql-server-linux

创建测试对象

使用SSMS连接到Docker母体机41433端口上,执行下面的测试代码:创建测试数据库、创建测试表、初始化两条数据和查询测试表。

IF DB_ID('TestDb') IS NULL
    CREATE DATABASE TestDb;
GO

USE TestDb
GO
IF OBJECT_ID('dbo.Test', 'U') IS NOT NULL
    DROP TABLE dbo.Test
GO

CREATE TABLE dbo.Test(
RowID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY
,Name VARCHAR(20) NOT NULL
);

INSERT INTO dbo.Test
SELECT 'A' UNION ALL SELECT 'B';

SELECT * FROM dbo.Test;

结果如下图展示:
01.png

销毁Docker容器

接下来模拟Docker容器销毁过程:我们需要使用Docker Stop停止SQL on Linux容器,然后使用Docker rm删除这个容器,接下来再次启动Docker容器,最后检查测试数据库、测试表和数据是否存在。如果不存在,说明Docker容器中的数据已经丢失。

$ docker ps
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                     NAMES
8c1202ff7a33        microsoft/mssql-server-linux   "/bin/sh -c /opt/m..."   2 minutes ago       Up 2 minutes        0.0.0.0:41433->1433/tcp   suspicious_liskov
...
$ docker stop 8c1202ff7a33
8c1202ff7a33
$ docker rm 8c1202ff7a33
8c1202ff7a33
$ docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=SQLOnLinux@123' -p 41433:1433 -d microsoft/mssql-server-linux
83cd4ca5cdf3d370118c10d8b783b204f86aa7b50fd7e334a27542d2cf7a1230

检查测试对象

再次使用SSMS连接到Docker母体机41433端口,查看测试数据库,展示如下图:
02.png

从这个结果来看,测试数据库已经丢失。说明Docker容器与容器中的数据库是命运共同体、同生死共命运。如果Docker容器销毁,容器中的数据库数据也随之丢失。这个是用户数据的灾难,我们需要迫切解决这个问题。看来老鸟说的大实话啊。

解决问题

SQL on Linux对Mac Docker Volume的限制

要解决这个问题,我们需要引入Docker的Volume技术。简单的说,这个技术的核心思想就是在启动Docker容器的时候,将Docker容器中的目录映射到母体机的目录,Docker容器对这个目录的所有操作会反映到母体机的这个映射目录里面。当Docker容器销毁的时候,母体机的这个映射目录会被保留下来。这样,我们的数据库数据文件不会随着容器的销毁而消失了,继而就解决了这个问题。但是,偏偏目前SQL on Linux不支持Mac操作系统的Docker Volume特性。详情参见微软官方文档:Run the SQL Server Docker image on Linux, Mac, or Windows
关键的地方,截图如下展示:
03.png
Mac系统Docker就真的不支持SQL on Linux Docker容器的Volume吗?让我们来试试看:

$ docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=SQLOnLinux@123' -p 41433:1433 -v /Users/cherish/Downloads/linuxsqldata:/var/opt/mssql -it microsoft/mssql-server-linux
Configuring Microsoft(R) SQL Server(R)...
Microsoft(R) SQL Server(R) setup failed with error code 1. Please check the setup log in /var/opt/mssql/log for more information.

的确启动Docker容器的过程中就会报告错误,详细的错误日志信息如下:

$ cat ~/Downloads/linuxsqldata/log/errorlog
2017-02-09 13:20:06.62 Server      Microsoft SQL Server vNext (CTP1.2) - 14.0.200.24 (X64) 
    Jan 10 2017 19:15:28 
    Copyright (C) 2016 Microsoft Corporation. All rights reserved.
    on Linux (Ubuntu 16.04.1 LTS)
2017-02-09 13:20:06.76 Server      UTC adjustment: 0:00
2017-02-09 13:20:06.80 Server      (c) Microsoft Corporation.
2017-02-09 13:20:06.84 Server      All rights reserved.
2017-02-09 13:20:06.88 Server      Server process ID is 4116.
2017-02-09 13:20:06.92 Server      Logging SQL Server messages in file 'C:\var\opt\mssql\log\errorlog'.
2017-02-09 13:20:06.98 Server      Registry startup parameters: 
     -d C:\var\opt\mssql\data\master.mdf
     -l C:\var\opt\mssql\data\mastlog.ldf
     -e C:\var\opt\mssql\log\errorlog
2017-02-09 13:20:07.09 Server      Command Line Startup Parameters:
     --setup
     --sa-password
2017-02-09 13:20:07.58 Server      Error: 17113, Severity: 16, State: 1.
2017-02-09 13:20:07.58 Server      Error 87(The parameter is incorrect.) occurred while opening file 'C:\var\opt\mssql\data\master.mdf' to obtain configuration information at startup. An invalid startup option might have caused the error. Verify your startup options, and correct or remove them if necessary.

解决方案

巴嘎,这里就又引入了另外一个问题,如何解决Mac系统上SQL on Linux的Docker容器不支持Volume的问题?不要惊慌,淡定,当然是有办法的,这个解决方法便是这篇文章存在的意义。解决方法如下:

$ docker create -v /var/opt/mssql --name sql41433data microsoft/mssql-server-linux
2e1deac3c2bffa5f6cd97dfdc3683c59628538550ea9010d16214906c299cf54

$ docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=SQLOnLinux@123' -p 41433:1433 --volumes-from sql41433data -it --name linuxsql41433 microsoft/mssql-server-linux

大概30秒后,Docker容器中的SQL实例服务起来以后,首先,参照问题重现中创建测试对象,然后销毁Docker容器,接下来再次启动Docker容器。

$ docker ps 
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                     NAMES
596f3bfebb8a        microsoft/mssql-server-linux   "/bin/sh -c /opt/m..."   57 seconds ago      Up 56 seconds       0.0.0.0:41433->1433/tcp   linuxsql41433
...
$ docker stop 596f3bfebb8a
596f3bfebb8a
$ docker rm 596f3bfebb8a
596f3bfebb8a
$ docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=SQLOnLinux@123' -p 41433:1433 --volumes-from sql41433data -it --name linuxsql41433 microsoft/mssql-server-linux

最后检查测试对象,截图如下:
04.png
其实,从启动过程的日志,我们也可以看到TestDb已经启动。
05.png
说明这个解决方法切实有效。

最后总结

这篇文章解决了Docker容器中SQL on Linux实例数据库与容器本身同生死同命运的问题,使得用户数据在容器被销毁时得以保留。更加详细的过程和步骤,可以参看youku视频:
11_SQLOnLinux_MacDockerVolumes

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
14天前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
25天前
|
存储 监控 Linux
在Linux中,如何进行容器技术的应用?
在Linux中,如何进行容器技术的应用?
|
23天前
|
Kubernetes Linux Docker
【Azure 应用服务】使用Docker Compose创建App Service遇见"Linux Version is too long. It cannot be more than 4000 characters"错误
【Azure 应用服务】使用Docker Compose创建App Service遇见"Linux Version is too long. It cannot be more than 4000 characters"错误
|
25天前
|
Kubernetes Ubuntu Linux
在Linux中,如何设计和部署容器化应用?
在Linux中,如何设计和部署容器化应用?
|
25天前
|
Linux 持续交付 虚拟化
在Linux中,Docker和容器虚拟概念是什么?
在Linux中,Docker和容器虚拟概念是什么?
|
26天前
|
运维 Kubernetes Linux
docker和kubectl客户端安装Linux
通过上述步骤,您应该已经在Linux环境中成功安装了Docker和kubectl客户端。安装完成后,您可以开始使用Docker来创建和管理容器,使用kubectl来管理Kubernetes集群。这些工具的安装和使用,对于现代云原生应用的开发和运维来说,是一个基础且关键的步骤。
26 0
|
27天前
|
存储 缓存 监控
在Linux中,如何优化虚拟机和容器的性能和资源使用?
在Linux中,如何优化虚拟机和容器的性能和资源使用?
|
27天前
|
Linux KVM 虚拟化
在Linux中,如何进行虚拟机和容器的备份和迁移?
在Linux中,如何进行虚拟机和容器的备份和迁移?
|
2月前
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
59 13
|
2月前
|
SQL
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。