2 回答
TA贡献1798条经验 获得超3个赞
我个人使用govendor。根据 golang 供应商约定,它将您的依赖项保存在项目内的供应商目录中。这仍然需要在构建时复制到您的 docker 映像中。
但是有很好的理由不供应商。例如,当您构建 pkg 时,您不应该供应商。当您有不同的 pkg 使用不同版本的依赖项时,事情会变得混乱。这可以通过仅供应可执行文件来解决。
因此,如果您有充分的理由不供应商,您可以分开几个步骤。将它们按正确的顺序排列将加快速度。
您可以创建一个 shell 脚本 ( get.sh),其中包含一些go get依赖项命令。(你可以把这些放在你的 Dockerfile 中,但它们有一个行限制)
go get github.com/golang/protobuf/proto
go get github.com/pborman/uuid
go get golang.org/x/net/context
go get golang.org/x/net/http2
go get golang.org/x/net/http2/hpack
然后在您的 Dockerfile 中,您首先复制并执行 shell 脚本。每次更新 get.sh 时,它都会完全重建。它仍然运行got get ./...以确保所有依赖项都存在。但是,如果所有内容都添加到get.sh脚本中,您将获得不错的速度提升。
FROM golang:1.6
RUN mkdir -p /go/src/app
COPY get.sh /go/src/app
WORKDIR /go/src/app
RUN bash get.sh
COPY . /go/src/app
RUN go get ./...
CMD go test -v
一般的想法是,您在 Dockerfile 中保持经常更改的内容较低,而顶部的内容则相当稳定。即使您必须添加另一个或两个命令。Docker 将逐行执行,直到找到需要重建的内容,然后也将执行之后的每一行。
TA贡献1946条经验 获得超3个赞
我一直在寻找您问题的答案,但具有讽刺意味的是,我发现了一个我有答案的问题(如何快速运行 docker 测试)。如果您真的想要快速测试,那么理想情况下,您应该在运行它们时完全避免重建容器。但是等等,如何将新的源代码放到容器中?卷我的朋友,卷。这是我的设置方式:
码头工人-compose.dev.yml:
backend-test:
volumes:
- .:/path/to/myapp
其中 /path/to/myapp 是图像中的路径,当然。您必须明确地将此图像传递给开发人员:
docker-compose up -f docker-compose.dev.yml
但是现在,当您运行测试时,您将不再使用 docker-compose,而是将使用 docker exec:
docker exec -it backend-test go test
如果你做对了,你在后端测试容器中的 src 目录将永远是最新的,因为它实际上是一个挂载的卷。附加到正在运行的容器并运行测试应该证明比每次都启动一个新容器要快得多。
编辑:评论者正确地指出,这只会在您的依赖项没有改变(不需要go get)时避免重建图像。好处是它不仅避免了重建,而且还避免了重新启动。当我像这样进行测试并添加依赖项时,我通常只是go get直接从我的测试控制台。在容器中工作可能有点棘手,但一种方法是通过挂载 SSH_AUTH_SOCKgo get将 ssh 代理转发到容器. 遗憾的是,您无法在构建期间挂载卷,因此如果您希望构建目标能够在运行测试之前提取新的依赖项,则可能需要在映像中包含某种部署密钥。但是,我的回答的要点是将构建和测试分开,以避免在您准备好生成最终工件之前进行完整构建。
也就是说,我想我可能理解我没有按照您提出的方式回答问题。在 ruby 中,答案就像复制 Gemfile 和 Gemfile.lock 并运行一样简单bundle install --deploy,然后再复制您更改的代码。就我个人而言,我不介意添加依赖项时的重建成本,因为我的 99% 的更改仍然不会涉及重建。也就是说,您可能会考虑使用受 golang 启发的新 Bundler 依赖管理器:dep。安装了 dep 后,我很确定你可以将你的Gopkg.tomland复制Gopkg.lock到你的工作目录中,运行dep ensure,然后复制您的代码。这只会在更新 Gopkg 时提取依赖项 - 否则 docker 将能够重用缓存层并安装您以前的依赖项。很抱歉长时间的编辑!
- 2 回答
- 0 关注
- 264 浏览
添加回答
举报