docker-alpine-glibc: running glibc binaries on a musl Alpine image
Carefully crafted Alpine Docker image with glibc (~12MB)
At a glance
- What is it?
- frolvlad/alpine-glibc is a Docker base image that adds glibc to Alpine Linux so binaries compiled against glibc, such as OracleJDK or Anaconda, run on a musl system without a full glibc distro. It suits teams that want a small image for a proprietary runtime, and the image is built by compiling glibc from source in three stages, which is why the build takes a while and why the glibc version has to be bumped in several places at once.
- Who is it for?
- Adopt frolvlad/alpine-glibc when you have a glibc linked binary you want to run in a small Alpine image, and pin the glibc version you need rather than tracking latest. Do not adopt it if the underlying program is pure musl or statically linked, because then the added glibc is dead weight in every layer, and check first that the base Alpine version matches what your binary expects, since the image pins Alpine 3.22 while packaging runs on 3.20.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 166 days ago.
- What is it written in?
- Mainly Dockerfile, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The 12MB base image for glibc binaries on a musl kernel
frolvlad/alpine-glibc is a Docker image that starts from Alpine Linux and adds the GNU C library to it. The project description calls it a carefully crafted Alpine Docker image with glibc at roughly 12MB.
The reason it exists is a compatibility mismatch that catches people out. Alpine ships musl libc rather than glibc, and Alpine is popular as a base image because it is small: the README says the Alpine image it is based on is only 5MB. A binary linked against glibc, however, will not run on a musl system out of the box. The README names the specific cases, proprietary projects compiled against glibc such as OracleJDK and Anaconda, and the image exists so that they work on Alpine.
The two libraries have to coexist, and the README says the image includes quirks to make glibc work side by side with musl libc, which is the default in Alpine. The glibc is not installed into the normal system paths. It lives under /usr/glibc-compat, and the build script passes that location through as a prefix directory.
That prefix has a visible consequence for anyone using the image. If you need to update the libc library cache you use /usr/glibc-compat/sbin/ldconfig rather than the usual /sbin/ldconfig, and you can use LD_LIBRARY_PATH as you would on a standard libc based distribution. If you have ever debugged a loader problem in a container, that is the line to look for.
The image is published on Docker Hub as frolvlad/alpine-glibc, and the repository itself is MIT licensed.
Building the image with buildx for two architectures
The image is built with a multi stage Dockerfile, and the documented build command produces both architectures at once:
docker buildx build --platform linux/arm64,linux/amd64 --build-arg GLIBC_VERSION=2.42 -t alpine-glibc:2.42 .Two things in that line matter. The build is a buildx build, so it goes through BuildKit and can emit a multi platform image rather than a single architecture one, and the platforms listed are linux/arm64 and linux/amd64. The second is the build argument: GLIBC_VERSION is passed in, and the tag matches it.
The Dockerfile declares the same version as a default, and that default is the value most builds use:
ARG ALPINE_VERSION=3.22
ARG ALPINE_PACKAGER=3.20
ARG GLIBC_VERSION=2.42Note the split between ALPINE_VERSION and ALPINE_PACKAGER, which are not the same thing. The comment in the Dockerfile explains why: the Alpine 3.20 image is used for packaging because the build script fails for an unknown reason on the newer Alpine versions, and the building Alpine version does not affect the use of the package in a newer Alpine version, so the arrangement is considered safe for now. That is an acknowledged workaround, and the phrase for now is doing real work.
The top of the Dockerfile also carries a maintenance instruction worth heeding if you fork it. Whenever you upgrade the GLIBC version you must update it in all the stages and in the .github/workflows, and whenever you upgrade the Alpine version you update it in stage 3 and in the workflows. The version is repeated in several places, so an upgrade is a multi-file edit rather than a single argument change.
Three build stages: compile glibc, package it, then install it
The Dockerfile structure explains the build time, which is the main practical complaint people have with this image.
Stage 1 is the compiler stage. It starts from ubuntu:24.04 and installs the toolchain glibc needs, namely bison, build-essential, gawk, gettext, openssl, python3, texinfo and wget. It copies in two files from the repository, configparams and builder, then runs the builder script with the prefix set:
COPY configparams /glibc-build/configparams
COPY builder /builder
ARG GLIBC_VERSION
RUN env PREFIX_DIR=/usr/glibc-compat /builderBuilding glibc from source on an Ubuntu base is the slow part, and it is why a plain local `docker build` of this image takes far longer than most.
Stage 2 is the packaging stage. It uses the Alpine 3.20 image, installs alpine-sdk with coreutils, cmake and sudo, creates a builder user in the abuild group, and generates a signing key so the produced package can be installed with apk:
FROM alpine:$ALPINE_PACKAGER AS packager
RUN apk --no-cache add alpine-sdk coreutils cmake sudo \
&& adduser -G abuild -g "Alpine Package Builder" -s /bin/ash -D builder \
&& echo "builder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \
&& mkdir /packages \
&& chown builder:abuild /packagesThe signing step matters more than it looks. The package is signed with a key generated at build time, and the public key is copied into /etc/apk/keys, so the final image can verify the package it installs rather than trusting it blindly.
Stage 3 is where the built glibc lands in the final Alpine image, and the repository also ships the supporting pieces for that stage: an `abuilder` script, a `builder` script, an `APKBUILD` file, a `configparams` file and a `glibc-bin.trigger` file. The `ld.so.conf` file at the repository root is the loader configuration that lets the dynamic linker find the glibc libraries in their non standard location.
Using it as a base image for a proprietary runtime
The intended usage is as a parent image, and the README keeps the example deliberately short:
FROM frolvlad/alpine-glibc
COPY ./my_app /usr/local/bin/my_appand then the application image is built in the usual way:
$ docker build -t my_app .The two step split is worth noticing. The `FROM` line is in a Dockerfile you write for your own application, and the second command builds that Dockerfile. You do not add a glibc package to your image, you inherit a base image that already has it.
Two details of the example carry a warning. The application is copied to /usr/local/bin/my_app, a standard location, and the `FROM` line has no tag, which means you get whatever the registry currently serves as the default. For a base image that is rebuilt whenever glibc or Alpine moves, pinning the tag is the difference between a reproducible build and one that changes under you. The tag to pin is the glibc version, as the build command shows with `-t alpine-glibc:2.42`.
The README also points at two existing images that build on this one, as usage examples. `frolvlad/alpine-oraclejdk8` and `frolvlad/alpine-mono` are the OracleJDK and Mono images built on this base, and both have their own GitHub repositories. Those are the closest thing to a worked example of the pattern, and they show the intended shape: a proprietary runtime that needs glibc, dropped on a small Alpine base.
The repository also contains an APKBUILD file, which is the Alpine package build recipe, and a configparams file, which is the glibc build configuration. The `configparams` file is the one to look at if you need a glibc build with different options, since it is the input to the whole stage 1 build.
What glibc in a musl image does not fix
The limits of this approach are worth being precise about, because the image solves a narrower problem than it can appear to.
It solves dynamic linking against glibc. A program that was compiled against glibc and links dynamically will find its libraries, and the loader configuration handles the search path. That is the case the README names: OracleJDK, Anaconda, other proprietary builds.
It does not solve a program that shells out to glibc specific tools at runtime and expects more of the distribution, and it does not turn the image into a full glibc system. The image is musl with a glibc alongside it, and the loader configuration is what routes a glibc linked binary to the right libraries. A program that mixes musl and glibc components in the same process, or that spawns one and then the other and expects consistent behaviour, is beyond what a library overlay can guarantee.
There is also the base distribution mismatch to keep in mind. The glibc version in the image is 2.42, and the Alpine base is 3.22, while the packaging stage runs on 3.20 because the build script fails on the newer versions for reasons the Dockerfile describes as unknown. A binary that needs a specific glibc symbol version has to be checked against the glibc you get, and the fact that the glibc is compiled from source in the same image means you can request another version with the build argument rather than being stuck with the default.
The cost side of the ledger is the build time and the fact that the glibc packages themselves are prepared by Sasha Gerrand and published in the sgerrand/alpine-pkg-glibc repository, with this Dockerfile inheriting configuration and commands from that repository, from sgerrand/docker-glibc-builder and from sgerrand/docker-alpine-abuild. The image is maintained by a chain of upstream projects, and each of them moves on its own schedule.
A maintained mirror of a community image
This repository is a mirror rather than the origin of the glibc packages, and the file layout records that.
The Dockerfile header states that the majority of the configuration and commands below are inherited from sgerrand/alpine-pkg-glibc, sgerrand/docker-glibc-builder and sgerrand/docker-alpine-abuild. The builder stage even carries the maintainer label of Sasha Gerrand. So the image under the frolvlad name is a repackaging and publication of a build recipe whose substance lives in those upstream repositories.
That arrangement is normal for a published base image, and it has one practical consequence. When glibc or Alpine moves, the upstream repositories are where the change happens, and this repository has to pick it up. The comment at the top of the Dockerfile, about updating the version in all the stages and in the workflows, is the local symptom of that dependency.
Maintenance state in this repository's own terms: it is not archived and the last push was on 2026-05-11. There are no GitHub releases, so there is no version history to read, and the tags that matter are the Docker Hub tags, which follow the glibc version like the 2.42 tag used in the build command. The licence is MIT, and the LICENSE file sits at the repository root next to the README, the Dockerfile and the build scripts.
The final note is about the comparison. The alternative to this image is a Debian or Ubuntu based image, which gives you glibc by default and costs tens of megabytes more. If the size saving matters and your binary is the only glibc dependent thing in the image, this approach wins. If the image also runs musl native tooling, you now carry two C libraries, and the size argument starts to look less convincing.
Editorial conclusion
Adopt frolvlad/alpine-glibc when you have a glibc linked binary you want to run in a small Alpine image, and pin the glibc version you need rather than tracking latest. Do not adopt it if the underlying program is pure musl or statically linked, because then the added glibc is dead weight in every layer, and check first that the base Alpine version matches what your binary expects, since the image pins Alpine 3.22 while packaging runs on 3.20.
Frequently asked questions
What does frolvlad/alpine-glibc do?
It is an Alpine Linux Docker base image that adds glibc alongside the default musl libc, so binaries compiled against glibc such as OracleJDK or Anaconda can run on Alpine. The image is described as roughly 12MB and the Alpine base it uses is 5MB.
How do I build the alpine-glibc image myself?
Use `docker buildx build --platform linux/arm64,linux/amd64 --build-arg GLIBC_VERSION=2.42 -t alpine-glibc:2.42 .` from the repository root. The build compiles glibc from source in a Ubuntu 24.04 stage, then packages it as an Alpine package.
How do I use alpine-glibc in my own Dockerfile?
Base your image on it with `FROM frolvlad/alpine-glibc`, copy your binary in, for example `COPY ./my_app /usr/local/bin/my_app`, then build with `docker build -t my_app .`. Pin the tag rather than relying on the default so the glibc version does not move under you.
Where is glibc installed and how do I update the loader cache?
The glibc packages are built with a prefix directory of /usr/glibc-compat. To update the libc library cache you use /usr/glibc-compat/sbin/ldconfig rather than the usual /sbin/ldconfig, and LD_LIBRARY_PATH works as on a standard libc based distribution.
What Alpine and glibc versions does the image use?
The Dockerfile defaults are ALPINE_VERSION 3.22, ALPINE_PACKAGER 3.20 and GLIBC_VERSION 2.42. Packaging runs on Alpine 3.20 because the build script fails for an unknown reason on newer versions, and the Alpine version is pinned separately from the glibc version.
Is alpine-glibc still maintained?
The repository is not archived and the last push was on 2026-05-11. There are no GitHub releases, and the image tracks the glibc version through Docker Hub tags, with the build recipe inherited from the sgerrand alpine-pkg-glibc and docker-glibc-builder projects.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/docker-hub-frolvlad-docker-alpine-glibc)Was this useful?