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

如何让基于自定义Raspbx镜像创建的Docker容器持续运行?

让Raspbx Docker容器持续稳定运行的解决方案

我来帮你梳理下问题并给出可行的修复方案。你遇到的核心问题是容器PID 1进程的生命周期管理,以及启动脚本里的逻辑错误导致脚本提前退出,最终让容器终止。以下是具体的解决步骤:


1. 修复启动脚本的逻辑错误

你的startup.sh里存在变量复用的问题,导致进程状态判断完全错误。比如启动fwconsole后,你没有更新status变量,仍然在用之前MySQL的状态值,这会导致错误的退出逻辑。同时,进程检查的方式也可以更可靠。

修改后的startup.sh如下:

#!/bin/bash -x
# 多服务容器管理脚本

# 启动MySQL
/etc/init.d/mysql start
status=$?
if [ $status -ne 0 ]; then
    echo "Failed to start mysql: $status"
    exit $status
fi

# 启动FreePBX
fwconsole start
status=$?
if [ $status -ne 0 ]; then
    echo "Failed to start fwconsole: $status"
    exit $status
fi

# 如果存在备份则恢复
if [ -f /backup/new.tgz ]; then
    echo "Restoring backup from /backup/new.tgz"
    php /var/www/html/admin/modules/backup/bin/restore.php --items=all --restore=/backup/new.tgz
    echo "Backup restore done"

    # 恢复后重启FreePBX
    fwconsole stop
    status=$?
    if [ $status -ne 0 ]; then
        echo "Failed to stop fwconsole: $status"
        exit $status
    fi

    fwconsole start
    status=$?
    if [ $status -ne 0 ]; then
        echo "Failed to start fwconsole: $status"
        exit $status
    fi
fi

# 启动Apache2
/etc/init.d/apache2 start
status=$?
if [ $status -ne 0 ]; then
    echo "Failed to start apache2: $status"
    exit $status
fi

# 启动后台脚本
/run/backup.sh &
status=$?
if [ $status -ne 0 ]; then
    echo "Failed to start backup.sh: $status"
    exit $status
fi

/run/delete-old-recordings.sh &
status=$?
if [ $status -ne 0 ]; then
    echo "Failed to start delete-old-recordings.sh: $status"
    exit $status
fi

# 主循环:持续监控关键进程,维持容器运行
while /bin/true; do
    # 用pgrep替代ps+grep,避免误判grep自身进程
    pgrep mysqld > /dev/null
    MYSQL_STATUS=$?
    
    pgrep asterisk > /dev/null
    ASTERISK_STATUS=$?
    
    pgrep -f '/run/backup.sh' > /dev/null
    BACKUP_STATUS=$?
    
    pgrep -f '/run/delete-old-recordings.sh' > /dev/null
    RECORD_STATUS=$?

    echo "Checking critical processes..."
    if [ $MYSQL_STATUS -ne 0 -o $ASTERISK_STATUS -ne 0 -o $BACKUP_STATUS -ne 0 -o $RECORD_STATUS -ne 0 ]; then
        echo "One or more critical processes exited. Stopping container."
        exit 1
    fi
    echo "All processes running normally."
    sleep 60
done

2. 解决Docker容器PID 1的特殊问题

Docker容器的PID 1进程需要负责:

  • 持续运行(否则容器终止)
  • 回收僵尸进程(避免容器资源泄漏)

你可以通过两种方式处理:

方式一:使用Docker内置的init进程

运行容器时添加--init参数,Docker会自动注入tini作为PID 1,帮你处理僵尸进程:

docker run --name=raspbx \
  --net=macvlan_network --ip=192.168.188.27 \
  -d --privileged --restart unless-stopped \
  --init raspbx

方式二:更新Dockerfile让脚本作为PID 1运行

确保你的Dockerfile将修复后的脚本设置为ENTRYPOINT:

FROM raspbx
COPY startup.sh /run/startup.sh
RUN chmod +x /run/startup.sh
ENTRYPOINT ["/run/startup.sh"]
EXPOSE 80 3306 5060 5061 5160 5161 4569 10000-20000/udp

重新构建镜像:

docker build -t raspbx-fixed .

然后用新镜像启动容器即可。


3. 验证与排障

如果容器仍然终止,先查看日志排查错误:

docker logs raspbx

重点检查服务启动失败的原因(比如MySQL/Apache是否因为容器环境缺少依赖而无法启动)。另外,--privileged权限虽然能解决大部分设备/权限问题,但如果仍有异常,可以尝试添加特定的设备映射(比如/dev/tty等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 18:17:35