Support Alpine Linux (no glibc, musl libc)
Description
unable to run application on a docker alpine image.
Basic info
Hi guys I'm using the last version of golang objectbox library. I would like to run my application on a alpine docker image but I'm not able to do it.
I'm getting the following error:
2025/03/15 14:55:44 ObjectBox Go Quickstart panic: Could not create box for entity ID 1: No error information
goroutine 1 [running]: github.com/objectbox/objectbox-go/objectbox.(*ObjectBox).InternalBox(0xc0000164b0?, 0x1) /go/pkg/mod/github.com/objectbox/[email protected]/objectbox/objectbox.go:198 +0xaa objectbox-test/model.BoxForTask(...) /usr/bin/model/model.obx.go:146 main.main() /usr/bin/main.go:22 +0xd7
How to reproduce
Steps to reproduce the behavior:
- docker buildx build -f ./build/Dockerfile --platform linux/amd64 -t objbectbox-test:latest --load .
- docker run test-objectbox
I attached my demo apps
Thanks for reporting! I don't see anything obvious in the example and it runs fine on Ubuntu 24.04.
So maybe Alpine Linux is missing some libraries or this is maybe a permission issue? Are there any additional logs that can help you diagnose?
I ran your issue through AI; here's the relevant part:
Alpine Linux uses musl libc instead of glibc, which can sometimes cause compatibility issues with libraries that have C dependencies. ObjectBox might be one such library.
Here are a few suggestions to troubleshoot this:
- Make sure you're including any necessary build dependencies in your Docker image. ObjectBox might require specific libraries that aren't included in the Alpine base image.
- Try using a non-Alpine base image like golang:1.20 instead of golang:1.20-alpine to see if the issue is indeed related to Alpine.
I can confirm that ObjectBox for Linux depends on glibc.
PS.: With that info, it might be possible to find workarounds. E.g. try this before running ObjectBox:
RUN apk add --no-cache gcompat
Please let us know if you find a working workaround.
Hy guys I already tried with gcompat but it doesn't work. the only way that i found is that one:
FROM --platform=${BUILDPLATFORM} tonistiigi/xx:latest AS xx
FROM --platform=${BUILDPLATFORM} golang:latest AS build
ARG TARGETPLATFORM
ARG TARGETARCH
# Set the Current Working Directory inside the container
WORKDIR /bin
COPY --from=xx / /
RUN xx-go --wrap
RUN set -e ; xx-apt-get install -y binutils gcc libc6-dev libstdc++6 libgcc-s1
# Copy go mod and sum files
COPY . .
# Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed
RUN go mod download
# export CGO_LDFLAGS="-L/home/vinz/go-workspace/objectbox-test/deps -Wl,-rpath -Wl,\$ORIGIN/deps"
ENV CGO_ENABLED=1
ENV CGO_LDFLAGS="-Wl,-rpath -Wl,\$ORIGIN/deps"
# Build the Go app
RUN if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc; fi && \
if [ "$TARGETARCH" = "arm64" ]; then export OBJECTBOX_ARCH=aarch64; else export OBJECTBOX_ARCH=x64; fi && \
mkdir objectboxlib && cd objectboxlib && wget https://github.com/objectbox/objectbox-c/releases/download/v4.2.0/objectbox-linux-$OBJECTBOX_ARCH.tar.gz && \
tar -xf objectbox-linux-$OBJECTBOX_ARCH.tar.gz && cp include/* /usr/include && cp lib/* /usr/lib && cd .. && \
go build --ldflags="-w -s" -o objectbox-test . && xx-verify objectbox-test
RUN if [ "$TARGETARCH" = "arm64" ]; then mkdir -p deps/lib/aarch64-linux-gnu && \
cp /lib/aarch64-linux-gnu/libgcc_s.so.1 deps/lib/aarch64-linux-gnu/ && \
cp /lib/aarch64-linux-gnu/libstdc++.so.6 deps/lib/aarch64-linux-gnu/ && \
cp /lib/aarch64-linux-gnu/libc.so.6 deps/lib/aarch64-linux-gnu/ && \
cp /lib/aarch64-linux-gnu/libdl.so.2 deps/lib/aarch64-linux-gnu/ && \
cp /lib/aarch64-linux-gnu/libm.so.6 deps/lib/aarch64-linux-gnu/ && \
cp /lib/aarch64-linux-gnu/libpthread.so.0 deps/lib/aarch64-linux-gnu/ && \
cp /lib/ld-linux-aarch64.so.1 deps/lib; else mkdir -p deps/lib/x86_64-linux-gnu && mkdir -p deps/lib64 && \
cp /lib/x86_64-linux-gnu/libc.so.6 deps/lib/x86_64-linux-gnu/ && \
cp /lib/x86_64-linux-gnu/libdl.so.2 deps/lib/x86_64-linux-gnu/ && \
cp /lib/x86_64-linux-gnu/libstdc++.so.6 deps/lib/x86_64-linux-gnu/ && \
cp /lib/x86_64-linux-gnu/libm.so.6 deps/lib/x86_64-linux-gnu/ && \
cp /lib/x86_64-linux-gnu/libgcc_s.so.1 deps/lib/x86_64-linux-gnu/ && \
cp /lib/x86_64-linux-gnu/libpthread.so.0 deps/lib/x86_64-linux-gnu/ && \
cp /lib64/ld-linux-x86-64.so.2 deps/lib64; fi && \
cp /lib/libobjectbox.so deps/lib/
FROM --platform=${TARGETARCH} alpine:latest AS base
#RUN apk update && apk add --no-cache \
# libc6-compat gcompat libgcc libstdc++
# For users that wish to run containers as a non-root user,
# provide a default unprivileged user such that the default paths
#ARG UID=1000
#ARG GID=1000
# objectbox-test
FROM base AS objectbox-test
COPY --from=build /bin/objectbox-test .
COPY --from=build /bin/deps /
#USER ${UID}:${GID}
# Command to run the executable
CMD ["./objectbox-test"]
is already attached on the .zip that I uploaded, is named as 'Dockerfile.work'
Great, thanks for pointing out that previously hidden gem!
May I ask your motivation to use alpine? Anything else than being small?
As an alternative, one could use e.g. Rocky Minimal, e.g. FROM rockylinux/rockylinux:8.10-minimal, which is around 35 MB (compressed), which may be OK for some use cases (note: 9.x is ~10 MB larger).
Yes, the primary reason is its small size. I believe the errors I encountered were due to differing library versions between the Debian and Alpine images. The Alpine image likely contains newer versions.
FROM --platform=${BUILDPLATFORM} tonistiigi/xx:latest AS xx
FROM --platform=${BUILDPLATFORM} golang:latest AS build
ARG TARGETPLATFORM
ARG TARGETARCH
# Set the Current Working Directory inside the container
WORKDIR /bin
COPY --from=xx / /
RUN xx-go --wrap
RUN set -e ; xx-apt-get install -y binutils gcc libc6-dev libstdc++6 libgcc-s1
# Copy go mod and sum files
COPY . .
# Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed
RUN go mod download
# export CGO_LDFLAGS="-L/home/vinz/go-workspace/objectbox-test/deps -Wl,-rpath -Wl,\$ORIGIN/deps"
ENV CGO_ENABLED=1
ENV CGO_LDFLAGS="-Wl,-rpath -Wl,\$ORIGIN/deps"
# Build the Go app
RUN if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc; fi && \
if [ "$TARGETARCH" = "arm64" ]; then export OBJECTBOX_ARCH=aarch64; else export OBJECTBOX_ARCH=x64; fi && \
mkdir objectboxlib && cd objectboxlib && wget https://github.com/objectbox/objectbox-c/releases/download/v4.2.0/objectbox-linux-$OBJECTBOX_ARCH.tar.gz && \
tar -xf objectbox-linux-$OBJECTBOX_ARCH.tar.gz && cp include/* /usr/include && cp lib/* /usr/lib && cd .. && \
go build --ldflags="-w -s" -o objectbox-test . && xx-verify objectbox-test
FROM --platform=${TARGETARCH} alpine:latest AS base
RUN apk update && apk add --no-cache \
libc6-compat gcompat libgcc libstdc++
# For users that wish to run containers as a non-root user,
# provide a default unprivileged user such that the default paths
#ARG UID=1000
#ARG GID=1000
# objectbox-test
FROM base AS objectbox-test
COPY --from=build /bin/objectbox-test .
COPY --from=build /lib/libobjectbox.so /deps/
#USER ${UID}:${GID}
# Command to run the executable
CMD ["./objectbox-test"]
Attached is the Dockerfile that produces the errors I previously reported. As mentioned, the build process completes without errors; the errors only occur when running the container. I suspect the issue stems from the differing versions of libgcc and libstdc++ libraries between the Alpine and Debian-based images.
Some background info... In the standard builds, ObjectBox links with older version of glibc etc. for better backward compatibility. E.g. you run it on systems with at least glibc 2.28 and GLIBCXX 3.4.25.