【发布时间】:2021-02-16 01:41:15
【问题描述】:
有一个用 Go 编写的库。它的文件夹结构是:
lib/
golang/
go.mod
lib.go
example/
golang/
proto/
protofile
go.mod
main.go
Dockerfile
example 是展示如何使用这个库的文件夹,所以它有一个可以构建和运行的 main.go。为了使用 lib,example/golang/go.mod 是:
module golang
go 1.15
require (
lib/golang v0.0.0
other stuff...
)
replace lib/golang => ../../golang
现在我想把可运行的例子打包成一个docker镜像,Dockerfile是:
FROM golang:1.15
WORKDIR /go/src/app
COPY . .
RUN go env -w GO111MODULE=auto
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN go get -d -v ./...
RUN go install -v ./...
CMD ["app"]
然后我 cd 进入 example/golang 运行docker build -t example .,错误日志是
open /go/golang/go.mod: no such file or directory
好像无法访问 lib/go.mod 文件,然后我 cd 到 lib 文件夹并运行 docker build -t server -f examples/golang/Dockerfile .,但这会影响 main.go 的导入:
import "golang/proto"
错误日志是:
golang/proto: unrecognized import path "golang/proto"
我应该如何解决这个问题以制作 docker 镜像?
============================================
在我花了一些时间阅读 docker doc 之后,这里是关于这个问题的总结:
docker build 命令遵循 PATH 参数,即末尾的点 .。控制构建的内容,它决定了 docker build 可以访问哪些文件。所以第一个错误的原因是 pwd 是 lib/example/golang,而 docker build 命令路径是.,那么 docker build 无法访问 lib/example/golang 的父文件,它们在 main.go 中是必需的一个库。
命令应该是:docker build -t example ../../ 但是,docker build 只在内容路径的根目录中寻找 Dockerfile,所以使用 -f 告诉它 Dockerfile 的位置:docker build -t example -f ./Dockerfile ../../
如果 pwd 为 lib/,则命令为 docker build -t server -f examples/golang/Dockerfile .
简短:
- 如果 dockerfile 不在项目根路径下,请使用 docker build 命令的 -f 和 PATH 为其提供足够的文件访问权限。如果使用 go 模块,请确保 PATH 包含 go.mod 文件
- 如果main.go位于子文件夹,请确保dockerfile中的WORKDIR与COPY后的子文件夹一致,否则go build或go install编译失败
【问题讨论】:
-
"golang/proto" 是无效的导入路径。你需要解决这个问题。这不是 docker 的问题。
-
run go build without dockerfile 会成功,不是编码错误
-
go build工作并不意味着它不是编码错误。您的 Docker 外部环境可能允许无效的导入路径。 -
你的
Dockerfile是嵌套的 - 所以docker build .构建上下文看不到父目录库。