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

Docker Compose执行down操作前能否运行自定义前置停止命令?

解决方案

核心思路

Docker 停止容器时默认会向容器内 PID 1 进程发送 SIGTERM 信号,等待指定的宽限期后未退出则发送 SIGKILL 强制终止。我们可以通过自定义启动脚本捕获该信号,在容器停止前先执行 screen 内进程的优雅退出逻辑,避免 docker-compose down 卡住。

具体实现步骤

第一步:编写自定义启动脚本

在 docker-compose 项目目录下新建启动脚本 start.sh,内容如下:

#!/bin/bash

# 优雅退出处理逻辑
cleanup() {
    # 向指定screen会话发送Minecraft服务停止指令(会自动保存存档后退出,比直接退出screen更安全)
    screen -S mc_screen -p 0 -X stuff "stop$(printf \\r)"
    # 等待screen会话完全退出后再结束脚本
    while screen -list | grep -q "mc_screen"; do
        sleep 1
    done
    exit 0
}

# 捕获docker stop默认发送的SIGTERM信号
trap cleanup SIGTERM

# 后台启动screen运行Minecraft进程,mc_screen为自定义的screen会话名
screen -dmS mc_screen java -Xmx4G -Xms2G -jar server.jar nogui

# 保持脚本前台运行,持续接收信号
while true; do
    sleep 1
done

本地执行以下命令给脚本添加执行权限:
chmod +x start.sh

第二步:修改docker-compose.yml配置

调整服务配置,使用自定义脚本启动,同时配置停止宽限期:

version: '3'
services:
  minecraft:
    build: . # 如果你需要预装screen,搭配下方Dockerfile使用
    # 如无需自定义镜像,可直接用预装screen的openjdk镜像替换上方build配置
    # image: 你的自定义镜像名
    working_dir: /data
    volumes:
      - ./mc-world:/data # 映射Minecraft存档目录
      - ./start.sh:/start.sh # 映射自定义启动脚本
    command: /start.sh # 替换默认启动命令为自定义脚本
    # 配置优雅停止宽限期,根据存档大小调整,避免存档未保存完被强制停止
    stop_grace_period: 2m
    ports:
      - "25565:25565"
    # 保留tty和stdin配置,保证screen正常运行
    tty: true
    stdin_open: true

可选:配置Dockerfile预装screen

如果使用的基础镜像没有screen,在项目目录下新建Dockerfile:

FROM openjdk:17-jdk-slim
RUN apt update && apt install -y screen && rm -rf /var/lib/apt/lists/*

验证效果

  • 后台启动服务:docker-compose up -d
  • 接入Minecraft终端:docker exec -it <容器名> screen -r mc_screen,按Ctrl+A+D detach不会杀死进程
  • 停止服务:docker-compose down,会先触发脚本内的cleanup逻辑,等Minecraft存档保存、screen退出后再正常停止容器,不会出现卡住的问题。
  • 如果确实需要直接退出screen而非发送MC的stop命令,把cleanup函数内的stuff参数替换为exit$(printf \\r)即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 18:54:05