英文:
How can I fix my docker build failing while my go build succeeds? Dockerfile includes go mod download
问题
我正在使用"github.com/confluentinc/confluent-kafka-go/kafka"作为一个非常简单的消费者。这基本上就是confluent作为kafka/go教程提供的内容。
"go build ."和"go run ."都成功了,但"docker build ."没有成功。
错误信息如下:
> [builder 7/7] RUN go build -o /app/bin/main .:
#12 9.826 # gitlab.com/.....
#12 9.826 ./main.go:24:24: undefined: kafka.ConfigMap
#12 9.826 ./main.go:30:18: undefined: kafka.NewConsumer
这是我的Dockerfile:
FROM golang:1.20.2-alpine3.16 AS builder
RUN apk --update add git
WORKDIR /app
COPY go.mod go.sum /app/
RUN go mod download
COPY . .
RUN go build -o /app/bin/main .
FROM scratch
WORKDIR /app
COPY --from=builder /app/bin/main /app/bin/main
ENTRYPOINT ["/app/bin/main"]
我对为什么会发生这种情况感到困惑,特别是它声称包中的一些函数未定义。我在代码中没有重新声明"kafka"。
英文:
I am using "github.com/confluentinc/confluent-kafka-go/kafka" in a very simple consumer. It's pretty much what confluent has as a kafka/go tutorial.
"go build ." and "go run ." succeed, "docker build ." does not.
The error is:
> [builder 7/7] RUN go build -o /app/bin/main .:
#12 9.826 # gitlab.com/.....
#12 9.826 ./main.go:24:24: undefined: kafka.ConfigMap
#12 9.826 ./main.go:30:18: undefined: kafka.NewConsumer
Here is my Dockerfile:
FROM golang:1.20.2-alpine3.16 AS builder
RUN apk --update add git
WORKDIR /app
COPY go.mod go.sum /app/
RUN go mod download
COPY . .
RUN go build -o /app/bin/main .
FROM scratch
WORKDIR /app
COPY --from=builder /app/bin/main /app/bin/main
ENTRYPOINT ["/app/bin/main"]
I am at a loss as to why this happens, especially since it claims that some functions in the package are undefined. I have not redeclared "kafka" anywhere in my code.
答案1
得分: 4
如Zeke在评论中正确指出的那样,Kafka Go客户端中包含了Kafka二进制文件,因此请查看我在更新部分中演示的情况。
这是因为您需要本机(C/C++)的librdkafka依赖项才能构建它。这在大多数情况下都意味着需要安装gcc
。这是您的代码使用的底层Kafka库。
您还需要让go build知道这一点。我在您的示例中添加并修改了这两行,并成功构建了它。
# 添加这一行
RUN apk add alpine-sdk
# 修改这一行
RUN GOOS=linux GOARCH=amd64 go build -tags musl -o /app/bin/main .
功能示例:
FROM golang:1.20.2-alpine3.16 AS builder
RUN apk add alpine-sdk
RUN apk --update add git
WORKDIR /app
COPY . .
RUN go mod download
RUN GOOS=linux GOARCH=amd64 go build -tags musl -o /app/bin/main .
FROM scratch
WORKDIR /app
COPY --from=builder /app/bin/main /app/bin/main
ENTRYPOINT ["/app/bin/main"]
我使用了这个快速入门的代码,构建过程没有问题。
更新
正如Zeke指出的那样,Kafka已经有了预构建的二进制文件。
下面是Dockerfile的详细说明:
gcc
和musl-dev
是使用所选镜像进行编译所需的。- go build
-tags musl
选项用于Alpine,根据Kafka SDK文档。 -ldflags '-extldflags "-static"'
将所有内容静态编译为单个二进制文件,包括依赖项。这将包括C标准库,将保持scratch镜像的干净。如果选择动态方式,则必须直接将依赖项添加到scratch镜像部分。
生成大小约为10MB的镜像的Dockerfile:
FROM golang:1.20.4-alpine3.17 AS builder
RUN apk add --no-progress --no-cache gcc musl-dev
WORKDIR /build
COPY . .
RUN go mod download
RUN go build -tags musl -ldflags '-extldflags "-static"' -o /build/main
FROM scratch
WORKDIR /app
COPY --from=builder /build/main .
ENTRYPOINT ["/app/main"]
在我的demo中运行时,使用测试代码与Kafka的集成是成功的。
英文:
> As correctly pointed out by Zeke in the comments, Kafka binaries are included in the Kafka Go client, so check out the Update section where I demonstrate such scenario.
That's because you need the native (C/C++) librdkafka. dependencies in order to build it. That will imply in most cases having gcc
available as well. That's the underlying Kakfa lib used by your code.
You also need to make go build aware of that. I've added and modified these two lines on your example and was able to build it.
# Add this
RUN apk add alpine-sdk
# Change this
RUN GOOS=linux GOARCH=amd64 go build -tags musl -o /app/bin/main .
Functional example:
FROM golang:1.20.2-alpine3.16 AS builder
RUN apk add alpine-sdk
RUN apk --update add git
WORKDIR /app
COPY . .
RUN go mod download
RUN GOOS=linux GOARCH=amd64 go build -tags musl -o /app/bin/main .
FROM scratch
WORKDIR /app
COPY --from=builder /app/bin/main /app/bin/main
ENTRYPOINT ["/app/bin/main"]
I've used this quickstart code and the build process was OK.
Update
As Zeke pointed out, Kafka already has the prebuilt binaries.
Breaking down the Dockerfile below:
gcc
andmusl-dev
are required for compilation using the selected image.- go build
-tags musl
option for Alpine, as per the Kafka SDK docs. -ldflags '-extldflags "-static"'
will statically compile everything in a single binary, including the dependencies. This will include for example C std lib, and will keep the scratch image clean. If dynamic is chosen, then one has to add the dependencies to the scratch image section directly.
The Dockerfile which generated the image with ~10MB size:
FROM golang:1.20.4-alpine3.17 AS builder
RUN apk add --no-progress --no-cache gcc musl-dev
WORKDIR /build
COPY . .
RUN go mod download
RUN go build -tags musl -ldflags '-extldflags "-static"' -o /build/main
FROM scratch
WORKDIR /app
COPY --from=builder /build/main .
ENTRYPOINT ["/app/main"]
Integration with Kafka using test code was successful when running in my demo.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论