如何使用多个Go模块组织项目并使用Docker compose?

nc1teljy  于 2023-04-09  发布在  Go
关注(0)|答案(1)|浏览(136)

我是Go的新手,对于如何用自己的多个模块构建一个项目并在docker compose中使用它们感到困惑。该项目目前是一个包含两个模块的git仓库:一个API和一个处理器,用于长时间运行的工作,每个都运行在自己的容器中。RabbitMQ用作两者之间的工作队列,还有一个MySQL数据库。
项目结构的简化视图:

├── api
│   ├── Dockerfile
│   └── stuff.go
├── docker-compose.yml
├── go.work
└── processor
    ├── Dockerfile
    └── stuff.go

API Dockerfile(除了“api”是“processor”之外,处理器文件是相同的):

FROM golang:1.20

WORKDIR /usr/src/app

COPY go.mod go.sum ./
RUN go mod download && go mod verify

COPY . .
RUN go build -v -o /usr/local/bin/ ./...

CMD [ "api" ]

简化的docker-compose.yml:

version: '3.8'

services:
  api:
    build:
      context: ./api
      ...

  processor:
    build:
      context: ./processor
      ...

  rabbitmq:
    image: rabbitmq:3.11-management
    ...

  mysql:
    image: mysql:8.0
    ...

我用docker compose up --build运行它,它工作得很好。问题是两个模块中有一些属于共享模块的重复代码,但我不知道如何在仍然能够在本地构建和工作的情况下做到这一点。
通过研究,我得到的印象是,我的模块应该在自己的存储库中。如果我这样做,似乎我需要为docker-compose.yml创建一个“项目”存储库,然后为共享模块创建另一个。然后我更新docker-compose.yml上下文,以指向在本地工作时克隆API和处理器项目的位置。
问题是共享模块没有Dockerfile,也不是docker-compose.yml中的服务。我假设Docker在构建时会go get共享模块的内容,但我仍然希望能够在本地处理该代码,而不必首先提交并将其推送到origin。

ux6nzvsh

ux6nzvsh1#

我会在这里忽略Docker。
按照普通Go应用程序的方式排列文件系统树,按照计划打包和分发文件系统树。你应该能够使用普通的go testgo build命令进行开发。听起来你有多个顶级命令围绕着一个共享代码库;将它们放在一个存储库中是有意义的,但是请记住,每个顶级命令都需要自己的目录。
如果你有一个这样的设置,并且你想在Docker中运行它,重要的细节是你需要传递整个源代码树作为构建上下文目录。每个应用程序的Dockerfile是可以的,并且有一个参数可以将它放在与其顶级应用程序相同的目录中。但是当你在Compose中声明它时,你必须告诉它项目根目录是构建上下文。
我将docker-compose.yml文件放在项目根目录下,紧挨着go.mod文件。它可能看起来像:

version: '3.8'
services:
  api:
    build:
      context: .
      dockerfile: ./cmd/api/Dockerfile
    ports: ['8000:8000']
  processor: { ... }
  rabbitmq: { ... }
  mysql: { ... }

您的Dockerfiles看起来基本上与您已经展示的一样。由于构建上下文是项目根,因此所有COPY命令都相对于项目根启动;另一方面,无论构建哪个应用程序,你都需要复制整个源代码树。对于Go,我几乎总是使用多阶段构建,以避免在最终图像中包含工具链。

# cmd/api/Dockerfile; but built with a context of the project root
FROM golang:1.20 AS builder

WORKDIR /usr/src/app

COPY go.mod go.sum ./
RUN go mod download && go mod verify

COPY . .
RUN go build -o api ./cmd/api

FROM ubuntu:22.04  # "alpine" or "not alpine" must match build stage
COPY --from=builder /usr/src/app/api /usr/local/bin/
CMD ["api"]

相关问题