You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Podman部署后容器冻结,需手动重启才可正常运行

Podman容器部署后冻结问题的分析与解决

问题根源

从你的CI/CD流水线脚本来看,导致容器部署后冻结的核心问题有三个:

  1. 重复启停容器的冗余操作:脚本先在5001端口启动新容器,确认运行后,又执行stop、rm再重新在5000端口启动。这种重复启动会导致Podman的网络、进程资源未完全释放,干扰应用初始化流程,引发进程死锁或冻结。
  2. 固定等待时间的不可靠性:用sleep 10判断服务就绪,容器状态显示“运行”不代表内部应用服务真正启动完成,此时后续操作会打断应用初始化。
  3. 仅依赖容器状态检查:只用podman ps确认容器运行,未验证内部服务的可用性,导致误判服务就绪状态,后续操作触发未就绪服务的异常。

针对性解决方案

1. 重构容器部署流程,避免重复启停

直接在目标端口启动新容器,通过临时名称切换的方式替换旧容器,全程只启动一次新容器:
修改AzureCLI任务中的部署逻辑为:

set -e
echo 'Logging in to Azure...'
az login --service-principal -u $(AZURE_CLIENT_ID) -p $(AZURE_CLIENT_SECRET) --tenant $(AZURE_TENANT_ID)

echo 'Logging in to ACR...'
podman login pdspqptestcontainerregistry.azurecr.io -u $(AZURE_ACR_USERNAME) -p $(AZURE_ACR_PASSWORD)

export IMAGE_TAG=$(cat image_tag.txt | cut -d '=' -f2)
NEW_CONTAINER_NAME="pqp-backend-gunicorn-${IMAGE_TAG}"
OLD_CONTAINER_NAME="pqp-backend-gunicorn"

echo "Pulling the latest backend image..."
podman pull pdspqptestcontainerregistry.azurecr.io/pqp_be_gunicorn:${IMAGE_TAG}

echo "Starting new backend container ${NEW_CONTAINER_NAME} on port 5000..."
podman run -d --name=${NEW_CONTAINER_NAME} --restart=always -p 5000:5000 \
  -e FLASK_ENV=$(FLASK_ENV) -e ES_TOKEN=$(ES_TOKEN) \
  pdspqptestcontainerregistry.azurecr.io/pqp_be_gunicorn:${IMAGE_TAG}

# 轮询检查应用健康状态,替换固定sleep
echo "Waiting for application to be ready..."
MAX_RETRIES=20
RETRY_INTERVAL=5
RETRY_COUNT=0
# 替换为你的实际健康检查接口路径
HEALTH_CHECK_URL="http://localhost:5000/health"

while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
  if curl -f $HEALTH_CHECK_URL; then
    echo "Application is ready."
    break
  fi
  echo "Waiting for application... ($((RETRY_COUNT+1))/$MAX_RETRIES)"
  sleep $RETRY_INTERVAL
  RETRY_COUNT=$((RETRY_COUNT+1))
done

if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
  echo "Application failed to become ready."
  podman logs ${NEW_CONTAINER_NAME}
  podman stop ${NEW_CONTAINER_NAME}
  podman rm ${NEW_CONTAINER_NAME}
  exit 1
fi

# 平滑切换容器:停止旧容器,删除后重命名新容器
echo "Switching to new container..."
podman stop ${OLD_CONTAINER_NAME} || true
podman rm ${OLD_CONTAINER_NAME} || true
podman rename ${NEW_CONTAINER_NAME} ${OLD_CONTAINER_NAME}

# 后续清理逻辑保持不变
echo "Cleaning up old images in ACR, keeping the last 5..."
REPO="pqp_be_gunicorn"
IMAGES=$(az acr repository show-tags --name pdspqptestcontainerregistry --repository $REPO --orderby time_desc --output tsv | tail -n +6)
for IMAGE in $IMAGES; do
  az acr repository delete --name pdspqptestcontainerregistry --image $REPO:$IMAGE --yes
done

echo "Cleaning up old images locally, excluding the current image..."
podman images --format "{{.ID}} {{.Repository}}:{{.Tag}}" | grep 'pqp_be' | grep -v "${IMAGE_TAG}" | awk '{print $1}' | xargs -I {} sh -c 'podman rmi -f {} || true'

2. 给镜像添加健康检查

在你的Dockerfile中添加健康检查指令,让Podman自动监控内部服务状态:

# 根据你的应用调整健康检查命令,确保能准确判断服务可用性
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:5000/health || exit 1

添加后,podman ps会显示容器的healthy状态,此时再执行后续操作更可靠。

3. 移除不必要的镜像清理前置步骤

原脚本中先删除所有旧镜像再构建,可能导致构建过程中依赖缺失(如果有多层镜像依赖),建议保留最近的1-2个旧镜像,或者在构建完成后再清理旧镜像。

验证方法

  1. 运行优化后的流水线,部署完成后执行podman ps,确认容器状态为healthy(添加健康检查后)。
  2. 调用服务接口或执行健康检查curl命令,确认服务正常响应。
  3. 观察10-15分钟,确认容器不会进入冻结状态。

内容的提问来源于stack exchange,提问作者Martin Benko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:57:35