在Docker中初始化含submodule的git仓库后子仓库为空是什么原因?
问题根因
你遇到的空文件夹问题本质是Docker构建阶段和运行阶段的文件系统隔离+volume挂载覆盖导致的:
- Dockerfile中的
RUN指令是镜像构建阶段执行的,此时你执行的git submodule相关命令已经成功把子模块内容写入到镜像内的/home/djangohome路径下 - 你在docker-compose中把
/home/djangohome挂载为了本地volume,容器启动时,本地对应的目录会直接覆盖容器内该路径的所有内容——你本地的子模块目录本身没有初始化拉取内容,挂载后就会把镜像里已经拉好的子模块内容完全覆盖,最终呈现为空文件夹。
你在本地直接执行命令能生效,是因为直接操作的就是本地目录,没有挂载覆盖的步骤。
可行解决方案
方案1:把子模块初始化逻辑移到容器启动阶段
不要在构建阶段执行git submodule命令,改为放到容器启动脚本(entrypoint)中执行,此时volume挂载已经完成,操作的就是挂载后的本地目录,内容会持久化保留:
- 新建启动脚本
entrypoint.sh:
#!/bin/bash # 初始化并拉取所有子模块,包含嵌套子模块 git submodule update --init --recursive # 补充你原来的容器启动命令即可
- 修改Dockerfile:
WORKDIR /home/djangohome COPY . /home/djangohome/ # 给启动脚本加执行权限 RUN chmod +x entrypoint.sh ENTRYPOINT ["./entrypoint.sh"]
方案2:缩小volume挂载范围
如果不需要通过本地修改所有代码,就不要挂载整个/home/djangohome目录,仅挂载需要本地编辑/持久化的子目录(例如日志目录、静态资源目录、用户上传目录等),代码相关路径直接使用镜像内的文件,就不会覆盖已经拉好的子模块内容。
排查注意项
确认你的.dockerignore文件没有排除.git目录或者子模块对应的路径,如果有相关排除规则需要删除,否则构建阶段git无法读取仓库配置,子模块拉取会静默失败。
内容的提问来源于stack exchange,提问作者Qohelet
相关产品推荐
相关产品推荐

