Add locales to your Alpine Linux Docker image

After moving from Debian- to Alpine-based Docker images we bumped into a problem: no localization support in Alpine. It's easier to not rely on it, but we've got some projects that do. I'll explain how to install locales on an Alpine Docker image.


Normally you can use locale-gen to add your required locale. Search for “how to use locale gen” and you will find enough information for every distro, but not for Alpine. Alpine aims for the smallest possible image size and omitting the locales is a quick win. But with musl-locale you can add basic support for locales. It’s a locale program for musl libc. That’s the C standard library Alpine uses.

First create a Dockerfile. Because we use a lot of PHP I use the PHP Alpine images as an example, but this will work for every Alpine based image. I’ve tested with Alpine 3.8, 3.9, 3.10 and 3.11.

# Dockerfile
FROM php:7.2-cli-alpine3.11

Let’s build and run a container. locale -a should list all available locales.

$ docker build . -t alpine-locale:latest
$ docker run --rm -it alpine-locale:latest locale -a
sh: locale: not found

So no locale command available in Alpine. Let’s start fixing it.

musl-locale has some dependencies which can be found in the README.

...
ENV MUSL_LOCALE_DEPS cmake make musl-dev gcc gettext-dev libintl

RUN apk add --no-cache \
    $MUSL_LOCALE_DEPS

Now we can download, compile and install musl-locale.

...
RUN apk add --no-cache \
    $MUSL_LOCALE_DEPS \
    && wget https://gitlab.com/rilian-la-te/musl-locales/-/archive/master/musl-locales-master.zip \
    && unzip musl-locales-master.zip \
      && cd musl-locales-master \
      && cmake -DLOCALE_PROFILE=OFF -D CMAKE_INSTALL_PREFIX:PATH=/usr . && make && make install \
      && cd .. && rm -r musl-locales-master

Let’s build and run a container to check our progress.

$ docker build . -t alpine-locale:latest
$ docker run --rm -it alpine-locale:latest locale -a
C
C.UTF-8

locale -a works and returns the available locales, but that’s only the default language. Which is not useful because it’s English and we already had that one. To make the other locales available MUSL_LOCPATH must be set.

...
ENV MUSL_LOCALE_DEPS cmake make musl-dev gcc gettext-dev libintl 
ENV MUSL_LOCPATH /usr/share/i18n/locales/musl
...

All steps combined:

# Dockerfile
FROM php:7.2-cli-alpine3.11

ENV MUSL_LOCALE_DEPS cmake make musl-dev gcc gettext-dev libintl 
ENV MUSL_LOCPATH /usr/share/i18n/locales/musl

RUN apk add --no-cache \
    $MUSL_LOCALE_DEPS \
    && wget https://gitlab.com/rilian-la-te/musl-locales/-/archive/master/musl-locales-master.zip \
    && unzip musl-locales-master.zip \
      && cd musl-locales-master \
      && cmake -DLOCALE_PROFILE=OFF -D CMAKE_INSTALL_PREFIX:PATH=/usr . && make && make install \
      && cd .. && rm -r musl-locales-master

Let’s check the complete list of available locales.

$ docker build . -t alpine-locale:latest
$ docker run --rm -it alpine-locale:latest locale -a
C
C.UTF-8
de_DE.UTF-8
es_ES.UTF-8
de_CH.UTF-8
ch_DE.UTF-8
ru_RU.UTF-8
nl_NL.UTF-8
sv_SE.UTF-8
en_US.UTF-8
fr_FR.UTF-8
en_GB.UTF-8

It’s a limited set of locales and you can’t generate specific ones, but it’s at least something. And if you need another language you can create a pull request.