☰
用Docker Compose跑SQL Server:告别本地安装折磨的完整实践
2026/10/1 11:32:05 网站建设 项目流程

说实话,我之所以认真研究用 docker-compose 跑 sqlserver,完全是被本地安装折腾怕了。最早装 SQL Server 2012 的时候,光下载安装包就花了大半天,中间还蹦出个“句柄无效”的报错,卸载重装了两次才过。后来换了电脑,又得从头折腾一遍,安装包下载、环境变量、防火墙、配置管理器,一套流程走下来,小半天就没了。直到我改成 docker-compose 启动 sql-server,这个体验才彻底翻转过来:一份配置文件,一条启动命令,干干净净的容器实例就跑起来了,用完还能一键销毁,完全不污染宿主机。

这篇内容不是什么高深教程,就是我把 sqlserver 容器化之后沉淀下来的完整实操记录。适合在本地做开发调试、跟着课程学数据库、搭 CI 验证脚本、或者临时给团队起一套测试环境的人参考。如果你也有过被 SQL Server 安装向导折磨的经历,这篇文章能让你少走很多弯路。

1. 为什么我最终选了 docker-compose:本地安装的坑与方案对比

很多人觉得 SQL Server 嘛,到官网下个安装包,一路 Next 不就行了?真上手过的人都知道,这套流程远没那么顺滑。尤其当你的主力开发机是 macOS 或者 Linux,想在本地跑一套 SQL Server,传统安装方式基本是死路一条。即使是 Windows 环境,多版本共存、卸载残留、服务配置这些坑也够喝一壶的。

1.1 本地装 SQL Server 的三大痛点

第一个痛点是安装包体积和下载速度。SQL Server 的安装镜像动辄几个 G,在网速不理想的时候,光是下载就足够劝退。更别提安装过程中还经常出现各种奇怪的报错,热搜词里那个“句柄无效 HRESULT”的异常,我当年也撞到过,最后只能靠卸载重装解决,折腾到怀疑人生。

第二个痛点是环境残留和版本冲突。同一台机器上装过 2012 再装 2019,或者装过默认实例再装命名实例,服务列表、注册表、配置管理器里的条目会非常混乱。卸载时你以为卸干净了,下次装新版照样可能因为旧组件残留导致失败。你甚至能找到专门用于清理 SQL Server 残留的第三方工具,光这一点就说明问题有多普遍。

第三个痛点是跨平台支持太差。虽然微软后来出了 SQL Server on Linux 版本,但安装步骤依然不轻松,依赖库、权限、配置步骤一大堆。如果你用的是 Apple Silicon 芯片的 Mac,本地安装这条路更是基本走不通,只能退而求其次连远程服务器。我见过不少新同事入职第一天,光装开发环境就耗掉一整天,最后卡在 SQL Server 上求助。

1.2 同类方案横向对比:纯 docker run 与 docker-compose 的取舍

有人可能会说,既然要用容器,直接docker run一条命令不就行了,为什么还要多此一举引入 docker-compose?我最初也是这么干的,但用了几次就发现问题了。docker run那条命令本身就长得离谱,镜像名、环境变量、端口映射、数据卷、内存限制全堆在一块,复制到终端里换行逻辑混乱,想改一个参数还得在长串命令里找半天。更麻烦的是,这种命令不容易共享给同事,也不方便沉淀到项目仓库里。

docker-compose 的核心价值在于把“环境配置”变成一份可以提交到 Git 的声明式文件。你只需要维护一个docker-compose.yml,里面写了什么镜像、什么端口、什么数据卷、什么环境变量,团队里的任何人拉下来执行一句docker compose up -d,就能得到一套完全一致的 SQL Server。这比发一段复杂命令让同事自己去复制粘贴要可靠得多,也比写一篇长篇安装文档更省心。

从运维角度看,docker-compose 对容器生命周期的管理也更友好。docker compose down可以整体停掉并删除,docker compose restart可以重启服务,配合卷挂载还能保证删容器不删数据。这种体验接近“用完即焚,需要再来”,非常契合开发测试环境的诉求。

1.3 这套方案适合谁,又不适合谁

先说明一点,这套容器化方案也有边界,不是所有场景都适合。它最适合的是三类人:第一类是开发人员,本地需要一台随时可用的 SQL Server 实例做调试;第二类是测试和 CI 环境维护者,需要在流水线里快速拉起、销毁数据库实例;第三类是学习数据库的新手,想快速体验 SQL Server 而不想被安装过程劝退。

如果你追求的是生产环境的高可用、极限性能或者复杂的 Windows 集成功能,比如 SQL Server Agent 任务、SSIS、Reporting Services、AlwaysOn 可用性组等,那容器化方案还达不到直接顶上线的程度。生产环境仍然建议使用云数据库或者专门的数据库服务器,容器用于开发和测试更稳妥。认清边界,才能用对工具。

2. 动手前准备:镜像选型、环境检查和工具搭配

写配置文件之前,有几件事需要先定下来。最核心的是选哪个版本的 SQL Server 镜像,其次要确认宿主机环境满足容器运行条件,最后是准备一套顺手的连接工具。这几步看着不起眼,但选错了镜像版本或者忽略了环境限制,后面启动时大概率会翻车。

2.1 镜像版本怎么选:2022 还是 2019,Developer 还是 Express

微软官方维护的 SQL Server 容器镜像托管在mcr.microsoft.com/mssql/server仓库下,目前最常用的两个大版本是 2019 和 2022。我个人建议新项目直接用 2022,毕竟功能更新、支持周期更长;如果你的生产库还停留在 2019,为了本地与线上版本保持一致,也可以用 2019 镜像。两者在容器化部署方式上完全一样,差别只在 SQL Server 版本功能。

另一个关键选项是MSSQL_PID环境变量,也就是产品版本。开发测试建议用Developer,这个版本拥有企业版级别的全部功能,而且免费,没有 180 天过期的坑。Express版本功能受限,数据库单库上限是 10GB,除非你刻意模拟 Express 的限制,否则没有理由选它。Standard和Enterprise需要许可证,一般只在测试商业版特性时才需要指定。

这里有个容易踩的坑:某些第三方教程会让你拉取mcr.microsoft.com/mssql/server:latest这个标签。latest的指向有时并不直观,建议直接用明确的版本标签,比如2022-latest。这样拉了哪个版本自己心里有数,排障时也容易定位。

2.2 宿主机环境检查:内存、引擎与端口占用

在动手之前,先用一条命令确认 Docker 环境本身是健康的。打开终端执行docker version,确认 Docker Engine 版本比较新。然后执行docker compose version,确认识别到了 compose 插件。这里顺便说一句,新版 Docker 已经内置了docker compose子命令,如果你还在用需要单独下载的旧版docker-compose,建议尽早迁移,命令格式基本不变,但性能和兼容性更好。

内存是启动 SQL Server 容器最关键的硬指标。SQL Server 进程要求至少 2GB 可用内存,否则容器启动后会立刻退出,日志里会明确提示“This program requires a machine with at least 2 gigabytes of RAM”。如果你的开发机只有 8GB 内存,还同时在跑 IDE、浏览器和一堆容器,务必给 SQL Server 预留足够的额度,或者在 compose 里显式限制容器内存。

端口方面要检查 1433 是否被占用。宿主机上如果已经装了 SQL Server 或者别的服务占了这个端口,容器启动时会报bind: address already in use。解决方案很简单,把宿主端口改成一个不冲突的数值,比如14330:1433,连接时连 14330 即可。

2.3 连接工具的搭配推荐

容器本身只是数据库服务,真正干活还得靠客户端工具。我经常被问到用什么连 SQL Server 比较好,这里列一张简单的对比表,供不同需求的人参考。

工具平台支持特点适用场景
SSMSWindows功能最全,数据库管理运维能力强DBA、Windows 用户深度管理
Azure Data StudioWin/macOS/Linux轻量、跨平台、适合写查询和脚本开发调试、Mac/Linux 用户首选
DBeaverWin/macOS/Linux通用型客户端,支持多种数据库需要同时管理多种数据库的人
sqlcmd容器内/命令行轻量命令行工具,适合脚本和自动化容器内快速查询、CI 流水线

如果你在网上搜过“sqlserver 图形化工具”这个词,大概率会看到上面几个名字。我的组合是:日常写查询用 Azure Data Studio,需要精细管理实例配置时换 SSMS,自动化脚本里用 sqlcmd。三个工具身份认证方式都能直接用sa账号连接,容器启动后填入账号密码就能干活。

3. docker-compose.yml 逐行拆解:环境变量、端口与数据卷

到底该怎么写那份关键的docker-compose.yml?这一节我会把配置文件里的每一行都拆开讲清楚,保证你拿回去能直接改、直接跑。同时还会解释为什么这些配置要这么写,避免照抄之后不知道在调什么。

3.1 一份可以直接抄的配置文件

先给出一份完整的、经过我实测的配置文件,然后再逐段解释。直接用这份文件能省掉很多摸索时间,但对每一行的含义还是要了解清楚。

services: sqlserver: image: mcr.microsoft.com/mssql/server:2022-latest container_name: mssql-dev environment: ACCEPT_EULA: "Y" MSSQL_SA_PASSWORD: "YourStrong!Passw0rd" MSSQL_PID: "Developer" TZ: "Asia/Shanghai" ports: - "1433:1433" volumes: - mssql-data:/var/opt/mssql - ./backup:/backup mem_limit: 4g cpus: 2 restart: unless-stopped volumes: mssql-data:

这里我没有写version字段,因为新版 docker compose 已经把它标记为 obsolete,写上也只是为了兼容旧工具,会额外弹提示,所以不写更干净。三个环境变量是启动 SQL Server 容器必须提供的,一个是ACCEPT_EULA,一个是MSSQL_SA_PASSWORD,另外建议显式指定MSSQL_PID。下面逐个说。

3.2 三个关键环境变量的含义与密码策略

ACCEPT_EULA用来接受微软的最终用户许可协议,必须设置为Y,否则容器会拒绝启动。这个变量没什么技术含量,但它提醒你一件事:SQL Server 虽然被容器化,但许可规则没有变,开发和测试用 Developer 版本也要遵守协议条款。

MSSQL_SA_PASSWORD是超级管理员sa的初始密码。这个密码必须满足 SQL Server 的强密码策略,至少 8 位,同时包含大写字母、小写字母、数字和符号四种字符中的三种。不满足要求的话,容器第一次初始化时就会失败,日志里能看到密码策略检查不通过的错误。我见过很多人踩这个坑,明明镜像和端口都没问题,就是密码不够复杂导致容器反复重启。

这里有个安全层面的补充建议:密码不要硬编码在docker-compose.yml里。虽然开发环境问题不大,但文件一旦提交到 Git,密码就等于公开了。更稳的做法是使用环境变量插值,把密码放在项目根目录的.env文件中,然后配置里写成MSSQL_SA_PASSWORD: "${SA_PASSWORD}",.env文件加进.gitignore。这样既能保证配置可共享,又不会泄露敏感信息。

MSSQL_PID用来指定产品版本,上面已经提过,开发测试直接用Developer。如果不设置这个变量,默认值正好就是 Developer,但显式写出来更清晰,团队其他人看到配置时能立刻理解当前实例的版本定位。

3.3 卷设计:具名卷、绑定挂载与备份目录规划

卷设计是整个配置里最值得花心思的部分,因为数据库容器最怕“数据跟着容器走”。如果容器被删,里面的数据库文件也跟着没了,那损失是灾难性的。

/var/opt/mssql是 SQL Server 在容器内保存数据文件和日志文件的默认目录。我在配置里把它挂载为一个具名卷mssql-data。具名卷由 Docker 管理,存放在 Docker 的数据目录下,数据不会因为容器删除而消失。相比绑定挂载,具名卷在 Windows 和 macOS 环境下的性能更好,也避开了文件权限的一系列坑。下次重新docker compose up,新容器会自动复用这个卷,之前建的库都还在。

备份目录我用的是绑定挂载,把宿主机当前目录下的./backup直接映射到容器内的/backup。这么做的原因是备份文件需要能被宿主机直接访问,方便随后拷贝、上传或者拿去做还原测试。如果也塞进具名卷,你想把备份文件拷出来还得额外绕一层docker cp,非常不方便。

还有一个细节:如果使用绑定挂载到宿主机目录,SQL Server 容器进程对目录需要有写权限。Linux 下如果遇到权限拒绝,可以在宿主机上执行chmod -R 755或者干脆用chown调整目录归属。Windows 和 macOS 下 Docker Desktop 的文件共享机制一般能自动处理,问题不大。

4. 实操全流程:从创建目录到连接查询

配置理解到位之后,实际操作就很快了。从创建项目目录到成功连上数据库,正常情况五分钟就能搞定。这一节带你完整走一遍流程,包括启动、验证、连接三个环节。

4.1 目录结构与启动命令

先创建一个工作目录,比如~/docker/mssql-dev,然后在这个目录下添加两个子目录:backup用于放备份文件,另外把上面的docker-compose.yml放进来。结构大概是这样:

mssql-dev/ ├── docker-compose.yml ├── backup/ └── .env

如果你决定用.env管理密码,就在目录下创建.env文件,内容类似SA_PASSWORD=YourStrong!Passw0rd,然后 compose 文件里的密码字段改成${SA_PASSWORD}。改完之后,在项目目录下执行启动命令:

docker compose up -d

第一次执行会从微软镜像仓库拉取镜像,这一步的耗时取决于网络状况。镜像大概 1.5GB 左右,如果拉取速度感人,可以检查 Docker 是否配置了镜像加速器。拉取完成后,compose 会创建并启动容器。整个过程里不需要手动去创建数据卷,具名卷会自动创建;不需要手工指定网络,compose 会为项目创建一个默认网络。

4.2 容器状态检查与启动日志解读

容器启动之后别急着连,SQL Server 初始化需要一点时间。执行docker compose ps查看状态,正常情况下STATUS列应该是Up。然后查看日志确认初始化完成:

docker compose logs -f sqlserver

日志中出现类似这样的一行,说明实例已经准备好接受连接了:

SQL Server is now ready for client connections. This is an informational message; no user action is required.

这段日志非常重要。很多人看到容器状态是 Up 就立刻去连,结果提示连接被拒绝,其实就是因为实例还在启动中,还没监听 1433 端口。多等十几秒再看日志,基本就解决了。

启动过程里还有个容易忽视的信号:如果你在日志里看到不致命的警告,比如SQL Server is attempting to register a Service Principal Name,不用紧张,那是容器环境下常见的正常消息,不会影响使用。

4.3 三种方式连接验证:命令行、图形工具与 JDBC

连接验证我建议先走命令行,因为最直接、最少依赖。SQL Server 2022 容器镜像自带 sqlcmd 工具,注意新版路径已经变成了/opt/mssql-tools18/bin/sqlcmd,老教程里常见的/opt/mssql-tools/bin/sqlcmd在 2022 镜像里已经不存在了。

可以从容器外部执行这么一条命令,直接进入容器内跑查询:

docker exec -it mssql-dev /opt/mssql-tools18/bin/sqlcmd \ -S localhost -U sa -P 'YourStrong!Passw0rd' -C \ -Q "SELECT @@VERSION"

注意-C参数,它表示信任服务器证书。sqlcmd 18 及配套的 ODBC Driver 18 默认要求加密连接,不加这个参数,连接会被 TLS 证书验证拦下来,报错信息里会出现 SSL Provider 之类的字样。网上很多老教程没提这个变化,导致不少人照着敲命令却连不上。

图形化工具连接更简单。打开 Azure Data Studio,新建连接,服务器填localhost,如果改了宿主端口就填localhost,14330,用户名为sa,密码填设置的密码。连接成功后,左侧就能看到系统数据库列表。

如果你用的是 IntelliJ IDEA 配 JDBC 连这个实例,注意连接串要带着加密参数,参考格式如下:

jdbc:sqlserver://localhost:1433;encrypt=true;trustServerCertificate=true;databaseName=master

encrypt=true和trustServerCertificate=true这两个参数缺一不可。IDEA 里经常会遇到自动下载 Microsoft JDBC 驱动失败的问题,实际上 Maven 仓库里这个驱动是可以正常访问的,多试几次或者手动把mssql-jdbc的 jar 包放进依赖就行,问题多半出在网络,而不是驱动本身。

5. 数据持久化与备份恢复:别让数据跟着容器跑

容器用起来爽,但数据安全问题始终要摆在第一位。我见过不少同事用了容器以后懒得管备份,直到某天不小心执行了docker compose down -v,卷一起删掉,才发现悲伤的故事已经无法挽回。这一节专门讲备份、还原和数据卷的规划。

5.1 备份数据库到宿主机指定目录

备份逻辑其实很简单:在容器内执行标准的BACKUP DATABASE语句,目标路径写成我们映射过的/backup目录即可。由于/backup已经绑定挂载到宿主机,备份文件会直接落在宿主机上。

先用 sqlcmd 验证一下备份能正常执行,假设有一个业务库叫TestDB:

docker exec -it mssql-dev /opt/mssql-tools18/bin/sqlcmd \ -S localhost -U sa -P 'YourStrong!Passw0rd' -C \ -Q "BACKUP DATABASE [TestDB] TO DISK = N'/backup/TestDB.bak' WITH FORMAT, INIT;"

执行成功后,去宿主机./backup目录下就能看到TestDB.bak文件。FORMAT参数会重新初始化备份介质,避免旧备份影响;INIT表示覆盖同名文件。如果哪天需要把这个备份文件发给同事,直接拿它走即可。

更规范一点的做法是结合定时任务做自动备份,宿主机上可以写一个简单的 cron 任务,定时执行 docker exec 触达备份命令。开发环境能自动做全量备份,已经很够用了。

5.2 还原数据库的常见报错与修复

还原比备份稍微麻烦一点,主要是两个经典问题:文件路径和名称冲突。先查看备份文件里的逻辑文件名:

docker exec -it mssql-dev /opt/mssql-tools18/bin/sqlcmd \ -S localhost -U sa -P 'YourStrong!Passw0rd' -C \ -Q "RESTORE FILELISTONLY FROM DISK = N'/backup/TestDB.bak';"

这一步会列出备份内的逻辑文件名,比如TestDB和TestDB_log。还原时要通过MOVE参数把它们重新定位到/var/opt/mssql/data目录下,否则会尝试往备份文件原来所在的路径写,默认不存在就报错。

一个典型的还原语句长这样:

RESTORE DATABASE [TestDB_Restored] FROM DISK = N'/backup/TestDB.bak' WITH MOVE 'TestDB' TO '/var/opt/mssql/data/TestDB_Restored.mdf', MOVE 'TestDB_log' TO '/var/opt/mssql/data/TestDB_Restored_log.ldf', REPLACE;

REPLACE参数可以覆盖同名数据库,省掉先删库的步骤。如果还原时报“数据库正在使用”,通常是目标库还连着活跃会话,可以先执行ALTER DATABASE [TestDB_Restored] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;,再重新还原。

5.3 数据卷层面的备份策略与存储空间规划

数据库层面的备份之外,还有个更粗粒度的思路:直接备份整个数据卷目录。对于开发环境,这是一种简单的应急手段。找一下具名卷的实际位置,Linux 下可以执行docker volume inspect mssql-dev_mssql-data查看挂载点,然后把整个目录拷走。但注意这种做法在做物理备份时不一定保证一致性,数据库引擎仍在运行,直接拷贝 MDF 和 LDF 文件有风险。应急可以,常态化还是建议走 SQL Server 自身的备份命令。

关于存储空间规划,这里想多说几句。搜索热词里有一条“sqlserver 单表上亿存储空间太大”,这个话题和容器环境也有关联。SQL Server 数据库文件默认是自动增长的,但每次增长的幅度如果设置得不合理,上亿行的表会让 MDF 文件频繁扩展,既占空间又影响性能。建议在容器里给数据文件提前规划好初始大小,并用MAXSIZE限制增长上限。例如:

ALTER DATABASE [TestDB] MODIFY FILE (NAME = 'TestDB', SIZE = 10GB, FILEGROWTH = 512MB, MAXSIZE = 50GB);

然后把/var/opt/mssql挂载到宿主机的高性能磁盘上,避免把数据卷放在空间不足的系统分区里。容器帮你省去安装流程,但数据库本身的体量管理,还是得按数据库的规矩来。

6. 资源控制与性能调优:让 SQL Server 学会“克制”

SQL Server 这个进程在资源使用上相当“贪婪”,如果不主动限制,它会把宿主机的大部分内存都纳入自己的缓冲池。这在容器环境里是个必须处理的问题,否则你开发机上其他程序会被拖到卡顿。docker-compose 提供了简单的资源限制参数,用上之后体验会好很多。

6.1 内存限制:为什么必须设置 mem_limit

如果你只给 SQL Server 设置一个参数,那一定选mem_limit。如果不限制,SQL Server 会动态占用宿主机的绝大部分空闲内存,即便你的库只有几十 MB 数据,它也会把内存预留给未来的数据页使用。在开发机上跑这套容器,同时还要开浏览器、IDE、Docker 里其他容器,内存瞬间告急。

我通常给 SQL Server 容器分配宿主总内存的一半左右。8GB 内存的开发机给4g,16GB 的给8g。注意不要低于 2GB,否则 SQL Server 启动时会因为不满足最低内存需求直接退出。

services: sqlserver: mem_limit: 4g

设了mem_limit之后,SQL Server 也会在这个上限内自行管理缓冲池大小,不需要再手动配置max server memory。运维上省心很多。

6.2 CPU 限制、时区设置与存储考量

CPU 限制也一样重要,不过通常没那么紧急。cpus: 2表示容器最多使用两个 CPU 核心。开发场景下数据库查询量不大,两个核心绰绰有余。如果你的开发机本身核数不多,也可以设成cpus: 1,代价只是复杂查询会更慢。

时区是个经常被忽略的细节。SQL Server 容器默认使用 UTC 时间,而我们在东八区,查询GETDATE()的时候会看到比本地时间慢 8 小时。解决方案有三种:一是配置里加上TZ: "Asia/Shanghai"环境变量,二是把宿主机的/etc/localtime以只读方式挂载到容器,三是在连接后手动执行SET TIMEZONE类逻辑。最省事的就是直接配置TZ,这也是我在示例配置里写好的做法。

最后说一下存储性能的考量。如果你要在容器里跑比较重的查询,建议把数据卷放在 SSD 上,尤其是日志文件所在的 LDF,IO 延迟影响会非常明显。Docker Desktop 在 macOS 和 Windows 上默认使用虚拟磁盘,性能比原生 Linux 环境略差,但对开发调试来说完全够用。真到了追求性能的阶段,就该考虑把数据库部署到专用服务器或云数据库上了。

7. 常见问题排查:我踩过的坑与速查表

容器化部署虽然省心,但也不是没有坑。这一节把我在实际使用中踩过、或者身边同事经常碰到的问题整理出来,按现象、原因、解决方案的顺序列成速查表,方便你遇到问题时直接对照。

7.1 起不来:内存不足、端口占用与密码不达标

容器启动后马上退出,或者反复重启,最常见的有三个原因。

内存不足是最经典的。宿主机内存不够 2GB,或 Docker 分配的内存不够,SQL Server 会在日志里打印明确的提示。解决方案很直接:释放内存、加内存,或者在 Docker Desktop 设置里调大分配给虚拟机的内存。

端口冲突也很常见。docker compose up -d执行后如果提示bind: address already in use,说明宿主机 1433 端口已经被占用。跑一下lsof -i :1433(Linux/macOS)或者netstat -ano | findstr 1433(Windows)找到占用进程,然后要么停掉它,要么把 compose 里端口映射改成14330:1433。

还有一个原因就是 SA 密码不满足强密码策略。启动日志里如果出现Password policy check failed,直接换一个包含大小写字母、数字和符号的强密码即可。

7.2 连不上:sqlcmd 加密参数、防火墙与 IPv6 问题

容器明明起来了,客户端却连不上,这是第二大类问题。新版本 sqlcmd 和 ODBC Driver 18 默认加密,导致连接时报证书相关的 SSL 错误,解决方法是加上-C参数或者连接串里加trustServerCertificate=true。这个问题我前面已经强调过,这里再次单列,因为它真的太常见了。

另一个容易忽略的是防火墙。如果你在远程服务器上用 Docker 跑 SQL Server,即使容器端口映射正常,云服务商的安全组或本机防火墙没有放行对应端口,连接一样会被拦截。在云服务器上排查问题时,先确认安全组入站规则放行了 1433(或自定义端口),再检查宿主机防火墙。

IPv6 相关的坑也值得提一下。某些环境下 DNS 解析或客户端默认尝试 IPv6 回环地址,可能导致连接超时。如果客户端连接时指定localhost失败,但指定127.0.0.1成功,可以尝试在 hosts 里把关 mapping,或者直接连接 IP 地址。

7.3 数据与时间相关的补充问题

数据库时间跟本地差 8 小时的问题,前面已经给了解决方案。这里补充一个场景:如果你在容器里创建表时发现默认排序规则对中文支持不友好,可以在首次启动时通过环境变量MSSQL_COLLATION指定排序规则,比如Chinese_PRC_CI_AS。这个参数必须在容器初始化之前设置,数据库文件建好之后再改排序规则会非常麻烦,所以一开始就定好是关键。

另外两个热词也顺带回应一下。一个是“sqlserver 字符串转数字”,在 T-SQL 里可以用TRY_CAST或TRY_CONVERT,比如SELECT TRY_CAST('123' AS INT)安全转换,转换失败会返回 NULL 而不是报错,这是我很推荐的方式。另一个是“sqlserver 多行合并成一行”,用STRING_AGG函数就能实现,例如SELECT STRING_AGG(name, ',') FROM sys.databases;会把所有库名用逗号拼接成一行。这两个技能点配合 docker 容器里的实机练习,上手会非常快。

关于这个方案,我最后的一些体会

如果你问我现在给一个从零开始学 SQL Server 或者需要在本地起一套开发库的人推荐什么安装方式,我大概率直接把这份 compose 文件甩过去。从实际使用的角度看,docker-compose 把安装、启动、销毁、重来这几个动作全部标准化了,无论换机器还是换同事,环境一致的代价都降到最低。

实际跑下来最爽的一个场景是:团队新来了一个实习生,之前从没装过 SQL Server。我把项目目录给他,他执行docker compose up -d,然后打开 Azure Data Studio 连上去,全程不到三分钟。这就是基础设施代码化的好处,不用反复口述安装步骤,一份配置文件就把环境描述清楚了。

最后分享一个小技巧。如果你需要在本地同时维护多个版本的 SQL Server,可以通过多个 compose 文件或者端口映射来区分,比如 2019 映射到 14330,2022 映射到 14331。开发时想切换版本,只需要连接不同端口即可,不用像过去那样卸载安装再重启大半天。这种做法我用了很久,体验非常稳定,值得你试试。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询