英文:
How to rebuild go project efficiently while using Docker Compose?
问题
这可能是一个愚蠢的问题,但我刚开始使用Docker-compose。到目前为止,我很喜欢它...但是构建时间很长。我的项目有几个依赖项,每次我进行更改时,我需要重新构建源代码。现在,我调用docker-compose build
来重新构建容器,然后再调用docker-compose up
。问题是:
-
每次我对源代码进行更改时,它都会重新构建整个容器(这需要很长时间--获取依赖项等)。这严重拖慢了我的速度。
-
我真的觉得我应该只需在容器上运行一个命令来重新构建并重新运行可执行文件,像这样:
docker-compose run web go build .
docker-compose run web ./app
或者
docker-compose run web go build .
docker-compose restart
这应该可以工作,因为我使用了一个卷来在主机和容器之间共享代码。不应该需要重新获取所有的依赖项。它不应该使用新构建的可执行文件吗?然而,这样做并没有反映出构建的更改,并且端口转发似乎出现了问题。
供参考,这是我的_Dockerfile_:
FROM golang:1.8
COPY . /go/src/github.com/codeblooded/test1
WORKDIR /go/src/github.com/codeblooded/test1
RUN echo $PATH
RUN go get -d -v ./...
RUN go install -v ./...
RUN go build -o test1 .
CMD ["test1"]
EXPOSE 3470
以及我的_docker-compose.yml_文件:
version: '3'
services:
postgres:
image: postgres
volumes:
- ./db/data/psql:/var/lib/postgresql/data
- ./db/schema:/db/schema
redis:
image: redis
volumes:
- ./db/data/redis:/data
server:
build: .
command: test1
volumes:
- .:/go/src/github.com/codeblooded/test1
ports:
- "3470:3470"
depends_on:
- postgres
- redis
我是否漏掉了什么?
英文:
This may be a stupid question, but I'm new to using Docker-compose. So far, I love it... but I'm having some long build times. I have a project with several dependencies, and I need to obviously rebuild the source every time I make a change. Right now, I'm calling docker-compose build
to rebuild the container, followed by a docker-compose up
. The problem is:
-
It's rebuilding the entire container for every change I make to the source code (which takes a long time -- fetching dependencies/etc). This is significantly slowing me down.
-
I really feel like I should just be able to run a command on the container to rebuild and then re-run the executable, like-so: <pre>
docker-compose run web go build .
docker-compose run web ./app</pre> or <pre>
docker-compose run web go build .
docker-compose restart
</pre> This should work because I'm using a volume to share code amongst the host and container. There shouldn't be a need to refetch all the dependencies. Shouldn't it use the freshly built executable? However, this does not reflect the built changes and port forwarding appears to break.
For reference, here is my Dockerfile:
FROM golang:1.8
COPY . /go/src/github.com/codeblooded/test1
WORKDIR /go/src/github.com/codeblooded/test1
RUN echo $PATH
RUN go get -d -v ./...
RUN go install -v ./...
RUN go build -o test1 .
CMD ["test1"]
EXPOSE 3470
And my docker-compose.yml file:
version: '3'
services:
postgres:
image: postgres
volumes:
- ./db/data/psql:/var/lib/postgresql/data
- ./db/schema:/db/schema
redis:
image: redis
volumes:
- ./db/data/redis:/data
server:
build: .
command: test1
volumes:
- .:/go/src/github.com/codeblooded/test1
ports:
- "3470:3470"
depends_on:
- postgres
- redis
Is there something I'm missing?
答案1
得分: 12
你提出了一个很好的问题。
在Dockerfile中,命令的顺序确实很重要。首先放置那些不经常更改的内容,然后是那些在每次构建中最有可能更改的内容:
FROM golang:1.8
RUN go get -d -v ./...
RUN go install -v ./...
COPY . /go/src/github.com/codeblooded/test1
WORKDIR /go/src/github.com/codeblooded/test1
RUN echo $PATH
RUN go build -o test1 .
CMD ["test1"]
EXPOSE 3470
当与上一次构建相比发生了层的更改时,Docker会丢弃以下缓存的层并重新运行它们,有时会浪费你的时间。
请注意,docker在每个从上一次构建中重新使用的层中输出的“Using cache”语句。
另一个建议是,在开发工作中,使用fresh可以在每次更改代码时自动重新构建你的go应用程序。只需在容器中安装它,并在docker-compose.yml中使用command: fresh
即可。
英文:
You have asked a good question.
The command's order in the Dockerfile really matters. Put first the things that don't change frequently, and later those that are most likely to change in every build:
FROM golang:1.8
RUN go get -d -v ./...
RUN go install -v ./...
COPY . /go/src/github.com/codeblooded/test1
WORKDIR /go/src/github.com/codeblooded/test1
RUN echo $PATH
RUN go build -o test1 .
CMD ["test1"]
EXPOSE 3470
When a layer change regarding the previous build, docker discards the following cached layers and runs them again, sometimes wasting your time.
Pay attention to the "Using cache" sentence that docker outputs in each layer that is re-used from the previous build.
Another recommendation, for your dev work, use fresh to re-build your go app automatically every time you change the code. Just install it in the container and simply using command: fresh
in your docker-compose.yml
答案2
得分: 3
如果你想改进你的Docker实现,你可以制作一个更小的镜像。我建议使用"多阶段构建"来实现这一点。
这个构建的镜像大小大约为600MB
FROM golang:1.8
RUN go get -d -v ./...
RUN go install -v ./...
COPY . /go/src/github.com/codeblooded/test1
WORKDIR /go/src/github.com/codeblooded/test1
RUN echo $PATH
RUN go build -o test1 .
CMD ["test1"]
EXPOSE 3470
使用多阶段构建,镜像的大小只有二进制文件的大小和一个空白镜像
FROM golang:1.8 as builder
RUN go get -d -v ./...
RUN go install -v ./...
COPY . /go/src/github.com/codeblooded/test1
WORKDIR /go/src/github.com/codeblooded/test1
RUN echo $PATH
RUN CGO_ENABLED=0 GOOS=linux go build -o test1 .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /go/src/github.com/codeblooded/
COPY --from=builder /go/src/github.com/codeblooded/test1 .
CMD ["test1"]
EXPOSE 3470
使用多阶段构建,你可以使用一个较大的镜像来构建应用程序,然后使用一个更小的镜像来运行你的应用程序。
英文:
And if you want to improve your Docker impl, you can make a smaller image. I suggest "multi-stage builds" to do that
> The image size for this build is like 600mb
FROM golang:1.8
RUN go get -d -v ./...
RUN go install -v ./...
COPY . /go/src/github.com/codeblooded/test1
WORKDIR /go/src/github.com/codeblooded/test1
RUN echo $PATH
RUN go build -o test1 .
CMD ["test1"]
EXPOSE 3470
> Using multi-stage builds, the image weight is the size of the binary and a scratch
FROM golang:1.8 as builder
RUN go get -d -v ./...
RUN go install -v ./...
COPY . /go/src/github.com/codeblooded/test1
WORKDIR /go/src/github.com/codeblooded/test1
RUN echo $PATH
RUN CGO_ENABLED=0 GOOS=linux go build -o test1 .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /go/src/github.com/codeblooded/
COPY --from=builder /go/src/github.com/codeblooded/test1 .
CMD ["test1"]
EXPOSE 3470
Using multi-stage builds you are using a heavy image for build the app and another really smaller for run your app.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论