开箱即用的 SQL Server Docker 之二
Docker 与 SQL Server 之一,讲的还只是 Docker 的一些基础概念,这篇将 Docker 应用在 SQL Server 上,包括这些主题:
- 在 Docker 上制作 SQL Server 镜像
- Docker 发布 SQL Server
参考:https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-2017
1. 在 Docker 上制作 SQL Server 镜像
制作 SQL Server On Docker 的镜像:
[aaa@qq.com Redis]# docker pull microsoft/mssql-server-linux
Using default tag: latest
Trying to pull repository docker.io/microsoft/mssql-server-linux ...
latest: Pulling from docker.io/microsoft/mssql-server-linux
f6fa9a861b90: Extracting [======================> ] 21.14 MB/46.41 MB
da7318603015: Download complete
6a8bd10c9278: Download complete
d5a40291440f: Download complete
bbdd8a83c0f1: Download complete
3a52205d40a6: Downloading [====================================> ] 21.27 MB/28.98 MB
6192691706e8: Downloading [=====================================> ] 28.7 MB/38.7 MB
1a658a9035fb: Download complete
25c716e804a1: Waiting
28fea03ad20e: Waiting
运行新建的 SQL Server On Docker 镜像:
# 官方实例
sudo docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=<YourStrong!Passw0rd>' \
-p 1433:1433 --name sql1 \
-d microsoft/mssql-server-linux:2017-latest
[aaa@qq.com Redis]# docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=1QAZ2WSX' -e 'MSSQL_PID=Developer' -p 1433 --rm --name=sqlserver microsoft/mssql-server-linux
2018-09-02 23:52:48.67 Server Setup step is copying system data file 'C:\templatedata\master.mdf' to '/var/opt/mssql/data/master.mdf'.
2018-09-02 23:52:48.83 Server Did not find an existing master data file /var/opt/mssql/data/master.mdf, copying the missing default master and other system database files. If you have moved the database location, but not moved the database files, startup may fail. To repair: shutdown SQL Server, move the master database to configured location, and restart.
2018-09-02 23:52:48.84 Server Setup step is copying system data file 'C:\templatedata\mastlog.ldf' to '/var/opt/mssql/data/mastlog.ldf'.
2018-09-02 23:52:48.85 Server Setup step is copying system data file 'C:\templatedata\model.mdf' to '/var/opt/mssql/data/model.mdf'.
2018-09-02 23:52:48.90 Server Setup step is copying system data file 'C:\templatedata\modellog.ldf' to '/var/opt/mssql/data/modellog.ldf'.
2018-09-02 23:52:48.94 Server Setup step is copying system data file 'C:\templatedata\msdbdata.mdf' to '/var/opt/mssql/data/msdbdata.mdf'.
2018-09-02 23:52:48.97 Server Setup step is copying system data file 'C:\templatedata\msdblog.ldf' to '/var/opt/mssql/data/msdblog.ldf'.
2018-09-02 23:52:49.16 Server Microsoft SQL Server 2017 (RTM-CU10) (KB4342123) - 14.0.3037.1 (X64)
Jul 27 2018 09:40:27
Copyright (C) 2017 Microsoft Corporation
Developer Edition (64-bit) on Linux (Ubuntu 16.04.5 LTS)
2018-09-02 23:52:49.17 Server UTC adjustment: 0:00
2018-09-02 23:52:49.17 Server (c) Microsoft Corporation.
2018-09-02 23:52:49.17 Server All rights reserved.
2018-09-02 23:52:49.18 Server Server process ID is 4120.
2018-09-02 23:52:49.18 Server Logging SQL Server messages in file '/var/opt/mssql/log/errorlog'.
2018-09-02 23:52:49.18 Server Registry startup parameters:
-d /var/opt/mssql/data/master.mdf
-l /var/opt/mssql/data/mastlog.ldf
-e /var/opt/mssql/log/errorlog
2018-09-02 23:52:49.21 Server SQL Server detected 2 sockets with 2 cores per socket and 2 logical processors per socket, 4 total logical processors; using 4 logical processors based on SQL Server licensing. This is an informational message; no user action is required.
2018-09-02 23:52:49.22 Server SQL Server is starting at normal priority base (=7). This is an informational message only. No user action is required.
2018-09-02 23:52:49.23 Server Detected 3030 MB of RAM. This is an informational message; no user action is required.
2018-09-02 23:52:49.23 Server Using conventional memory in the memory manager.
2018-09-02 23:52:49.69 Server Buffer pool extension is already disabled. No action is necessary.
2018-09-02 23:52:50.14 Server InitializeExternalUserGroupSid failed. Implied authentication will be disabled.
2018-09-02 23:52:50.14 Server Implied authentication manager initialization failed. Implied authentication will be disabled.
2018-09-02 23:52:50.16 Server Successfully initialized the TLS configuration. Allowed TLS protocol versions are ['1.0 1.1 1.2']. Allowed TLS ciphers are ['ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:!DHE-RSA-AES256-GCM-SHA384:!DHE-RSA-AES128-GCM-SHA256:!DHE-RSA-AES256-SHA:!DHE-RSA-AES128-SHA'].
2018-09-02 23:52:50.26 Server The maximum number of dedicated administrator connections for this instance is '1'
2018-09-02 23:52:50.26 Server Node configuration: node 0: CPU mask: 0x000000000000000f:0 Active CPU mask: 0x000000000000000f:0. This message provides a description of the NUMA configuration for this computer. This is an informational message only. No user action is required.
2018-09-02 23:52:50.28 Server Using dynamic lock allocation. Initial allocation of 2500 Lock blocks and 5000 Lock Owner blocks per node. This is an informational message only. No user action is required.
2018-09-02 23:52:50.31 Server In-Memory OLTP initialized on lowend machine.
2018-09-02 23:52:50.42 Server Database Instant File Initialization: enabled. For security and performance considerations see the topic 'Database Instant File Initialization' in SQL Server Books Online. This is an informational message only. No user action is required.
ForceFlush is enabled for this instance.
2018-09-02 23:52:50.44 Server Query Store settings initialized with enabled = 1,
2018-09-02 23:52:50.46 Server Software Usage Metrics is disabled.
2018-09-02 23:52:50.46 spid6s Starting up database 'master'.
ForceFlush feature is enabled for log durability.
2018-09-02 23:52:50.78 spid6s The tail of the log for database master is being rewritten to match the new sector size of 4096 bytes. 3072 bytes at offset 418816 in file /var/opt/mssql/data/mastlog.ldf will be written.
2018-09-02 23:52:51.31 spid6s Converting database 'master' from version 862 to the current version 869.
2018-09-02 23:52:51.32 spid6s Database 'master' running the upgrade step from version 862 to version 863.
2018-09-02 23:52:51.38 spid6s Database 'master' running the upgrade step from version 863 to version 864.
2018-09-02 23:52:51.49 spid6s Database 'master' running the upgrade step from version 864 to version 865.
2018-09-02 23:52:51.53 spid6s Database 'master' running the upgrade step from version 865 to version 866.
2018-09-02 23:52:51.58 spid6s Database 'master' running the upgrade step from version 866 to version 867.
2018-09-02 23:52:51.62 spid6s Database 'master' running the upgrade step from version 867 to version 868.
2018-09-02 23:52:51.66 spid6s Database 'master' running the upgrade step from version 868 to version 869.
2018-09-02 23:52:52.15 spid6s Resource governor reconfiguration succeeded.
2018-09-02 23:52:52.15 spid6s SQL Server Audit is starting the audits. This is an informational message. No user action is required.
2018-09-02 23:52:52.16 spid6s SQL Server Audit has started the audits. This is an informational message. No user action is required.
2018-09-02 23:52:52.29 spid6s SQL Trace ID 1 was started by login "sa".
2018-09-02 23:52:52.35 spid6s Server name is '104ee73da2eb'. This is an informational message only. No user action is required.
2018-09-02 23:52:52.40 spid20s Always On: The availability replica manager is starting. This is an informational message only. No user action is required.
2018-09-02 23:52:52.41 spid20s Always On: The availability replica manager is waiting for the instance of SQL Server to allow client connections. This is an informational message only. No user action is required.
2018-09-02 23:52:52.41 spid6s Starting up database 'msdb'.
2018-09-02 23:52:52.42 spid9s Starting up database 'mssqlsystemresource'.
2018-09-02 23:52:52.45 spid9s The resource database build version is 14.00.3037. This is an informational message only. No user action is required.
2018-09-02 23:52:52.47 spid19s Password policy update was successful.
2018-09-02 23:52:52.57 spid9s Starting up database 'model'.
2018-09-02 23:52:52.92 spid6s The tail of the log for database msdb is being rewritten to match the new sector size of 4096 bytes. 512 bytes at offset 306688 in file /var/opt/mssql/data/MSDBLog.ldf will be written.
2018-09-02 23:52:52.99 spid6s Converting database 'msdb' from version 862 to the current version 869.
2018-09-02 23:52:53.00 spid6s Database 'msdb' running the upgrade step from version 862 to version 863.
2018-09-02 23:52:53.11 spid9s The tail of the log for database model is being rewritten to match the new sector size of 4096 bytes. 2048 bytes at offset 75776 in file /var/opt/mssql/data/modellog.ldf will be written.
2018-09-02 23:52:53.12 spid19s A self-generated certificate was successfully loaded for encryption.
2018-09-02 23:52:53.14 spid19s Server is listening on [ 'any' <ipv6> 1433].
2018-09-02 23:52:53.15 spid19s Server is listening on [ 'any' <ipv4> 1433].
2018-09-02 23:52:53.16 spid6s Database 'msdb' running the upgrade step from version 863 to version 864.
2018-09-02 23:52:53.17 Server Server is listening on [ ::1 <ipv6> 1434].
2018-09-02 23:52:53.17 Server Server is listening on [ 127.0.0.1 <ipv4> 1434].
2018-09-02 23:52:53.18 Server Dedicated admin connection support was established for listening locally on port 1434.
2018-09-02 23:52:53.19 spid9s Converting database 'model' from version 862 to the current version 869.
2018-09-02 23:52:53.19 spid9s Database 'model' running the upgrade step from version 862 to version 863.
2018-09-02 23:52:53.21 spid19s SQL Server is now ready for client connections. This is an informational message; no user action is required.
2018-09-02 23:52:53.27 spid6s Database 'msdb' running the upgrade step from version 864 to version 865.
2018-09-02 23:52:53.29 spid9s Database 'model' running the upgrade step from version 863 to version 864.
2018-09-02 23:52:53.33 spid6s Database 'msdb' running the upgrade step from version 865 to version 866.
2018-09-02 23:52:53.35 spid9s Database 'model' running the upgrade step from version 864 to version 865.
2018-09-02 23:52:53.38 spid6s Database 'msdb' running the upgrade step from version 866 to version 867.
2018-09-02 23:52:53.42 spid9s Database 'model' running the upgrade step from version 865 to version 866.
2018-09-02 23:52:53.45 spid6s Database 'msdb' running the upgrade step from version 867 to version 868.
2018-09-02 23:52:53.49 spid9s Database 'model' running the upgrade step from version 866 to version 867.
2018-09-02 23:52:53.51 spid6s Database 'msdb' running the upgrade step from version 868 to version 869.
2018-09-02 23:52:53.54 spid9s Database 'model' running the upgrade step from version 867 to version 868.
2018-09-02 23:52:53.58 spid9s Database 'model' running the upgrade step from version 868 to version 869.
2018-09-02 23:52:53.77 spid9s Polybase feature disabled.
2018-09-02 23:52:53.77 spid9s Clearing tempdb database.
2018-09-02 23:52:54.59 spid9s Starting up database 'tempdb'.
2018-09-02 23:52:55.02 spid9s The tempdb database has 1 data file(s).
2018-09-02 23:52:55.08 spid24s The Service Broker endpoint is in disabled or stopped state.
2018-09-02 23:52:55.09 spid24s The Database Mirroring endpoint is in disabled or stopped state.
2018-09-02 23:52:55.11 spid24s Service Broker manager has started.
2018-09-02 23:52:55.26 spid6s Recovery is complete. This is an informational message only. No user action is required.
2018-09-02 23:52:55.40 spid20s The default language (LCID 0) has been set for engine and full-text services.
2018-09-02 23:57:57.72 spid54 Using 'dbghelp.dll' version '4.0.5'
连接在 Docker 中运行的 SQL Server:
# 官方实例
sudo docker exec -it sql1 /opt/mssql-tools/bin/sqlcmd \
-S localhost -U SA -P '<YourStrong!Passw0rd>' \
-Q 'ALTER LOGIN SA WITH PASSWORD="<YourNewStrong!Passw0rd>"'
[aaa@qq.com Sinatra]# docker exec -it sqlserver /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P '1QAZ2WSX'
Docker 持续集成 SQL Server 变更
在持续发布 SQL Server 变更的过程中,Docker 需要做的有两件事:
1 Docker 不会持久性保存数据,将数据库存储文件与 Docker 隔离,指向外围的数据文件,是第一件事。通过添加 volume 可以完成;
2 Docker 能保障的是数据库的运行环境,而我们在发布一次又一次的数据库变更时,更新的是实实在在的数据库对象,是内容而不仅仅是软硬件环境(操作系统补丁,或者数据库补丁等)。
因此在生成(build)数据库 Docker 镜像的时候,每个阶段都需要翻新上一个版本,即在上一个版本的基础上,应用本次 source code 中的变更,使其生成一个新的镜像,然后发布到各个环境,比如开发,测试甚至生产。
很多公司对于数据库开发规范和发布的做法,有很大的随意性。比如开发人员随意访问这种数据库环境,并且在这些环境上做了很多没有回滚的事务操作。发布数据库的时候,只是根据对象的存在与否而发了增量的变更。此时并不能真正有效的监测到数据库的发布脚本是否正确。一上生产就各种问题。
有了 SQL Server Docker 之后,可以很好的规避这个问题。每一次的变更都是基于上一个版本做增量更新,都会走一遍配置更新和脚本部署更新,对于原来的 DEV(开发环境),STG(QA 集成化测试环境),UAT(用户 sign off 环境) 都使用同一个构建的 SQL Server 环境,甚至对于测试数据(构建到 SQL Server Docker 里面去)也能每个平台保持一致,因此不会出现有了bug 无法重现的情况。只要把 SQL Server Docker 基于某一个开发版本重构建一次(其实每次的构建都会随着开发版本保留下来),所有环境立马相同,bug 也就无处遁形了。
总结一下, SQL Server Docker 的好处大约有:
1 构建一次,到处运行,保障了 DEV, STG, UAT 配置与数据的一致性
2 时刻保持与应用开发版本的步调一致
一个简易版本的 SQL Server Docker 持续集成例子
总体来说,因为数据库文件与容器的集成度不同,发布 SQL Server Docker 有两种方式:
1 数据库文件内建于容器镜像之内
2 数据库文件游离于容器镜像之外
1 构建【数据库文件内建于容器镜像之内】的 SQL Server Docker 发布步骤如下:
1 Pull 一个最原始的 sql server docker 镜像
镜像来自于微软在 Docker Hub 上提供的初始容器。
当然我们也可以自己用 Dockerfile 来生成一个自己的镜像。这样定制化就更强一些。
但为了方便陈述如何使用 sql server docker 来完成持续集成发布(CI),还是采用微软提供的镜像。可就在尝试去配置安全策略的时候,发生了点小麻烦,因为 dockerfile 的编制也相当于是一门语言 DSL, 需要培养语感。
[aaa@qq.com Redis]# docker pull microsoft/mssql-server-linux
打开 docker repository 库查看:
[aaa@qq.com Sinatra]# docker images microsoft/mssql-server-linux
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/microsoft/mssql-server-linux latest b2b20452a15b 3 weeks ago 1.44 GB
2 编写第一版的数据库对象创建脚本
SQL 脚本:
CREATE DATABASE CRM
GO
USE CRM
GO
CREATE TABLE dbo.Account(
AccountId INT IDENTITY(1,1),
AccountName NVARCHAR(200)
)
保存为 DBSchemaInit.sql
3 构建新容器镜像
基于从 Docker Hub 上的 sql server docker, 构建一个新的镜像,保存为 sqlv1. sqlv1 镜像解决的主要问题是,完成基本环境的配置,包括配置连接安全认证(用户和密码)以及执行第二步编写的数据库对象创建脚本。
构建自定义的容器镜像,最重要的是编写 Dockerfile.在编写这份 Dockerfile 的过程中,会有很多概念是需要逐一去理清楚的:
RUN 指令的运用。尝试用 RUN docker run 去配置 sa 密码,结果会运用到新的镜像吗?
我觉得是不会的。docker run 是运行一台 docker, 而运行 sql server docker 的时候,会用 docker run -e ‘ACCEPT_EULA=Y’ -e ‘SA_PASSWORD=PASSWORD’. 纠结的地方原来就在这里, -e 到底是什么意思!
如果 -e 是指环境变量,那就好办了,因为 dockerfile 编制手册上提到,用 ENV 来指定环境变量,那么只要在新建的这份 dockerfile 中指定 ENV 即可,而不是 RUN docker run 指令。
docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=<YourStrong!Passw0rd>' \
-p 1433:1433 --name sql1 \
-d microsoft/mssql-server-linux:2017-latest
好像说的 -e 就是环境变量,那么试一下。
[aaa@qq.com v1]# cat Dockerfile
FROM microsoft/mssql-server-linux
MAINTAINER Lenis Huang "aaa@qq.com"
ENV ACCEPT_EULA=Y
ENV SA_PASSWORD=1QAZ2WSX3EDC
EXPOSE 1433
最终似乎构建成功了:
[aaa@qq.com v1]# docker build -t=sqlserver/v1 .
Sending build context to Docker daemon 3.584 kB
Step 1/5 : FROM microsoft/mssql-server-linux
---> b2b20452a15b
Step 2/5 : MAINTAINER Lenis Huang "aaa@qq.com"
---> Running in 532a5f141f11
---> 182a1a9aed84
Removing intermediate container 532a5f141f11
Step 3/5 : ENV ACCEPT_EULA Y
---> Running in c72d741f2f8e
---> ee590cf78e2b
Removing intermediate container c72d741f2f8e
Step 4/5 : ENV SA_PASSWORD 1QAZ2WSX3EDC
---> Running in 67559621fd8d
---> 7d92d6155c25
Removing intermediate container 67559621fd8d
Step 5/5 : EXPOSE 1433
---> Running in 2bb8ee0440a4
---> 67f770bfdacd
Removing intermediate container 2bb8ee0440a4
Successfully built 67f770bfdacd
[aaa@qq.com v1]#
[aaa@qq.com v1]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
sqlserver/v1 latest 67f770bfdacd 36 seconds ago 1.44 GB
试着来运行新建的容器镜像:
[aaa@qq.com v1]# docker run -p 1433 --rm --name=dev_sqlv1 sqlserver/v1
2018-09-06 04:30:53.94 spid21s ERROR: Unable to set system administrator password: Password validation failed. The password does not meet SQL Server password policy requirements because it is not complex enough. The password must be at least 8 characters long and contain characters from three of the following four sets: Uppercase letters, Lowercase letters, Base 10 digits, and Symbols..
2018-09-06 04:30:53.96 spid21s An error occurred during server setup. See previous errors for more information.
2018-09-06 04:30:53.97 spid21s SQL Trace was stopped due to server shutdown. Trace ID = '1'. This is an informational message only; no user action is required.
[aaa@qq.com v1]#
密码强度不够。
FROM microsoft/mssql-server-linux
MAINTAINER Lenis Huang "aaa@qq.com"
ENV ACCEPT_EULA=Y
ENV SA_PASSWORD=1QAZ2wsx3EDC.
EXPOSE 1433
重复构建过程。
至此,一份崭新的可用于项目部署的 sql server docker 构建完毕。
[aaa@qq.com DockerNginx]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f29258559cb4 sqlserver/v1 "/opt/mssql/bin/sq..." About a minute ago Up 59 seconds 0.0.0.0:32793->1433/tcp dev_sqlv1
从 docker ps 执行的结果中看到运行着 sqlv1 镜像的容器,可以通过本机的 32793 端口连接到容器中 sql server 服务对应的 1433 端口。
在 Dev, STG, UAT 环境,都以 sqlv1 为蓝本,使应用都连接到在 sqlv1 容器中运行的数据库。开发测试中出现任何问题,都可以拿着 sqlv1 重建一个新的容器来运行数据库。
这种方式不能部署生产系统,因为数据库是集成在 docker 里面的。之后会讲脱离了容器的数据库,怎么完成 docker 化的发布。
4 开发新一版本的数据库应用,将其应用于 sqlv1 镜像,进而构建 sqlv2 镜像
[aaa@qq.com v2]# cat Dockerfile
FROM sqlserver/v1
MAINTAINER Lenis Huang "aaa@qq.com"
CMD sqlcmd -S localhost,1433 -U sa -P 1QAZ2wsx3EDC. -i DBSchemaInit.sql
[aaa@qq.com v2]# docker run -p 1433 --rm --name=dev_sqlv2 sqlserver/v2
/bin/sh: 1: sqlcmd: not found
构建之初,并没有安装 sql-cmd tools. 回到构建之初的 dockerfile,安装 sqlcmd tools client.
构建镜像的时候,指定了 FROM 指令,接着运行命令来安装 sqlcmd tools client, 这份 tools client 会安装在容器里面吗,因为此时的 Docker 还没有启动起来。
但是通过潜入容器内部发现,sqlcmd 已经安装完毕了,其实是没有指定执行路径造成的。那么只要设定 PATH 路径即可。
[aaa@qq.com v2]# cat Dockerfile
FROM sqlserver/v1
MAINTAINER Lenis Huang "aaa@qq.com"
ENV PATH=${PATH}:/opt/mssql/bin:/opt/mssql-tools/bin
RUN mkdir /opt/sqlfiles
COPY ./DBSchemaInit.sql /opt/sqlfiles/DBSchemaInit.sql
CMD sqlcmd -S localhost,1433 -U sa -P 1QAZ2wsx3EDC. -i /opt/sqlfiles/DBSchemaInit.sql
但基于这份 Dockerfile 构建的容器,运行会报错:
[aaa@qq.com v2]# docker run -p 1433 --rm --name dev_sqlv2 sqlserver/v2
Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Login timeout expired.
Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : TCP Provider: Error code 0x2749.
Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : A network-related or instance-specific error has occurred while establishing a connection to SQL Server. Server is not found or not accessible. Check if instance name is correct and if SQL Server is configured to allow remote connections. For more information see SQL Server Books Online..
前提是并没有运行着的 sql server 实例。
#Dockerfile
FROM sqlserver/v1
MAINTAINER Lenis Huang "aaa@qq.com"
ENV PATH=${PATH}:/opt/mssql/bin:/opt/mssql-tools/bin
RUN mkdir /opt/sqlfiles
COPY ./DBSchemaInit.sql /opt/sqlfiles/DBSchemaInit.sql
RUN sqlservr
CMD sqlcmd -S localhost,1433 -U sa -P 1QAZ2wsx3EDC. -i /opt/sqlfiles/DBSchemaInit.sql
~
但这里直接运行起 sql server 来了。但修改为后台运行之后,依然报上面的错误:
RUN sqlservr &
因此我断定不是这问题,况且基于 sqlv1 已经自启动运行了。
在 google 上翻了一遍,发现这篇文章似乎有用:
https://www.handsonarchitect.com/2018/01/build-custom-sql-server-2017-linux.html
经过修改和调试,终于找到正确的方法了:
# Dockerfile
FROM sqlserver/v1
MAINTAINER Lenis Huang "aaa@qq.com"
ENV ACCEPT_EULA=Y
ENV SA_PASSWORD=1QAZ2wsx3EDC.
ENV PATH=${PATH}:/opt/mssql/bin:/opt/mssql-tools/bin
RUN mkdir sqlfiles
COPY DBSchemaInit.sql ./sqlfiles/DBSchemaInit.sql
COPY setup-database.sh ./sqlfiles/setup-database.sh
COPY entrypoint.sh ./sqlfiles/entrypoint.sh
RUN chmod a+x ./sqlfiles/setup-database.sh
RUN chmod a+x ./sqlfiles/entrypoint.sh
CMD bash ./sqlfiles/entrypoint.sh
# entrypoint.sh
echo 'starting database setup'
./sqlfiles/setup-database.sh &
/opt/mssql/bin/sqlservr
# setup-database.sh
echo 'please wait while database is starting up ...'
sleep 45s
echo 'try to connect to database in containder and create the sample db...'
/opt/mssql-tools/bin/sqlcmd -S localhost,1433 -U sa -P 1QAZ2wsx3EDC. -d master -i ./sqlfiles/DBSchemaInit.sql
echo 'sample db have been created!'
entrypoint.sh 中特别要注意的是最后一个命令一定是 sqlservr, 这是决定 docker 是否在前台一直运行,而不终止的决定性因素;setup-database.sh 中特别要注意的是对数据库实例是否已经启动的判断,这里方便演示只是写了强行休息 45秒,实际上应该判断 sqlservr 进程是否已经开启;而 DBSchemaInit.sh 要注意的是每段部署脚本是可重复执行的,反复执行不会累加。
作为数据库部署,每次构建新容器,要关注的便是编写增量部署脚本,以替代第一次的数据库初始化脚本 DBSchemaInit.sql.
5 如此循环达到持续集成和发布
在这种发布流程中,要思考的问题是,如何在生产环境发布。
按照 docker 发布数据库的这套流程,能发现和规避的问题是:
数据库发布脚本的一致性。
在dev, stg, uat,prod 都是使用了同一套脚本,并且脚本有错误可以及时调整。不至于在单发生产环境的时候,由于在 dev,stg, uat 测试环境发布时,没有及时校验出脚本逻辑上错误,或者因为环境的影响,比如大家随意的在 dev,stg,uat 环境创建数据库对象,而导致发布脚本本身没有得以验证正确性与完整性。
数据库发布的快捷性。
原本需要dev,stg,uat,prod 都重新部署一台新的服务器。之后,应用数据库发布脚本。现在只要竭尽全力构建一台正确可用的 docker 镜像,基于这份镜像,可以实现多个平台同时部署。而应用只需要指定相应的 doker 名即可。在多台集群环境中,这种部署手法给运维带来极大便利。还记得 Linux 的 ssh shell 嘛,发明远程无密登录就是为了能让运维在多个服务器之间穿梭,而不用一台台去安装软件了。在大数据当道,时不时要求上千台集群服务器的时下,docker 可以看做是一剂良药。
而这套流程,需要考虑的地方在于,生产环境的发布稍微不同。同样的发布脚本,但是数据库文件是游离于容器之外的。所以严格来说,不能以这样的方式去发布生产环境。必须从头至尾的,将数据库文件隔离于容器。在构建容器之时,先附加数据库文件到镜像,再应用发布脚本,最终构建发布版本的容器镜像。这样的构建脚本(Dockerfile)才具有可移植性。
2 构建【数据库文件游离于容器镜像之外】的 SQL Server Docker 发布步骤如下:
有了上面的经验,这次就简单很多了,就是对 Dockerfile 增加 Volume 指令的修改。本质上,是用 Volume 中的磁盘空间来存储数据库文件。
唯一不同的便是 dockerfile 的编写 和指定挂载的本地文件
# Dockerfile
FROM sqlserver/v1
MAINTAINER Lenis Huang "aaa@qq.com"
ENV ACCEPT_EULA=Y
ENV SA_PASSWORD=1QAZ2wsx3EDC.
ENV PATH=${PATH}:/opt/mssql/bin:/opt/mssql-tools/bin
RUN mkdir sqlfiles
COPY DBSchemaInit.sql ./sqlfiles/DBSchemaInit.sql
COPY setup-database.sh ./sqlfiles/setup-database.sh
COPY entrypoint.sh ./sqlfiles/entrypoint.sh
RUN chmod a+x ./sqlfiles/setup-database.sh
RUN chmod a+x ./sqlfiles/entrypoint.sh
VOLUME /sql/data
CMD bash ./sqlfiles/entrypoint.sh
加了 VOLUME 指令用来指定所有挂载的本地文件都被挂载到 /sql/data 上。
[aaa@qq.com v4]# mkdir -p /sql/data
[aaa@qq.com v4]# docker run -p 1433 --rm --name=dev_sqlv5 -v sqlvolume:/sql/data sqlserver/v5
[aaa@qq.com data]# docker volume inspect sqlvolume
[
{
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/sqlvolume/_data",
"Name": "sqlvolume",
"Options": {},
"Scope": "local"
}
]
在 sqlvolume 指定的目录下面,我们可以看到任何被放在 docker 中 /sql/data 目录下的文件。当然我们也可以自己创建一个 volume 挂载上去。