Azure Pipeline SSH部署Docker容器后自动退出的问题咨询
容器通过Azure Pipeline SSH部署后自动退出的问题排查与优化方案
问题概述
通过Azure Pipeline完成应用容器镜像构建并推送到私有镜像仓库后,使用SSH任务连接目标VM执行docker run -d启动容器。容器能正常启动并监听端口,但运行一段时间后自动退出,容器日志显示gunicorn主进程收到SIGTERM信号后主动关闭。
排查分析
从日志和部署配置来看,docker run -d已指定后台运行容器,容器退出与SSH会话无关。核心原因是容器进程收到终止信号,可能的触发点包括:
- 容器内主进程未正确处理系统信号(比如PID 1进程的信号转发问题)
- 目标VM的系统进程管理工具(如systemd)或定时任务误杀容器进程
- 容器资源耗尽(但日志未体现OOM等相关信息)
解决方案
1. 确保容器进程以正确方式运行
检查Dockerfile的CMD/ENTRYPOINT配置,确保gunicorn以前台方式启动,避免使用&将进程放入后台(Docker需要主进程保持前台运行,否则会认为容器任务完成而退出)。示例正确配置:
# Dockerfile示例 CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "app:app"]
2. 配置Docker自动重启容器
在docker run命令中添加--restart always参数,让Docker在容器意外退出时自动重启:
docker run -d --restart always --name $(APPLICATION_NAME) -p 5000:5000 "$DOCKER_IMAGE"
3. 使用systemd管理容器生命周期
如果目标VM基于systemd(大多数Linux发行版默认),将容器注册为systemd服务,由系统负责监控和自动恢复,彻底避免进程被误杀或意外退出的问题:
修改Azure Pipeline的SSH任务命令如下:
echo "started executing commands" export DOCKER_IMAGE="$(DOCKER_CONTAINER_REGISTRY)/$(APPLICATION_NAME):$(APP_VERSION)" docker login -u $(azure_username) -p $(azure_password) $(DOCKER_CONTAINER_REGISTRY) docker pull $DOCKER_IMAGE # 停止并清理旧容器(如果存在) PREVIOUS_CONTAINER=$(docker ps -aq --filter "name=$APPLICATION_NAME") if [ ! -z "$PREVIOUS_CONTAINER" ]; then docker stop "$PREVIOUS_CONTAINER" || true docker rm "$PREVIOUS_CONTAINER" || true fi # 生成systemd服务文件 cat > /etc/systemd/system/$(APPLICATION_NAME).service << EOF [Unit] Description=$(APPLICATION_NAME) Container Service After=docker.service Requires=docker.service [Service] Restart=always ExecStart=/usr/bin/docker run --name $(APPLICATION_NAME) -p 5000:5000 "$DOCKER_IMAGE" ExecStop=/usr/bin/docker stop -t 10 $(APPLICATION_NAME) ExecStopPost=/usr/bin/docker rm -f $(APPLICATION_NAME) [Install] WantedBy=multi-user.target EOF # 重新加载systemd配置并启动服务 systemctl daemon-reload systemctl restart $(APPLICATION_NAME).service systemctl enable $(APPLICATION_NAME).service
4. 优化镜像的信号处理
使用tini作为容器的init进程,解决PID 1进程无法正确转发信号的问题。在Dockerfile中添加以下内容:
RUN apt-get update && apt-get install -y --no-install-recommends tini ENTRYPOINT ["tini", "--"] CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "app:app"]
更优实现方式
- 使用Docker Compose管理部署:将容器配置写入
docker-compose.yml,简化部署命令,同时便于扩展服务:
# docker-compose.yml version: '3.8' services: myapp: image: ${DOCKER_IMAGE} ports: - "5000:5000" restart: always
在SSH任务中执行docker-compose up -d完成部署。
- 替换SSH任务为专用部署工具:如果目标VM是Azure VM,可使用Azure Pipeline的
Azure VM Deployment任务,或者借助Ansible等配置管理工具实现更可靠的部署流程,避免直接执行SSH命令的维护成本。
内容的提问来源于stack exchange,提问作者Manish
相关产品推荐
相关产品推荐

