Docker容器中Python3脚本随机终止问题求助
我是Docker新手,在Docker的使用与概念上存在一些入门级困惑。
我启动构建完成的镜像的命令为:
docker run -d -p 7070:80 --name mov_container my_image
我的Dockerfile内容如下:
FROM php:7.1-apache RUN apt-get update RUN apt-get install -y python3 RUN apt-get install -y python3-pip RUN pip3 install requests RUN pip3 install pymysql COPY src/ /var/www/html/ COPY Movement_Tracker.py /var/movtrack/ RUN docker-php-ext-install mysqli RUN docker-php-ext-enable mysqli apachectl restart
目前遇到的问题是:Docker容器中的Python3脚本会随机终止。
作为经常处理Docker入门问题的开发者,我帮你梳理下几个核心原因和对应的解决办法:
1. 脚本缺乏稳定的运行守护机制
你的容器默认主进程是Apache(来自php:7.1-apache基础镜像),而Python脚本只是被复制到容器里,没有配置持续运行的机制。如果脚本是长运行类型(比如循环任务、事件监听),一旦遇到异常或资源波动退出,Apache主进程不会主动重启它,就会出现"随机终止"的情况。
解决办法:用进程管理器同时管理Apache和Python脚本
推荐用supervisord来统一管控多个进程:
- 第一步,在Dockerfile中安装supervisord:
RUN apt-get install -y supervisor && rm -rf /var/lib/apt/lists/* - 第二步,创建一个supervisor配置文件(比如
supervisord.conf),放在项目根目录:[supervisord] nodaemon=true # 让supervisord在前台运行,作为容器主进程 [program:apache2] command=/usr/sbin/apache2ctl -D FOREGROUND stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [program:mov_tracker] command=python3 /var/movtrack/Movement_Tracker.py directory=/var/movtrack stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 autorestart=true # 脚本意外退出时自动重启 startretries=3 - 第三步,在Dockerfile中复制配置文件,并设置容器启动命令:
COPY supervisord.conf /etc/supervisor/conf.d/ CMD ["supervisord"]
2. 脚本自身存在未处理的异常或资源泄漏
很多时候"随机终止"其实是脚本内部隐藏的问题,比如:
- requests请求遇到网络波动未捕获异常
- pymysql数据库连接断开未重连
- 内存泄漏导致被系统OOM Killer杀死
解决办法:排查脚本内部问题
- 查看容器日志:执行
docker logs mov_container(用supervisord后,Apache和Python的日志都会在这里输出),找脚本终止前的错误信息。 - 给脚本加异常捕获和日志:
import logging import traceback # 配置日志输出到文件和控制台 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('/var/movtrack/tracker.log'), logging.StreamHandler() ] ) try: # 你的脚本核心逻辑 while True: # 比如任务循环 pass except Exception as e: logging.error(f"脚本异常终止: {str(e)}") logging.error(traceback.format_exc()) # 如果需要自动退出让supervisord重启,就保留exit;如果想继续运行,就移除 exit(1) - 监控容器资源:用
docker stats mov_container查看CPU、内存占用,如果内存持续上涨,说明有内存泄漏,需要优化脚本(比如及时释放无用对象、关闭未使用的连接)。
3. 容器资源不足被系统杀死
如果主机本身资源紧张,容器里的Python进程可能因为内存不足被Linux的OOM Killer强制终止。
解决办法:给容器分配足够资源
启动容器时指定内存限制,比如分配512MB内存:
docker run -d -p 7070:80 --name mov_container --memory=512m my_image
也可以查看系统OOM日志确认:执行dmesg | grep oom-killer,如果能看到和你的容器相关的记录,就说明是内存不足导致的。
4. Dockerfile中的无效命令
最后提个小细节:你的Dockerfile最后一行apachectl restart是无效的——RUN命令是在镜像构建阶段的临时容器中执行的,构建完成后这个临时容器会被销毁,启动正式容器时Apache会重新启动。所以这行可以删掉,而且docker-php-ext-enable mysqli后也不需要手动重启Apache,容器启动时会自动加载扩展。
内容的提问来源于stack exchange,提问作者hallo02

