最近在将一个Python项目容器化时遇到了一个典型问题:当我在Docker容器中运行项目时,系统抛出ModuleNotFoundError: No module named 'src'错误。这个问题看似简单,实则涉及Python模块导入机制、Docker文件系统映射和PYTHONPATH环境变量配置等多个技术点的协同工作。
这种情况通常发生在以下场景:
src/目录)from src.module import func)Python的模块搜索路径遵循以下顺序:
当出现ModuleNotFoundError时,说明Python解释器在以上所有位置都未能找到对应的模块。
在Docker容器中,这个问题会更加复杂因为:
首先确保项目结构符合Python包规范:
code复制my_project/
├── Dockerfile
├── requirements.txt
└── src/
├── __init__.py
├── module1.py
└── module2.py
dockerfile复制# 使用官方Python基础镜像
FROM python:3.9-slim
# 设置工作目录(关键步骤)
WORKDIR /app
# 先复制requirements.txt单独安装依赖(利用Docker缓存层)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制整个项目(注意最后的点表示当前目录)
COPY . .
# 设置PYTHONPATH环境变量(关键步骤)
ENV PYTHONPATH=/app
# 指定容器启动命令
CMD ["python", "src/main.py"]
WORKDIR设置:
/app作为项目根目录PYTHONPATH设置:
/app加入Python模块搜索路径src作为包COPY指令顺序:
对于开发环境,可以在Dockerfile中添加:
dockerfile复制RUN pip install -e .
这需要在项目根目录包含setup.py文件。
对于生产环境,推荐使用多阶段构建:
dockerfile复制# 构建阶段
FROM python:3.9 as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt
# 运行阶段
FROM python:3.9-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
ENV PYTHONPATH=/app
对于复杂项目,可以在入口脚本中动态设置:
python复制import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent))
排查步骤:
bash复制docker exec -it <container> ls /app/src
bash复制docker exec -it <container> env | grep PYTHONPATH
bash复制docker exec -it <container> python -c "import src"
Windows特有的注意事项:
.dockerignore文件排除不必要的文件经过多个项目的实践验证,我总结出以下可靠方案:
对于特别复杂的项目,可以考虑使用专门的工具管理Python路径,如:
python-dotenv管理环境变量setup.cfg或pyproject.toml声明项目结构importlib动态导入模块