Matched signals
- libc.musl
- error loading shared libraries
- not a valid ELF file
- apk add.*not found
- no such package
- apk: command not found
- apt-get: command not found
- APKINDEX.*fetch failed
Alpine vs Debian/Ubuntu package or binary incompatibility
What this failure means
A CI build or container fails because it mixes Alpine Linux (musl libc) and
Debian/Ubuntu (glibc) artifacts. Pre-compiled binaries or native extensions
linked against glibc crash on Alpine’s musl libc, and package names may
differ between apk (Alpine) and apt (Debian/Ubuntu).
Symptoms
Faultline looks for one or more of these log fragments:
libc.musl
error loading shared libraries
not a valid ELF file
apk add.*not found
no such package
apk: command not found
apt-get: command not found
APKINDEX.*fetch failed
Diagnosis
Alpine Linux uses musl libc instead of glibc. Most pre-compiled binaries
distributed on the internet are glibc-linked and will not run on Alpine.
Additionally, Alpine packages are managed with apk, not apt, and
many package names differ.
Common failure patterns:
- A glibc-linked binary runs inside an Alpine container
- Node.js native addons compiled on glibc cannot load on musl
- A Dockerfile switches base image from
ubuntutoalpinewithout updatingapt-get installcommands toapk add
Check the binary’s libc requirement:
# Inside the container
ldd /app/server
# If output shows "/lib/x86_64-linux-gnu/libc.so.6" → glibc binary
# Alpine's musl: "/lib/ld-musl-x86_64.so.1"
file /app/server
# Shows "dynamically linked" and the interpreter path
Fix steps
-
Use a glibc base image if the application requires glibc-linked libraries:
# Switch from Alpine FROM alpine:3.19 # musl # To Debian slim for a smaller glibc image FROM debian:bookworm-slim # glibc # Or Ubuntu minimal FROM ubuntu:24.04 -
Compile for musl if staying on Alpine:
# Go: produces statically-linked binary (no libc dependency) CGO_ENABLED=0 GOOS=linux go build -o server ./cmd/server# Multi-stage: compile on glibc builder, copy to Alpine FROM golang:1.22 AS builder RUN CGO_ENABLED=0 go build -o /server ./cmd/server FROM alpine:3.19 COPY --from=builder /server /server # works: no glibc dependency -
Fix package names when switching between Alpine and Debian:
Debian Alpine apt-getapklibssl-devopenssl-devlibpq-devpostgresql-devbuild-essentialbuild-baseca-certificatesca-certificates# Debian/Ubuntu RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev ca-certificates && rm -rf /var/lib/apt/lists/* # Alpine RUN apk add --no-cache openssl-dev ca-certificates -
For Node.js native addons on Alpine, add the build tools and rebuild:
FROM node:20-alpine RUN apk add --no-cache python3 make g++ RUN npm install --build-from-source
Validation
- Run
ldd /app/serverinside the container and confirm it resolves to the correct libc (ld-musl-x86_64.so.1on Alpine). - Run the container and confirm the application starts.
- Re-run the CI pipeline.
Why it matters
Alpine is popular for small Docker images but its musl libc is not binary compatible with the glibc ecosystem and most pre-built language binaries. Mixing them produces cryptic errors that appear to be missing libraries but are actually a libc ABI incompatibility.
Prevention
- Choose a base image and commit to it; keep it consistent across builder and final stages.
- Use statically-linked binaries (
CGO_ENABLED=0in Go) when using Alpine final stages. - Test the final image by running the application, not just checking that it builds.
How Faultline detects it
Use faultline explain alpine-debian-incompatibility to see the full playbook.
faultline analyze build.log
faultline explain alpine-debian-incompatibility
Generated from playbooks/bundled/log/build/alpine-debian-incompatibility.yaml. Do not edit directly.