Alpine vs Debian/Ubuntu package or binary incompatibility

A CI build or container fails because it mixes Alpine Linux (musl libc) and Debian/Ubuntu (glibc) artifacts.

alpine-debian-incompatibility medium confidence build docker

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:

  1. A glibc-linked binary runs inside an Alpine container
  2. Node.js native addons compiled on glibc cannot load on musl
  3. A Dockerfile switches base image from ubuntu to alpine without updating apt-get install commands to apk 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

  1. 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
    
  2. 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
    
  3. Fix package names when switching between Alpine and Debian:

    DebianAlpine
    apt-getapk
    libssl-devopenssl-dev
    libpq-devpostgresql-dev
    build-essentialbuild-base
    ca-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
    
  4. 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/server inside the container and confirm it resolves to the correct libc (ld-musl-x86_64.so.1 on 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=0 in 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.

Try it on your own failed log

$ faultline analyze failed.log
Want this across every CI run? Faultline Teams tracks recurring failures across all your repos and surfaces patterns in a shared dashboard.