问题描述

在实际开发中,我的项目目录结构如下所示(test 为核心项目文件夹):

1
2
3
test
├── output
├── app.py

项目的核心文件是 app.py,其代码逻辑中定义了以下路径:

1
output_dir = "output"

程序会往 output 文件夹中写入文件。
在 Docker 容器中运行时,遇到了路径相关的问题:

  1. Dockerfile 设置的 WORKDIR 是 /app,且项目通过以下指令复制到容器中:
    1
    COPY test /app/test
  2. 容器启动时执行了以下命令:
    1
    CMD ["python", "test/app.py"]
  3. 运行后发现,output 文件夹并没有出现在 /app/test(即 app.py 同级)下,而是出现在了 /app(与 test 同级)下。

问题原因分析

  1. Docker 容器的文件系统独立性: 容器中的路径与主机系统完全隔离。当主机上的文件夹(如 test)通过 COPY 指令复制到容器中时,它们会被放置在容器内的 /app/test中,而路径的解析完全取决于容器内的环境配置。
  2. Docker 的 WORKDIR 设置的影响: Dockerfile 中使用了以下指令:
    1
    WORKDIR /app
    这将容器的工作目录设置为 /app,即容器内所有相对路径都会相对于 /app 解析。
  3. Python 运行时的路径解析机制: 在 Python 中,使用相对路径时,路径是相对于运行时的“当前工作目录”(由 os.getcwd() 获取)解析的,而非脚本文件所在的目录。
    – 运行 mockup4/app_l4.py 时,工作目录仍然是 /app。
    – 因此,相对路径 output 被解析为 /app/output。
  4. 代码中路径与实际目录的不一致性: 程序逻辑期望 output 位于 test 内,即 /app/test/output,但由于工作目录设置为 /app,最终导致 output 文件夹出现在 /app。

解决方案

解决方案1(代码逻辑):修改代码,动态解析路径

调整代码逻辑,让相对路径基于脚本文件的位置,而非运行时的工作目录。
在 app.py 中,使用以下代码动态获取脚本文件的路径,并生成目标文件夹的路径:

1
2
3
4
5
6
7
8
9
10
import os

# 获取当前脚本所在的目录
script_dir = os.path.dirname(os.path.abspath(__file__))

# 设置 output 文件夹路径为脚本所在目录的子目录 "output"
output_dir = os.path.join(script_dir, "output")

# 输出路径(调试时可用)
print(f"Output directory: {output_dir}")

效果:

  • 无论 WORKDIR 设置为何,output_dir 都会解析为 /app/mockup4/output。
  • 提高了代码的移植性,适用于本地调试和容器运行的场景。

解决方案2(Docker 配置):调整 Docker 的 WORKDIR 设置

修改 Dockerfile,将工作目录设置为 mockup4 文件夹所在的路径 /app/mockup4,这样程序运行时相对路径自然指向脚本同级路径。
修改后的 Dockerfile:

1
2
3
4
5
6
7
8
# 设置工作目录为 /app/test
WORKDIR /app/test

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

# 运行程序
CMD ["python", "app.py"]

效果:

  • 相对路径 output 会解析为 /app/test/output。
  • 不需要修改代码逻辑。
  • 容器中路径配置与项目期望一致,直观易懂。