英文:
Dockerfile for Go project of two runnables with shared packages
问题
我有一个包含客户端-服务器和多个共享文件的项目。我正在尝试为客户端和服务器创建Docker镜像,并且在编写Dockerfile方面遇到了困难。
我查看了在线资源,其中大多数包括非常简单的项目或者项目太大,对此问题没有帮助。
我的项目结构遵循标准的项目布局:
项目
-api
-api.go
-cmd
-client
-client.go
-server
-server.go
-configs
-configuration.yaml
-internal
-client_int
-client_logic.go
-server_int
-server_logic.go
-shared_int
-shared_logic.go
-Dockerfile
-go.mod
请问有人能够就项目结构提供建议/评论,或者有一个类似的Dockerfile示例吗?
谢谢。
*我查阅了许多在谷歌上出现的教程,或者使用简单的GitHub关键词。
英文:
I am have a project that includes a client-server with multiple shared files. I am trying to create docker images for the client and server, and struggling with writing the dockerfile.
I have looked at online sources which mostly include very simple projects or projects that are too big and weren't helpful on this matter.
My project structure is following the standard project layout:
Project
-api
-api.go
-cmd
-client
-client.go
-server
-server.go
-configs
-configuration.yaml
-internal
-client_int
-client_logic.go
-server_int
-server_logic.go
-shared_int
-shared_logic.go
-Dockerfile
-go.mod
Would anyone please be able to advise/comment on the project structure or have a similar dockerfile as example?
Thanks.
*I looked into many tutorials that come up on google or with simple github keywords.
答案1
得分: 1
在这个(非常正常的)项目布局中,有两个重要的细节:
- 当构建镜像时,上下文目录(Compose 的
build: { context: }
,或者docker build
命令的目录参数)必须是顶级的Project
目录。 - 无论 Dockerfile 实际上位于哪里,
COPY
指令的左侧必须相对于Project
目录(即前面提到的上下文目录)。
对于如何构建 Docker 镜像,有一些选择。你可以构建一个包含客户端和服务器的镜像,或者为每个部分构建一个单独的镜像,你可以将 Dockerfile 放在顶级目录或相关的 cmd
子目录中;对于这样的项目,我认为没有一种标准的方法来做。
为了选择一种方法(绝不是“最佳”方法,但是可以工作的方法),假设我们为每个部分创建单独的镜像;但是,由于代码共享很多,你基本上需要将整个源代码树复制到进行镜像构建的位置。
# cmd/server/Dockerfile
# 构建阶段:
FROM golang:alpine AS build
WORKDIR /build
# 首先安装库依赖
# (这些依赖项下载和更改的成本很高;
# 一次性完成这些操作可以节省重新构建的时间)
COPY go.mod go.sum .
RUN go mod install
# 将整个应用程序树复制进来
COPY . .
# 构建我们想要运行的特定组件
RUN go build -o server ./cmd/server
# 最终的运行时镜像:
FROM alpine
# 获取构建的二进制文件
COPY --from=build /build/server /usr/bin
# 并将其设置为主要的容器命令
CMD ["server"]
也许你正在通过 Docker Compose 运行这个项目:
version: '3.8'
services:
server:
build:
context: .
dockerfile: cmd/server/Dockerfile
ports:
- 8000:8000
client:
build:
context: .
dockerfile: cmd/client/Dockerfile
environment:
SERVER_URL: 'http://server:8000'
请注意,两个镜像都将项目根目录指定为构建的 context:
,但是为每个镜像指定了不同的 dockerfile:
。
英文:
With this (very normal) project layout, there are two important details:
- When you build the image, the context directory (the Compose
build: { context: }
, or thedocker build
directory argument) must be the top-levelProject
directory. - Wherever the Dockerfile physically is, the left-hand side of any
COPY
instructions must be relative to theProject
directory (the context directory from the previous point).
There are some choices on how to build Docker images out of this. You could build one image with both the client and server, or a separate image for each, and you could put the Dockerfile(s) at the top directory or in the relevant cmd
subdirectory; for a project like this I don't think there's a standard way to do it.
To pick an approach (by no means "the best" approach, but one that will work) let's say we create separate images for each part; but, since so much code is shared, you basically need to copy the whole source tree in to do the image build.
# cmd/server/Dockerfile
# Build-time stage:
FROM golang:alpine AS build
WORKDIR /build
# First install library dependencies
# (These are expensive to download and change rarely;
# doing this once up front saves time on rebuilds)
COPY go.mod go.sum .
RUN go mod install
# Copy the whole application tree in
COPY . .
# Build the specific component we want to run
RUN go build -o server ./cmd/server
# Final runtime image:
FROM alpine
# Get the built binary
COPY --from=build /build/server /usr/bin
# And set it as the main container command
CMD ["server"]
And maybe you're running this via Docker Compose:
version: '3.8'
services:
server:
build:
context: .
dockerfile: cmd/server/Dockerfile
ports:
- 8000:8000
client:
build:
context: .
dockerfile: cmd/client/Dockerfile
environment:
SERVER_URL: 'http://server:8000'
Note that both images specify the project root directory as the build context:
, but then specify a different dockerfile:
for each.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论