英文:
Docker-Compose: Composing with Dockerfiles that need relative imports
问题
开始,这是我的项目层次结构:
myproj/
- commons1/
- com1_file1.go
- ...
- commons2/
- com2_file1.go
- ...
- module1/
- mod1_file1.go
- Dockerfile
- ...
- module2/
- mod2_file1.go
- Dockerfile
- ...
- docker-compose.yml
我想要的是,当 module1
和 module2
容器启动时,它们各自在其 GOPATH
中都有 commonsN
目录的副本,以便每个容器都可以访问 commonsN
目录中公共库。
例如,我希望在 module1
容器中看到类似于以下内容:
/go/
- src/
- commons1/
- com1_file1.go
- ...
- commons2/
- com2_file1.go
- ...
- module1/
- mod1_file1.go
- ...
原因是这基本上是我的本地 GOPATH
的样子(当然还有其他模块的添加),这样我就可以在我的源文件中做类似于以下的事情:
package main
import(
"fmt"
"myproj/commons1"
)
func main() {
fmt.Println("Some thing from common library :", commons1.SomethingFromCommons)
}
根据我对 Docker 的初步了解,似乎我不允许修改我的 Dockerfile 来执行类似于 COPY ../commons1 /go/src/commons1
的操作,所以我想知道如何实现这一点?
我强烈不希望使用 Github 的方法,因为源代码都在公司的代理服务器后面,我想象配置所有这些可能比简单复制一些目录要花费更长的时间。
编辑
根据 barat 的建议,我已经更新了我的 docker-compose.yml
文件,大致如下:
version: '2'
services:
module1:
volumes:
- ./commons1:/go/src/myproj/commons1
build: module1/
module1
的 Dockerfile 如下:
FROM golang:1.8.0
RUN mkdir -p /go/src/app
WORKDIR /go/src/app
COPY . /go/src/app
RUN go get -d -v
RUN go install -v
ENTRYPOINT /go/bin/app
EXPOSE 8080
docker-compose build
在 go get -d -v
步骤失败,报错信息为:
>package myproj/commons1: unrecognized import path "myproj/commons1" (import path does not begin with hostname)
如果 myproj/commons1
被复制到 /go/src/
中,那么这个问题就不应该存在,对吗?我猜这个目录还没有被复制过来?
英文:
To begin, this is my project hierarchy:
myproj/
- commons1/
- com1_file1.go
- ...
- commons2/
- com2_file1.go
- ...
- module1/
- mod1_file1.go
- Dockerfile
- ...
- module2/
- mod2_file1.go
- Dockerfile
- ...
- docker-compose.yml
What I'd like to do is that when module1
and module2
containers start up, they each have a copy of all the commonsN
directories in their GOPATH
's so that each can access the common libraries exposed by each of the commonsN
directories.
For example, I would like to see something like this in the container for module1
:
/go/
- src/
- commons1/
- com1_file1.go
- ...
- commons2/
- com2_file1.go
- ...
- module1/
- mod1_file1.go
- ...
Reason being is that this is basically how my local GOPATH
looks (with the addition of the other modules of course) so that I can do something like this in my source files:
package main
import(
"fmt"
"myproj/commons1"
)
func main() {
fmt.Println("Some thing from common library :", commons1.SomethingFromCommons)
}
From my naive understanding of Docker, it appears I'm not allowed to modify my Dockerfiles to do something along the lines of COPY ../commons1 /go/src/commons1
, so I'm wondering how I would go about accomplishing this?
I would strongly prefer to not go the Github route since the source code is all behind company proxies and whatnot and I'm imagining configuring all that is going to take way longer than simply copying some directories.
Edit
I have updated my docker-compose.yml
file to look something like this per suggestion from barat:
version: '2'
services:
module1:
volumes:
- ./commons1:/go/src/myproj/commons1
build: module1/
Dockerfile for module1
looks like this:
FROM golang:1.8.0
RUN mkdir -p /go/src/app
WORKDIR /go/src/app
COPY . /go/src/app
RUN go get -d -v
RUN go install -v
ENTRYPOINT /go/bin/app
EXPOSE 8080
docker-compose build
fails on the go get -d -v
with error:
>package myproj/commons1: unrecognized import path "myproj/commons1" (import path does not begin with hostname)
If myproj/commons1
was copied into /go/src/
, then this shouldn't be an issue right? I'm guessing then it hasn't been copied over then?
答案1
得分: 2
你可以构建一个包含commons1
和commons2
的镜像,其他镜像都是基于它们构建的。
FROM golang:1.8.0
RUN mkdir -p /go/src/myproj/commons1 && mkdir -p /go/src/myproj/commons2
COPY commons1/ /go/src/myproj/commons1/
COPY commons2/ /go/src/myproj/commons2/
不过这种方法的缺点是,每当你更新其中一个公共项目时,都需要进行外部构建步骤:
docker build -t me/myproj:commons .
然后,你的组合应用程序可以依赖于commons
镜像,而不是golang
镜像,并且可以像正常构建一样进行构建,而无需使用卷。
FROM me/myproj:commons
...
英文:
You could build an image including commons1
and commons2
that your other images are based on.
FROM golang:1.8.0
RUN mkdir -p /go/src/myproj/commons1 && mkdir -p /go/src/myproj/commons2
COPY commons1/ /go/src/myproj/commons1/
COPY commons2/ /go/src/myproj/commons2/
The downside is this requires an external build step whenever you update one of the common projects:
docker build -t me/myproj:commons .
Then your compose apps can rely on the commons image instead of golang
and build as normal without the volumes.
FROM me/myproj:commons
...
答案2
得分: 0
问题出在go get -d -v
命令上,因为它抱怨myproj/commons1
没有安装在$GOPATH/src
中。我怀疑这是因为Docker Compose在运行docker-compose build
之前没有挂载我之前提到的卷。所以我在我的docker-compose.yml
中做了一个变通的解决方法,但是这远非优雅:
version: '2'
services:
module1:
volumes:
- ./commons1:/go/src/myproj/commons1
build: module1/
ports:
- "8080:8080"
command: bash -c "go get -d -v && go install -v && /go/bin/app"
显然,这远非理想,因为每次我运行docker-compose up
时,我的Go二进制文件都会被重新构建,而不管我是否运行了docker-compose build
。
这也是有问题的,因为我想在某些容器中使用dockerize
,以等待另一个容器完全启动,现在我觉得这变得非常混乱。
英文:
So problem was the go get -d -v
command since it was complaining myproj/commons1
wasn't installed in $GOPATH/src
basically. This I of course suspect was because Docker Compose wasn't mounting the volumes I mentioned before it ran the go get
on docker-compose build
so I made a work around in my docker-compose.yml
but it is far from elegant:
version: '2'
services:
module1:
volumes:
- ./commons1:/go/src/myproj/commons1
build: module1/
ports:
- "8080:8080"
command: bash -c "go get -d -v && go install -v && /go/bin/app
This is obviously far from ideal because my Go binary is rebuilt every time I do a docker-compose up
regardless of whether or not I ran docker-compose build
.
This is also problematic because I wanted to use dockerize
for certain containers to wait until another container has started up completely and it becomes quite messy now I think.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论