Docker镜像Shell脚本问题:启动MSSQL后执行数据导入,服务随即停止
问题根源分析
你遇到的核心问题是Docker容器的生命周期和主进程绑定——当容器的主进程(也就是你的shell脚本)退出时,容器会直接停止,后台运行的sqlservr进程也会被一并终止。
你的脚本里用了exec /opt/mssql/bin/sqlservr &,把SQL Server放到后台运行,然后执行完数据导入步骤后,脚本就直接结束了,这时候Docker会认为主进程已退出,自然就停掉了整个容器,包括后台的SQL Server。
修复方案
我们需要让脚本在完成初始化后,持续保持运行,直到SQL Server进程本身退出。这里有个更可靠的修改版本:
#!/bin/bash database=myDB password=myPw # 启动SQL Server到后台运行,并记录它的进程ID /opt/mssql/bin/sqlservr & sqlservr_pid=$! # 替换固定sleep,循环检查SQL Server是否就绪(比固定等待更可靠) echo "Waiting for MSSQL server to become ready..." until /opt/mssql-tools/bin/sqlcmd -S 0.0.0.0 -U sa -P $password -Q "SELECT 1" > /dev/null 2>&1; do sleep 2 done # 执行数据初始化 echo "Starting data import..." /opt/mssql-tools/bin/sqlcmd -S 0.0.0.0 -U sa -P $password -i ./init.sql # 等待后台的SQL Server进程,让脚本持续运行(容器不会退出) wait $sqlservr_pid
关键改动说明
- 去掉了
exec:exec会替换当前shell进程,结合&虽然能后台启动SQL Server,但后续脚本结束时还是会导致容器终止 - 记录SQL Server的PID(
$!代表最后一个后台进程的ID):方便后续用wait命令追踪它的状态 - 用循环替代固定
sleep:不同环境下SQL Server启动速度不同,循环检查连接能确保初始化操作在服务就绪后才执行,避免导入失败 - 最后用
wait $sqlservr_pid:让脚本一直等待SQL Server进程,这样容器的主进程(脚本)会持续运行,直到SQL Server本身停止,完美贴合Docker的运行逻辑
内容的提问来源于stack exchange,提问作者Kristof Plennings
相关产品推荐
相关产品推荐

