You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何动态检测docker-compose是否启动/重启容器?是否有terraform plan类预览?

解决Docker Compose的两个需求:预览操作与判断容器启动/重启状态

针对你提到的两个问题,我整理了几个实用且相对优雅的方案,分别对应预览操作和动态判断容器状态:

一、类似Terraform Plan的预览功能:提前知道Docker Compose将要执行的操作

Docker Compose(尤其是v2版本)提供了直接的方式来预览up命令会触发的变更,不需要实际执行容器操作:

  • 使用docker compose up --dry-run命令
    这个参数会模拟执行up流程,输出所有将要进行的操作,比如哪些容器会被创建、启动、重启,哪些容器状态不会变化。示例输出类似:

    Container my-app-1 Creating
    Container my-db-1 Restarting
    Container redis-1 Running (unchanged)
    

    注意:这个功能在Docker Compose v2.10.0+版本中正式支持,如果你还在使用v1(docker-compose命令),建议升级到v2;如果暂时无法升级,也可以用docker-compose config --dry-run结合配置差异分析,但前者体验要好得多。

  • 额外技巧:结合--quiet减少冗余输出
    如果你只关心有变更的容器,可以加上--quiet参数,这样只会输出需要变更的容器名称:

    docker compose up --dry-run --quiet
    

二、动态判断指定容器是否被本次up启动/重启

要区分容器是本来就运行的,还是本次up才启动/重启的,有几种相对优雅的实现方式:

方案1:提前记录容器状态,执行后对比

这是最直观且准确性高的方法,通过在up前后分别获取容器的状态和启动时间,进行对比:

  1. 执行up前,记录目标容器的状态和启动时间
    比如针对名为my-app的服务,执行:

    # 获取容器ID(如果服务有多个实例,需调整逻辑遍历所有实例)
    CONTAINER_ID=$(docker compose ps -q my-app)
    # 记录当前是否运行,以及启动时间
    BEFORE_RUNNING=$(docker inspect --format '{{.State.Running}}' $CONTAINER_ID)
    BEFORE_STARTED_AT=$(docker inspect --format '{{.State.StartedAt}}' $CONTAINER_ID)
    
  2. 执行docker compose up命令

    docker compose up -d my-app
    
  3. 执行后,再次获取状态和启动时间,对比判断

    AFTER_RUNNING=$(docker inspect --format '{{.State.Running}}' $CONTAINER_ID)
    AFTER_STARTED_AT=$(docker inspect --format '{{.State.StartedAt}}' $CONTAINER_ID)
    
    # 判断逻辑
    if [ "$BEFORE_RUNNING" = "false" ] && [ "$AFTER_RUNNING" = "true" ]; then
        echo "容器my-app是本次up启动的"
    elif [ "$BEFORE_RUNNING" = "true" ] && [ "$BEFORE_STARTED_AT" != "$AFTER_STARTED_AT" ]; then
        echo "容器my-app是本次up重启的"
    else
        echo "容器my-app原本就处于运行状态,未被本次up变更"
    fi
    

方案2:监听Docker事件流

Docker本身提供了事件监听功能,可以实时捕获容器的startrestart事件,结合up命令的执行时间,判断是否是本次操作触发的:

  1. 先记录up命令的开始时间

    START_TIME=$(date -u +"%Y-%m-%dT%H:%M:%S.%NZ")
    
  2. 后台启动事件监听,过滤目标容器的相关事件
    比如监听my-app服务对应的容器的startrestart事件:

    docker events --filter "container=$(docker compose ps -q my-app)" --filter "event=start" --filter "event=restart" --since "$START_TIME" &
    EVENT_PID=$!
    
  3. 执行docker compose up命令

    docker compose up -d my-app
    
  4. 停止事件监听,检查是否捕获到事件

    kill $EVENT_PID
    # 如果有输出,说明容器被启动/重启了
    

    这个方案的优势是可以实时感知容器状态变化,不需要前后两次查询,适合脚本自动化场景。

方案3:解析Docker Compose的输出日志

虽然你提到解析日志不够优雅,但如果是简单场景,这个方法最快捷:
执行up命令时,直接过滤包含目标容器名和Starting/Restarting关键字的输出:

docker compose up -d my-app 2>&1 | grep -E "(Starting|Restarting) my-app"

如果有输出,说明容器被本次up启动或重启了;没有输出则说明容器原本就运行,未变更。


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

火山引擎 最新活动