Dockerfile for Go project of two runnables with shared packages

huangapple go评论112阅读模式
英文:

Dockerfile for Go project of two runnables with shared packages

问题

我有一个包含客户端-服务器和多个共享文件的项目。我正在尝试为客户端和服务器创建Docker镜像,并且在编写Dockerfile方面遇到了困难。
我查看了在线资源,其中大多数包括非常简单的项目或者项目太大,对此问题没有帮助。

我的项目结构遵循标准的项目布局:

  1. 项目
  2. -api
  3. -api.go
  4. -cmd
  5. -client
  6. -client.go
  7. -server
  8. -server.go
  9. -configs
  10. -configuration.yaml
  11. -internal
  12. -client_int
  13. -client_logic.go
  14. -server_int
  15. -server_logic.go
  16. -shared_int
  17. -shared_logic.go
  18. -Dockerfile
  19. -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:

  1. Project
  2. -api
  3. -api.go
  4. -cmd
  5. -client
  6. -client.go
  7. -server
  8. -server.go
  9. -configs
  10. -configuration.yaml
  11. -internal
  12. -client_int
  13. -client_logic.go
  14. -server_int
  15. -server_logic.go
  16. -shared_int
  17. -shared_logic.go
  18. -Dockerfile
  19. -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

在这个(非常正常的)项目布局中,有两个重要的细节:

  1. 当构建镜像时,上下文目录(Compose 的 build: { context: },或者 docker build 命令的目录参数)必须是顶级的 Project 目录。
  2. 无论 Dockerfile 实际上位于哪里,COPY 指令的左侧必须相对于 Project 目录(即前面提到的上下文目录)。

对于如何构建 Docker 镜像,有一些选择。你可以构建一个包含客户端和服务器的镜像,或者为每个部分构建一个单独的镜像,你可以将 Dockerfile 放在顶级目录或相关的 cmd 子目录中;对于这样的项目,我认为没有一种标准的方法来做。

为了选择一种方法(绝不是“最佳”方法,但是可以工作的方法),假设我们为每个部分创建单独的镜像;但是,由于代码共享很多,你基本上需要将整个源代码树复制到进行镜像构建的位置。

  1. # cmd/server/Dockerfile
  2. # 构建阶段:
  3. FROM golang:alpine AS build
  4. WORKDIR /build
  5. # 首先安装库依赖
  6. # (这些依赖项下载和更改的成本很高;
  7. # 一次性完成这些操作可以节省重新构建的时间)
  8. COPY go.mod go.sum .
  9. RUN go mod install
  10. # 将整个应用程序树复制进来
  11. COPY . .
  12. # 构建我们想要运行的特定组件
  13. RUN go build -o server ./cmd/server
  14. # 最终的运行时镜像:
  15. FROM alpine
  16. # 获取构建的二进制文件
  17. COPY --from=build /build/server /usr/bin
  18. # 并将其设置为主要的容器命令
  19. CMD ["server"]

也许你正在通过 Docker Compose 运行这个项目:

  1. version: '3.8'
  2. services:
  3. server:
  4. build:
  5. context: .
  6. dockerfile: cmd/server/Dockerfile
  7. ports:
  8. - 8000:8000
  9. client:
  10. build:
  11. context: .
  12. dockerfile: cmd/client/Dockerfile
  13. environment:
  14. SERVER_URL: 'http://server:8000'

请注意,两个镜像都将项目根目录指定为构建的 context:,但是为每个镜像指定了不同的 dockerfile:

英文:

With this (very normal) project layout, there are two important details:

  1. When you build the image, the context directory (the Compose build: { context: }, or the docker build directory argument) must be the top-level Project directory.
  2. Wherever the Dockerfile physically is, the left-hand side of any COPY instructions must be relative to the Project 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.

  1. # cmd/server/Dockerfile
  2. # Build-time stage:
  3. FROM golang:alpine AS build
  4. WORKDIR /build
  5. # First install library dependencies
  6. # (These are expensive to download and change rarely;
  7. # doing this once up front saves time on rebuilds)
  8. COPY go.mod go.sum .
  9. RUN go mod install
  10. # Copy the whole application tree in
  11. COPY . .
  12. # Build the specific component we want to run
  13. RUN go build -o server ./cmd/server
  14. # Final runtime image:
  15. FROM alpine
  16. # Get the built binary
  17. COPY --from=build /build/server /usr/bin
  18. # And set it as the main container command
  19. CMD ["server"]

And maybe you're running this via Docker Compose:

  1. version: '3.8'
  2. services:
  3. server:
  4. build:
  5. context: .
  6. dockerfile: cmd/server/Dockerfile
  7. ports:
  8. - 8000:8000
  9. client:
  10. build:
  11. context: .
  12. dockerfile: cmd/client/Dockerfile
  13. environment:
  14. 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.

huangapple
  • 本文由 发表于 2021年7月22日 00:27:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/68473233.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定