confluent-kafka-go: 1.4.0: Building apps fails on latest alpine, when using bundled librdkafka

Description

When using the 1.4.0 release, the bundled librdkafka fails to work as intended with the latest alpine.

How to reproduce

Build an application which uses github.com/confluentinc/confluent-kafka-go, in a container, using the alpine:3.11 image (which, at the time of writing, is actually alpine:3.11.5) as a base. Errors such as the following will be displayed:

 go: downloading github.com/confluentinc/confluent-kafka-go v1.4.0
 # github.com/confluentinc/confluent-kafka-go/kafka
 /usr/lib/gcc/x86_64-alpine-linux-musl/9.2.0/../../../../x86_64-alpine-linux-musl/bin/ld: /go/pkg/mod/github.com/confluentinc/confluent-kafka-go@v1.4.0/kafka/librdkafka/librdkafka_glibc_linux.a(rdkafka_txnmgr.o): in function `rd_kafka_txn_set_fatal_error':
 (.text+0x141): undefined reference to `__strdup'
 /usr/lib/gcc/x86_64-alpine-linux-musl/9.2.0/../../../../x86_64-alpine-linux-musl/bin/ld: /go/pkg/mod/github.com/confluentinc/confluent-kafka-go@v1.4.0/kafka/librdkafka/librdkafka_glibc_linux.a(rdkafka_txnmgr.o): in function `rd_kafka_txn_set_abortable_error':
 (.text+0x64f): undefined reference to `__strdup'
...

Installing a fresh build of librdkafka 1.4.0 into the container and building the application with -tags dynamic resolves the issue.

Could possibly be because the bundled librdkafka was built from a :edge release of alpine, instead of :latest?

Checklist

Please provide the following information:

  • confluent-kafka-go and librdkafka version (LibraryVersion()): 1.4.0, bundled.
  • Apache Kafka broker version: N/A
  • Client configuration: N/A
  • Operating system: Alpine Linux
  • Provide client logs (with "debug": ".." as necessary): N/A
  • Provide broker log excerpts: N/A
  • Critical issue: No

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 3
  • Comments: 28 (7 by maintainers)

Commits related to this issue

Most upvoted comments

You might need -tags musl on those commands too.

Ok seems like this works:

# builder
FROM golang:1.14-alpine AS builder

RUN set -ex &&\
    apk add --no-progress --no-cache \
      gcc \
      musl-dev

WORKDIR /go/src/app
COPY go.* ./
RUN go mod download

COPY . .
RUN go get -d -v
RUN GOOS=linux GOARCH=amd64 go build -a -v -tags musl

e.g. I think the key points:

  • removing the CGO_ENABLED flag
  • adding build tools into the build stage

@bschofield Did you build your application with -tags musl? It seems like it is linking the glibc librdkafka (which references __strdup).

Along these same lines, I can confirm that this worked with golang:1.13.10-alpine3.10 as my builder_base image with librdkafka v1.3.0.

...
RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -tags static_all,netgo -o /bin/app ./cmd/**/main.go

# final stage
FROM alpine:3.10
COPY --from=builder_base /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder_base /bin/app /bin/app

But as soon as I switch to 1.4.0 of confluent-kafka-go, and librdkafka, I get the below error:

BROKERFAIL|rdkafka#consumer-1| [thrd:sasl_ssl://cloud_host:9092/bootstr]: sasl_ssl://cloud_host:9092/bootstrap: failed: err: Local: SSL error: (errno: No error information)

Here’s the base image with the updated versions… For the working version, just substitute the docker image to golang:1.13.10-apine3.11, librdkafka v1.3.0.

FROM golang:1.14.2-alpine3.11 AS go_kafka_base
RUN apk update && apk add --no-cache  \
        bash              \
        build-base        \
        coreutils         \
        gcc               \
        git               \
        make              \
        musl-dev          \
        openssl-dev       \
        openssl           \
        libsasl           \
        libgss-dev        \
        rpm               \
        lz4-dev           \
        zlib-dev          \
        ca-certificates   \
        wget          &&  \
    cd $(mktemp -d) && \
    wget -nv -O cyrus-sasl-2.1.27.tar.gz https://github.com/cyrusimap/cyrus-sasl/releases/download/cyrus-sasl-2.1.27/cyrus-sasl-2.1.27.tar.gz && \
    tar -xz --strip-components=1 -f cyrus-sasl-2.1.27.tar.gz && \
    rm -f cyrus-sasl-2.1.27.tar.gz && \
    ./configure --prefix=/usr --disable-sample --disable-obsolete_cram_attr --disable-obsolete_digest_attr --enable-static --disable-shared \
        --disable-checkapop --disable-cram --disable-digest --enable-scram --disable-otp --disable-gssapi --with-dblib=none --with-pic && \
    make && \
    make install

RUN cd $(mktemp -d) && \
    wget -nv -O v1.4.0.tar.gz https://github.com/edenhill/librdkafka/archive/v1.4.0.tar.gz && \
    tar -xz --strip-components=1 -f v1.4.0.tar.gz && \
    rm -f v1.4.0.tar.gz && \
    ./configure --prefix=/usr --enable-sasl && \
    make -j && \
    make install

I am facing the same issue, from the container I can run go build -a -tags musl and it works fine, but go test ./... -tags musl fails just as as @bulletblp4

what I am missing ?

Fixed by creating a static link

RUN go build -a -tags musl -installsuffix cgo -ldflags '-extldflags "-static"'  -o main myproject.go

After following @lifeofguenter I was able to build but not run the file.

FROM golang:1.14-alpine AS builder

RUN set -ex &&\
    apk add --no-progress --no-cache \
      gcc \
      musl-dev

# Set necessary environmet variables needed for our image

ENV GO111MODULE=on \
    # CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64 \

# Move to working directory /build
WORKDIR /build

# Copy and download dependency using go mod
COPY go.mod .
COPY go.sum .
RUN go mod download

# Copy the code into the container
COPY . .

# Build the application
RUN go get -d -v
RUN go build -a -tags musl -o main myproject.go

# Move to /dist directory as the place for resulting binary folder
WORKDIR /dist

# Copy binary from build to main folder
RUN cp /build/main .

# Build a small image
FROM scratch

COPY --from=builder /dist/main /

# Command to run
ENTRYPOINT ["/main"]

I get the following error on running the file.

standard_init_linux.go:211: exec user process caused "no such file or directory"

I am getting:

./xxx.go:15:9: undefined: kafka.Producer

when building:

FROM golang:1.14-alpine AS builder

WORKDIR /go/src/app
COPY . .
RUN go get -d -v
RUN CGO_ENABLED=0 GOOS=linux go build -a -v -tags musl

I ended up getting past this by continuing to copy the ca-certificates into the docker image as I mentioned earlier, and then making sure the consumer set:

ssl.ca.location=/etc/ssl/certs/ca-certificates.crt

Setting this prior to 1.4.0 was not needed, and instead was able to find the ssl ca on its own.

@edenhill Thanks for the fast response!

I did not use -tags musl. Using -tags musl does indeed fix the issue.

Would it be useful to include a comment about the need to add -tags musl for alpine builds, in https://github.com/confluentinc/confluent-kafka-go/blob/master/README.md#install-the-client? At the moment I see that you do mention it in a separate repo (https://github.com/confluentinc/confluent-kafka-go-example/blob/master/README.md), but you don’t mention it in the main repo README.

similar issue here

from golang:1.14.2 I also can’t install librdkafka 1.4.0 from deb using this manual https://docs.confluent.io/current/installation/installing_cp/deb-ubuntu.html#systemd-ubuntu-debian-install

wget -qO - https://packages.confluent.io/deb/5.4/archive.key | apt-key add -
add-apt-repository "deb [arch=amd64] https://packages.confluent.io/deb/5.4 stable main"
apt-get update && apt-get install librdkafka-dev -y

Result in:

The following packages have unmet dependencies:
 librdkafka-dev : Depends: librdkafka1 (= 1.3.0~1confluent5.4.1-1) but 0.9.3-1 is to be installed
                  Depends: librdkafka++1 (= 1.3.0~1confluent5.4.1-1) but 0.9.3-1 is to be installed
E: Unable to correct problems, you have held broken packages.