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

Docker Compose中三个Python容器脚本运行混淆问题排查

问题描述

目录结构:

python_tools/
├─ scriptA/
│  ├─ main.py
│  └─ requirements.txt
├─ scriptB/
│  ├─ main.py
│  └─ requirements.txt
├─ scriptC/
│  ├─ main.py
│  └─ requirements.txt
├─ logs/
│  ├─ scriptA/
│  ├─ scriptB/
│  └─ scriptC/
├─ docker-compose.yml
├─ Dockerfile.scriptA
├─ Dockerfile.scriptB
└─ Dockerfile.scriptC

原docker-compose.yml配置:

version: "3.1"
services:
    scriptA:
        image: python:3.9
        volumes:
        - ./python_tools/logs/scriptA:/opt/app/scriptA/log
        build:
            context: .
            dockerfile: Dockerfile.scriptA
    scriptB:
        image: python:3.9
        volumes:
        - ./python_tools/logs/scriptB:/opt/app/scriptB/log
        build:
            context: .
            dockerfile: Dockerfile.scriptB
    scriptC:
        image: python:3.9
        volumes:
        - ./python_tools/logs/scriptC:/opt/app/scriptC/log
        build:
            context: .
            dockerfile: Dockerfile.scriptC

每个Dockerfile.scriptX内容:

FROM python:3.9
COPY ./python_tools/scriptX /opt/app/scriptX
WORKDIR /opt/app/scriptX
RUN pip install -r requirements.txt
ENTRYPOINT [ "python", "-u", "main.py" ]

main.py代码:

def log(msg):
    print(msg)
    f = open("log/log.txt", "a+")
    f.write(msg + "\r\n")
    f.close()

if __name__ == "__main__":
    log("Starting scriptX")
    while(True):
        do_something()

遇到的问题:

  • 执行docker logs -f python_scriptB-1时,输出的是scriptA的启动日志,同时报错找不到log文件
  • 执行docker compose build --no-cache时,重复构建scriptA,未按预期构建三个独立服务
问题原因分析
  1. 镜像名称冲突:三个服务都指定了相同的image: python:3.9,Docker Compose会将这三个服务关联到同一个镜像。构建时会重复使用第一个服务的构建结果,导致三个服务实际运行的都是scriptA的镜像内容,所以日志串线,且路径不匹配引发文件找不到的错误。
  2. 日志目录权限/路径问题:若宿主机器上的python_tools/logs/scriptX目录不存在,Docker会自动创建该目录,但默认是root权限;同时由于镜像串用,scriptB容器实际运行的是scriptA代码,尝试写入的路径与挂载的scriptB日志目录不匹配,双重因素触发找不到文件的错误。
优化后的配置方案

方案1:简化配置,使用唯一镜像名+子目录上下文

修改docker-compose.yml,给每个服务指定唯一镜像名,并将build的context指向对应子目录,减少冗余:

version: "3.8"
services:
  scriptA:
    image: script-a:latest
    volumes:
      - ./python_tools/logs/scriptA:/opt/app/log
    build:
      context: ./python_tools/scriptA
      dockerfile: ../../Dockerfile.script
    restart: unless-stopped

  scriptB:
    image: script-b:latest
    volumes:
      - ./python_tools/logs/scriptB:/opt/app/log
    build:
      context: ./python_tools/scriptB
      dockerfile: ../../Dockerfile.script
    restart: unless-stopped

  scriptC:
    image: script-c:latest
    volumes:
      - ./python_tools/logs/scriptC:/opt/app/log
    build:
      context: ./python_tools/scriptC
      dockerfile: ../../Dockerfile.script
    restart: unless-stopped

将三个Dockerfile合并为一个通用的Dockerfile.script:

FROM python:3.9

# 创建工作目录并设置日志目录权限
WORKDIR /opt/app
RUN mkdir -p log && chmod 777 log

# 复制当前子目录的代码(context已指向scriptX目录)
COPY . .

# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt

# 非root用户运行(可选,提升安全性)
RUN useradd -m appuser
USER appuser

ENTRYPOINT ["python", "-u", "main.py"]

修改main.py中的日志路径(对应挂载的/opt/app/log):

def log(msg):
    print(msg)
    with open("log/log.txt", "a+") as f:
        f.write(msg + "\n")

if __name__ == "__main__":
    log("Starting scriptX")
    while True:
        # 替换为实际业务逻辑
        do_something()

方案2:使用Docker Compose模板减少重复配置

如果需要保留独立Dockerfile,可使用YAML锚点简化配置:

version: "3.8"
x-base-script: &base-script
  restart: unless-stopped
  build:
    context: .

services:
  scriptA:
    <<: *base-script
    image: script-a:latest
    volumes:
      - ./python_tools/logs/scriptA:/opt/app/scriptA/log
    build:
      dockerfile: Dockerfile.scriptA

  scriptB:
    <<: *base-script
    image: script-b:latest
    volumes:
      - ./python_tools/logs/scriptB:/opt/app/scriptB/log
    build:
      dockerfile: Dockerfile.scriptB

  scriptC:
    <<: *base-script
    image: script-c:latest
    volumes:
      - ./python_tools/logs/scriptC:/opt/app/scriptC/log
    build:
      dockerfile: Dockerfile.scriptC

关键注意事项

  • 每个服务必须指定唯一的镜像名称,避免Docker Compose混淆镜像来源
  • 提前创建宿主机器上的日志目录,或在Dockerfile中创建容器内的日志目录并设置合理权限
  • 使用with open替代直接open/close,确保文件句柄正确释放
  • 尽量使用非root用户运行容器,提升安全性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:47:54