在父目录中运行"go mod download"的Golang实践指南
在父目录中运行"go mod download"的Golang实践指南 项目结构:
project_dir/
├── prj1/
│ ├── go/
│ ├─ |─ go.mod
│ ├─ |─ main.go
│ └─ |─ ...
│ └── ...
├── prj2/
│ ├── go.mod
│ ├── main.go
│ └── Dockerfile
│ └── ...
└── ...
prj2 中的代码通过 go mod edit -replace 命令引用了 prj1 中的一个函数。现在,这在本地运行良好,但我需要使用 Docker 进行部署,并且遇到了问题。
我的 Docker 脚本如下所示:
FROM golang:1.17.5 as builder
WORKDIR /app
COPY go.* ./
ADD ./prj1 ./prj1
RUN go mod download
...
最初,我在 prj2 目录内运行 docker build .,Dockerfile 中没有 ADD 命令,但 RUN go mod download 失败并提示:
go mod download: github.com/name/project/prj1@v0.0.0-00010101000000-000000000000 (replaced by …/prj1/go/): reading /prj1/go/go.mod: open /prj1/go/go.mod: no such file or directory
因此,我在 Dockerfile 中添加了 ADD 命令来复制 prj1。接着,我回到 project_dir 并运行 docker build -f ./prj2/Dockerfile,但现在 RUN go mod download 又失败了,提示:
go mod download: no modules specified (see ‘go help mod download’)
所以,我的基本问题是,如何告知 go 命令 go.mod 文件位于 prj2 目录内?
编辑: 正确的项目结构
更多关于在父目录中运行"go mod download"的Golang实践指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html
替换的格式如下: replace github.com/name/project/prj1 => …/proj1/go/
更多关于在父目录中运行"go mod download"的Golang实践指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你 prj2/go.mod 中的 “replace” 是相对路径吗?或许你可以尝试 replace … => /app/prj1
我认为
将 http://github.com/name/project/prj1 替换为 /app/proj1/go
应该是可行的,因为 proj1 的完整路径位于 /app 目录下。
你好,@ozuf,
go mod download 必须在 go.mod 文件所在的目录中运行。(换句话说,在主模块内部)。对于 Docker,这可能意味着 go.mod 文件必须在 WORKDIR 目录下(或者 WORKDIR 必须指向 go.mod 文件所在的位置)。
关于另一个错误,.../prj1/go 中的三个点是故意的吗?我认为应该只有两个点,这样才符合项目结构。
在父目录中运行 go mod download 时,需要指定正确的模块路径。以下是解决方案:
解决方案
1. 修改 Dockerfile 使用正确的上下文和工作目录
FROM golang:1.17.5 as builder
# 设置工作目录到 prj2
WORKDIR /app/prj2
# 复制整个项目结构
COPY . /app/
# 复制 prj2 的 go.mod 和 go.sum
COPY prj2/go.mod prj2/go.sum ./
# 下载依赖
RUN go mod download
# 复制源代码
COPY prj2/ ./
# 构建
RUN CGO_ENABLED=0 GOOS=linux go build -o main .
2. 使用多阶段构建的完整示例
FROM golang:1.17.5 as builder
# 设置项目根目录
WORKDIR /app
# 复制所有 go.mod 文件
COPY prj1/go/go.mod ./prj1/go/
COPY prj2/go.mod ./prj2/
# 复制 go.sum 文件(如果存在)
COPY prj1/go/go.sum ./prj1/go/ 2>/dev/null || true
COPY prj2/go.sum ./prj2/ 2>/dev/null || true
# 在 prj2 目录中下载依赖
WORKDIR /app/prj2
RUN go mod download
# 复制所有源代码
COPY . .
# 构建 prj2
RUN CGO_ENABLED=0 GOOS=linux go build -o main .
# 最终阶段
FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/prj2/main .
CMD ["./main"]
3. 使用构建参数指定模块路径
FROM golang:1.17.5 as builder
ARG MODULE_PATH=prj2
WORKDIR /app
# 复制必要的文件
COPY ${MODULE_PATH}/go.mod ${MODULE_PATH}/go.sum ./
# 下载依赖
RUN go mod download
# 复制源代码
COPY ${MODULE_PATH}/ ./
COPY prj1/go/ ./prj1/go/
# 构建
RUN CGO_ENABLED=0 GOOS=linux go build -o main .
4. 使用 docker-compose 的配置示例
version: '3.8'
services:
prj2:
build:
context: .
dockerfile: prj2/Dockerfile
volumes:
- ./prj2:/app/prj2
- ./prj1/go:/app/prj1/go
5. 关键点说明
在 prj2 的 go.mod 中,replace 指令应该正确指向本地路径:
module github.com/yourname/prj2
go 1.17
replace github.com/yourname/prj1 => ../prj1/go
require github.com/yourname/prj1 v0.0.0
构建命令应该从项目根目录执行:
# 从项目根目录构建
docker build -f prj2/Dockerfile -t prj2-app .
# 或者进入 prj2 目录构建
cd prj2
docker build -t prj2-app .
6. 验证构建的脚本
#!/bin/bash
# build.sh
# 确保在项目根目录
if [ ! -f "prj2/Dockerfile" ]; then
echo "请在项目根目录运行此脚本"
exit 1
fi
# 清理旧的构建
docker rm -f prj2-build 2>/dev/null || true
# 构建镜像
docker build -f prj2/Dockerfile -t prj2-app .
# 验证构建
docker run --rm prj2-app go version
这些方法都能解决在父目录中运行 go mod download 时找不到正确模块的问题。关键是要确保 Docker 构建上下文正确,并且 go mod download 在包含正确 go.mod 文件的目录中执行。

