docker-compose运行Python+MongoDB项目容器反复重启但单独run正常如何解决
问题原因及解决方案
核心问题1:MongoDB账号权限不匹配
你配置的MongoDB根用户账号为mongodbuser/mongodbrootpassword,但给Python应用传递的数据库账号是appuser/mongopassword,而你并没有在MongoDB初始化阶段创建appuser这个普通用户,同时MongoDB开启了身份校验,应用连接数据库直接失败崩溃,触发restart: unless-stopped策略反复重启。如果你的Python代码没有捕获连接异常并打印日志,就会出现容器日志无输出的情况。
核心问题2:Python输出被缓冲
Python默认在非交互式终端环境下会对标准输出/标准错误做缓冲,应用崩溃的报错信息被缓存在内存中没有写入日志,导致docker logs看不到内容。
核心问题3:应用启动早于MongoDB初始化完成
depends_on仅保证MongoDB容器先启动,不会等待MongoDB内部的用户、库初始化完成,首次启动时应用大概率会因为数据库未就绪连接失败退出。
修复步骤
- 修复日志无输出问题
在docker-compose的app服务中添加环境变量禁用Python输出缓冲:
environment: # 新增如下配置 PYTHONUNBUFFERED: 1
或者修改Dockerfile的CMD为:
CMD ["python3", "-u", "foo.py"]
- 修复MongoDB权限问题
两种可选方案:
- 方案1:应用直接使用MongoDB根账号,修改app服务的环境变量:
同时注意代码中MongoDB连接字符串需要指定根账号的认证源为admin库,示例:MONGODB_USERNAME: mongodbuser MONGODB_PASSWORD: mongodbrootpasswordclient = pymongo.MongoClient("mongodb://mongodbuser:mongodbrootpassword@mongodb:27017/db?authSource=admin") - 方案2:新增初始化脚本创建普通应用账号,在项目目录下新建
mongo-init.js:
然后在mongodb服务的volumes中挂载该初始化脚本:db.createUser({ user: "appuser", pwd: "mongopassword", roles: [{ role: "readWrite", db: "db" }] })volumes: - mongodbdata:/data/db - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
- 修复启动顺序问题
给MongoDB服务添加健康检查,让应用等数据库就绪后再启动:
mongodb: image: mongo container_name: mongodb restart: unless-stopped command: mongod --auth # 新增健康检查配置 healthcheck: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] interval: 5s timeout: 5s retries: 3 environment: MONGO_INITDB_ROOT_USERNAME: mongodbuser MONGO_INITDB_ROOT_PASSWORD: mongodbrootpassword MONGO_INITDB_DATABASE: db MONGODB_DATA_DIR: /data/db MONDODB_LOG_DIR: /dev/null volumes: - mongodbdata:/data/db networks: - internal
同时修改app服务的depends_on配置:
depends_on: mongodb: condition: service_healthy
- 修复Dockerfile中的无效配置
你Dockerfile中RUN export PYTHONPATH=$PATHONPATH:pwd``存在两处错误:一是变量名拼写错误(PATHONPATH应为PYTHONPATH),二是RUN指令设置的环境变量仅在构建阶段生效,容器运行时不会保留,修改为ENV指令即可:
ENV PYTHONPATH="${PYTHONPATH}:/app"
内容的提问来源于stack exchange,提问作者EDGAR MEDINA
相关产品推荐
相关产品推荐

