Docker 安装 SQL Server
大约 11 分钟约 3353 字
Docker 安装 SQL Server
简介
SQL Server 是微软推出的企业级关系型数据库管理系统,广泛应用于企业信息化系统中。通过 Docker 容器化部署 SQL Server,可以快速搭建开发测试环境,避免在宿主机上安装复杂的依赖,实现环境一致性。本文详细介绍如何使用 Docker 在 CentOS/Linux 环境中安装、配置和管理 SQL Server 容器。
容器化部署的优势
- 环境隔离:多个 SQL Server 实例互不影响
- 快速部署:几分钟内完成安装,无需手动配置
- 版本切换:不同版本(2019/2022)随时切换
- 数据持久化:通过数据卷保存数据库文件
- 易于迁移:容器可以在不同主机间快速迁移
拉取镜像
# SQL Server 2019 最新版
sudo docker pull mcr.microsoft.com/mssql/server:2019-latest
# SQL Server 2022 最新版
sudo docker pull mcr.microsoft.com/mssql/server:2022-latest
# 指定具体版本(推荐生产环境固定版本)
sudo docker pull mcr.microsoft.com/mssql/server:2019-CU27-ubuntu-20.04
# 查看已下载的镜像
sudo docker images | grep mssql
# 查看镜像详细信息
sudo docker inspect mcr.microsoft.com/mssql/server:2019-latest创建主机映射目录
# 创建 SQL Server 数据目录
mkdir -p /usr/local/docker/sqlserver
# 查看目录创建结果
ls -la /usr/local/docker/sqlserver修改主机映射目录权限
SQL Server 容器内的进程以非 root 用户(UID 10001)运行,因此宿主机上的映射目录必须赋予正确的权限,否则容器无法写入数据文件。
# 修改目录权限(SQL Server 容器内用户 UID 为 10001)
chown -R 10001:0 /usr/local/docker/sqlserver
# 验证权限
ls -la /usr/local/docker/ | grep sqlserver
# 输出应为:drwxr-xr-x 2 10001 root 4096 ...
# 如果遇到权限问题,可以临时赋予更宽松的权限(仅调试用)
chmod -R 777 /usr/local/docker/sqlserver运行容器
提示
SA_PASSWORD 环境变量已弃用。请改用 MSSQL_SA_PASSWORD。
# SQL Server 2019
# Enterprise:HMWJ3-KY3J2-NMVD7-KG4JR-X2G8G
# Enterprise Core:2C9JR-K3RNG-QD4M4-JQ2HR-8468J
# Standard:PMBDC-FXVM3-T777P-N4FY8-PKFF4
# Web:33QQK-WWQNB-G6T46-C86YB-TX2PH
# Developer(免费,功能完整,仅限开发测试):无密钥或使用任意密钥
docker run -p 1433:1433 --name sqlserver \
-e "ACCEPT_EULA=Y" \
-e "MSSQL_SA_PASSWORD=YourStrong@Passw0rd" \
-e "MSSQL_PID=HMWJ3-KY3J2-NMVD7-KG4JR-X2G8G" \
-e "MSSQL_COLLATION=Chinese_PRC_CI_AS" \
--restart=always \
-v /usr/local/docker/sqlserver:/var/opt/mssql \
-d \
mcr.microsoft.com/mssql/server:2019-latest# SQL Server 2022
docker run -p 1433:1433 --name sqlserver \
-e "ACCEPT_EULA=Y" \
-e "MSSQL_SA_PASSWORD=YourStrong@Passw0rd" \
-e "MSSQL_COLLATION=Chinese_PRC_CI_AS" \
--restart=always \
-v /usr/local/docker/sqlserver:/var/opt/mssql \
-d \
mcr.microsoft.com/mssql/server:2022-latest# Windows Docker Desktop 下挂载目录示例
docker run -p 1433:1433 --name sqlserver `
-e "ACCEPT_EULA=Y" `
-e "MSSQL_SA_PASSWORD=YourStrong@Passw0rd" `
-e "MSSQL_COLLATION=Chinese_PRC_CI_AS" `
--restart=always `
-v D:/docker/sqlserver/data:/var/opt/mssql/data `
-d `
mcr.microsoft.com/mssql/server:2022-latest参数说明
| 参数 | 说明 |
|---|---|
-e "ACCEPT_EULA=Y" | 确认接受最终用户许可协议,SQL Server 镜像的必需设置 |
-e "MSSQL_SA_PASSWORD=[YourStrong@Passw0rd]" | 指定 SA 密码,至少 8 个字符,需包含大小写字母和数字 |
-e "MSSQL_PID=HMWJ3-KY3J2-NMVD7-KG4JR-X2G8G" | 产品序列号(PID),决定 SQL Server 版本 |
-e "MSSQL_COLLATION=[SQL_Server_collation]" | 指定排序规则,默认 SQL_Latin1_General_CP1_CI_AS |
-p 1433:1433 | 端口映射:宿主机端口:容器端口 |
--name sqlserver | 容器名称,便于后续管理 |
--hostname sqlserver | 容器主机名,默认为容器 ID |
-d | 后台运行容器(守护进程模式) |
--restart=always | 容器退出后自动重启 |
-v /usr/local/docker/sqlserver:/var/opt/mssql | 数据卷挂载 |
SQL Server 版本密钥对照
| 版本 | 密钥 | 说明 |
|---|---|---|
| Enterprise | HMWJ3-KY3J2-NMVD7-KG4JR-X2G8G | 企业版,全部功能 |
| Enterprise Core | 2C9JR-K3RNG-QD4M4-JQ2HR-8468J | 企业核心版 |
| Standard | PMBDC-FXVM3-T777P-N4FY8-PKFF4 | 标准版 |
| Web | 33QQK-WWQNB-G6T46-C86YB-TX2PH | Web 版 |
| Developer | 任意密钥或不填 | 开发者版,免费,功能完整 |
其他常用环境变量
# 设置最大内存限制(MB)
-e "MSSQL_MEMORY_LIMIT_MB=4096"
# 设置时区
-e "TZ=Asia/Shanghai"
# 设置数据文件路径(容器内)
-e "MSSQL_DATA_DIR=/var/opt/mssql/data"
# 设置日志文件路径
-e "MSSQL_LOG_DIR=/var/opt/mssql/log"
# 启用 SQL Server Agent
-e "MSSQL_AGENT_ENABLED=True"
# 设置默认语言
-e "MSSQL_LCID=2052" # 中文简体查看运行状态
# 查看所有容器状态
sudo docker ps -a
# 查看运行中的容器
sudo docker ps
# 查看容器详细信息
sudo docker inspect sqlserver
# 查看容器资源使用情况
sudo docker stats sqlserver
# 查看容器进程
sudo docker top sqlserver
# 查看容器日志
sudo docker logs sqlserver
sudo docker logs --tail 50 sqlserver # 最后 50 行
sudo docker logs -f sqlserver # 实时跟踪查看错误日志
# 查看容器日志
docker logs --tail 50 --follow --timestamps sqlserver
# 进入容器查看 SQL Server 错误日志
docker exec -it sqlserver bash
cat /var/opt/mssql/log/errorlog | tail -20
# 搜索特定错误
docker exec -it sqlserver cat /var/opt/mssql/log/errorlog | grep -i "error"
docker exec -it sqlserver cat /var/opt/mssql/log/errorlog | grep -i "connection"
# 如果存在权限文件夹错误
# 执行:chown -R 10001:0 /usr/local/docker/sqlserver更改系统管理员密码
# 方法 1:使用 docker exec + sqlcmd
sudo docker exec -it sqlserver /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U SA \
-P "$(read -sp 'Enter current SA password: '; echo "${REPLY}")" \
-Q "ALTER LOGIN SA WITH PASSWORD='$(read -sp 'Enter new SA password: '; echo "${REPLY}")'"
# 方法 2:交互式修改
sudo docker exec -it sqlserver /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U SA -P "OldPassword" \
-Q "ALTER LOGIN SA WITH PASSWORD='NewStrong@Passw0rd'"
# 方法 3:使用环境变量重启容器(简单但不推荐生产环境)
docker stop sqlserver
docker rm sqlserver
docker run -p 1433:1433 --name sqlserver \
-e "ACCEPT_EULA=Y" \
-e "MSSQL_SA_PASSWORD=NewStrong@Passw0rd" \
-e "MSSQL_COLLATION=Chinese_PRC_CI_AS" \
--restart=always \
-v /usr/local/docker/sqlserver:/var/opt/mssql \
-d \
mcr.microsoft.com/mssql/server:2022-latest连接到 SQL Server
# 进入容器的 bash
sudo docker exec -it sqlserver bash
# 使用 sqlcmd 连接(容器内)
/opt/mssql-tools18/bin/sqlcmd -S localhost -U SA -P "YourStrong@Passw0rd"
# 从宿主机直接使用 sqlcmd 连接(需安装 mssql-tools)
sqlcmd -S 127.0.0.1,1433 -U SA -P "YourStrong@Passw0rd"
# 使用 Azure Data Studio / SSMS 连接
# 服务器地址:宿主机IP,1433
# 认证方式:SQL Server 身份验证
# 用户名:SA
# 密码:设置的 SA 密码# 常用 sqlcmd 命令
# 查看所有数据库
SELECT name FROM sys.databases;
GO
# 创建数据库
CREATE DATABASE MyDatabase;
GO
-- 查看数据库文件路径
SELECT name, physical_name FROM sys.database_files;
GO
-- 退出 sqlcmd
QUIT删除容器
# 停止容器
sudo docker stop sqlserver
# 删除容器(数据卷中的数据不受影响)
sudo docker rm sqlserver
# 强制删除运行中的容器
sudo docker rm -f sqlserver
# 如果要彻底清除(包括数据卷)
sudo docker rm -v sqlserver
# 注意:这会删除挂载的匿名卷,但不会删除绑定挂载的宿主机目录防火墙放行端口 1433
# 查看防火墙目前的放行端口列表
firewall-cmd --list-ports
# 添加防火墙放行端口(permanent 代表永久生效)
firewall-cmd --add-port=1433/tcp --permanent
# 重新加载防火墙(添加完放行端口一定要重新加载)
firewall-cmd --reload
# 验证端口已放行
firewall-cmd --list-ports
# 也可以使用 --add-service 方式(如果预定义了 ms-sql-s 服务)
firewall-cmd --add-service=ms-sql-s --permanent
firewall-cmd --reload
# 限制来源 IP(仅允许特定网段访问)
firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="1433" protocol="tcp" accept' --permanent
firewall-cmd --reload数据备份与恢复
# 备份数据库(在容器内执行)
docker exec -it sqlserver /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U SA -P "YourStrong@Passw0rd" \
-Q "BACKUP DATABASE MyDatabase TO DISK='/var/opt/mssql/backup/MyDatabase.bak' WITH INIT"
# 先创建备份目录
docker exec -it sqlserver mkdir -p /var/opt/mssql/backup
# 恢复数据库
docker exec -it sqlserver /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U SA -P "YourStrong@Passw0rd" \
-Q "RESTORE FILELISTONLY FROM DISK='/var/opt/mssql/backup/MyDatabase.bak'"
docker exec -it sqlserver /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U SA -P "YourStrong@Passw0rd" \
-Q "RESTORE DATABASE MyDatabase FROM DISK='/var/opt/mssql/backup/MyDatabase.bak' WITH MOVE 'MyDatabase' TO '/var/opt/mssql/data/MyDatabase.mdf', MOVE 'MyDatabase_Log' TO '/var/opt/mssql/data/MyDatabase_Log.ldf'"常见问题排查
# 容器启动后立即退出
docker logs sqlserver
# 常见原因:SA 密码不符合要求(需至少 8 位,含大小写和数字)
# 常见原因:目录权限不正确
# 常见原因:端口被占用
# 检查端口占用
ss -tlnp | grep 1433
# 如果被占用,更换映射端口
docker run -p 14330:1433 --name sqlserver ...
# 容器启动成功但无法连接
# 1. 检查防火墙
firewall-cmd --list-ports
# 2. 检查 SELinux
getenforce
# 3. 检查容器是否健康
docker inspect --format='{{.State.Health.Status}}' sqlserver
# 磁盘空间不足
df -h /usr/local/docker/sqlserver
docker system dfDocker Compose 编排
完整 Compose 配置
# docker-compose.yml — SQL Server 完整编排
version: '3.8'
services:
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest
container_name: sqlserver
ports:
- "1433:1433"
environment:
- ACCEPT_EULA=Y
- MSSQL_SA_PASSWORD=YourStrong@Passw0rd
- MSSQL_COLLATION=Chinese_PRC_CI_AS
- MSSQL_MEMORY_LIMIT_MB=4096
- TZ=Asia/Shanghai
volumes:
- sqlserver_data:/var/opt/mssql
- ./backup:/var/opt/mssql/backup
- ./scripts:/var/opt/mssql/scripts
restart: always
healthcheck:
test: /opt/mssql-tools18/bin/sqlcmd -S localhost -U SA -P "YourStrong@Passw0rd" -Q "SELECT 1" -No
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
networks:
- app-network
# 可选:SQL Server 监控
sqlserver-exporter:
image: awaragi/prometheus-mssql-exporter
container_name: sqlserver-exporter
ports:
- "9399:9399"
environment:
- SERVER=sqlserver
- USERNAME=SA
- PASSWORD=YourStrong@Passw0rd
depends_on:
sqlserver:
condition: service_healthy
networks:
- app-network
# 可选:Azure Data Studio Web(浏览器访问)
# 可以通过 Web 界面管理 SQL Server
volumes:
sqlserver_data:
driver: local
networks:
app-network:
driver: bridge初始化脚本
# scripts/init.sql — 容器启动后执行的初始化脚本
-- 创建数据库
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = 'MyAppDB')
BEGIN
CREATE DATABASE MyAppDB;
PRINT '数据库 MyAppDB 创建成功';
END
GO
USE MyAppDB;
GO
-- 创建登录用户
IF NOT EXISTS (SELECT name FROM sys.server_principals WHERE name = 'app_user')
BEGIN
CREATE LOGIN app_user WITH PASSWORD = 'AppUser@StrongPass123';
CREATE USER app_user FOR LOGIN app_user;
ALTER ROLE db_datareader ADD MEMBER app_user;
ALTER ROLE db_datawriter ADD MEMBER app_user;
PRINT '用户 app_user 创建成功';
END
GO
-- 创建示例表
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Users')
BEGIN
CREATE TABLE Users (
Id INT IDENTITY(1,1) PRIMARY KEY,
Username NVARCHAR(100) NOT NULL,
Email NVARCHAR(200) NOT NULL,
CreatedAt DATETIME2 DEFAULT GETUTCDATE(),
UpdatedAt DATETIME2 DEFAULT GETUTCDATE()
);
CREATE UNIQUE INDEX IX_Users_Username ON Users(Username);
CREATE UNIQUE INDEX IX_Users_Email ON Users(Email);
PRINT '表 Users 创建成功';
END
GO# 等待 SQL Server 启动完成后执行初始化脚本
#!/bin/bash
# scripts/wait-and-init.sh
echo "等待 SQL Server 启动..."
for i in {1..30}; do
if /opt/mssql-tools18/bin/sqlcmd -S localhost -U SA -P "YourStrong@Passw0rd" -Q "SELECT 1" -No > /dev/null 2>&1; then
echo "SQL Server 已就绪"
break
fi
echo "等待中... ($i/30)"
sleep 2
done
echo "执行初始化脚本..."
/opt/mssql-tools18/bin/sqlcmd -S localhost -U SA -P "YourStrong@Passw0rd" -i /var/opt/mssql/scripts/init.sql -No
echo "初始化完成"性能调优
SQL Server 容器性能优化
-- 查看当前配置
SELECT * FROM sys.configurations ORDER BY name;
-- 内存配置(容器环境下建议限制)
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
-- 最大服务器内存(MB),建议为容器内存的 70-80%
EXEC sp_configure 'max server memory', 3072;
RECONFIGURE;
-- 最小服务器内存
EXEC sp_configure 'min server memory', 512;
RECONFIGURE;
-- 最大并行度(容器 CPU 核心数较少时建议设为 1 或 2)
EXEC sp_configure 'max degree of parallelism', 2;
RECONFIGURE;
-- 查看当前内存使用
SELECT
physical_memory_in_use_kb / 1024 AS 'Memory Used (MB)',
total_physical_memory_kb / 1024 AS 'Total Memory (MB)',
available_physical_memory_kb / 1024 AS 'Available Memory (MB)'
FROM sys.dm_os_process_memory CROSS JOIN sys.dm_os_sys_info;
-- 查看缓冲池使用情况
SELECT
COUNT(*) AS cached_pages_count,
COUNT(*) * 8 / 1024 AS cached_size_MB,
CASE database_id
WHEN 32767 THEN 'ResourceDb'
ELSE DB_NAME(database_id)
END AS database_name
FROM sys.dm_os_buffer_descriptors
GROUP BY database_id
ORDER BY cached_size_MB DESC;
-- 查看最耗资源的查询
SELECT TOP 10
total_worker_time / execution_count AS avg_cpu_time_us,
total_elapsed_time / execution_count AS avg_duration_us,
execution_count,
SUBSTRING(st.text,
(qs.statement_start_offset / 2) + 1,
CASE WHEN qs.statement_end_offset = -1
THEN LEN(st.text)
ELSE (qs.statement_end_offset - qs.statement_start_offset) / 2
END) AS query_text
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
ORDER BY avg_cpu_time_us DESC;容器资源限制
# 限制容器资源使用
docker run -p 1433:1433 --name sqlserver \
-e "ACCEPT_EULA=Y" \
-e "MSSQL_SA_PASSWORD=YourStrong@Passw0rd" \
-e "MSSQL_MEMORY_LIMIT_MB=4096" \
--memory=6g \
--memory-swap=6g \
--cpus=4 \
--restart=always \
-v /usr/local/docker/sqlserver:/var/opt/mssql \
-d \
mcr.microsoft.com/mssql/server:2022-latest
# 查看容器资源使用
docker stats sqlserver --no-stream
# 查看容器资源限制
docker inspect sqlserver --format='{{.HostConfig.Memory}} {{.HostConfig.NanoCpus}}'关键知识点
- 部署类主题的核心不是"装成功",而是"稳定运行、可排障、可回滚"
- 同一个服务通常至少要关注版本、目录、端口、权限、数据、日志和备份
- Linux 问题经常跨越系统层、网络层、服务层和应用层
- 部署主题通常要同时看镜像、容器、卷、网络和宿主机资源
项目落地视角
- 把安装步骤补成可重复执行的清单,必要时写成脚本或配置文件
- 把配置目录、数据目录、日志目录和挂载点明确拆开
- 上线前检查防火墙、SELinux、时区、磁盘、系统服务和健康检查
- 固定镜像标签,记录端口、挂载目录、环境变量和自启动策略
常见误区
- 使用 latest 或未固定版本,导致环境不可复现
- 只验证启动成功,不验证持久化、开机自启和故障恢复
- 遇到问题先改配置而不是先看日志和依赖链路
- 使用 latest 导致结果不可复现
- 忽略 SA 密码复杂度要求导致容器启动失败
进阶路线
- 继续补齐 systemd、性能监控、安全加固和备份恢复
- 把单机操作升级成 Docker、Kubernetes 或 IaC 方案
- 建立标准化运维手册,包括巡检、扩容、回滚和灾备演练
- 继续补齐 Compose 编排、镜像瘦身、安全扫描和镜像仓库治理
适用场景
- 当你准备把 Docker 安装 SQL Server 真正落到项目里时,最适合先在一个独立模块或最小样例里验证关键路径
- 适合单机环境初始化、中间件快速搭建、测试环境验证和生产部署前准备
- 当服务稳定性依赖端口、权限、目录、网络和系统参数时,这类主题会直接影响成败
落地建议
- 固定版本号与镜像标签,避免"latest"带来的不可预期变化
- 把配置、数据、日志目录拆开管理,并记录恢复步骤
- 上线前确认端口、防火墙、SELinux、时区和磁盘空间
- 使用 Docker Compose 编排,便于版本管理和团队协作
排错清单
- 先查 systemctl、容器日志和应用日志,确认失败发生在哪一层
- 检查端口占用、目录权限、挂载路径和网络连通性
- 如果是新环境问题,优先对比与已知正常环境的差异
- 检查 SA 密码是否符合复杂度要求
复盘问题
- 如果把 Docker 安装 SQL Server 放进你的当前项目,最先要验证的输入、输出和失败路径分别是什么?
- Docker 安装 SQL Server 最容易在什么规模、什么边界条件下暴露问题?你会用什么指标或日志去确认?
- 相比默认实现或替代方案,采用 Docker 安装 SQL Server 最大的收益和代价分别是什么?
