To keep Alpine Linux as lean as possible, its developers have chosen different components from those that are commonly used in “big” Linux libraries.
For example, Alpine Linux uses the standard C library musl instead of glibc or the init system OpenRC instead of systemd. Even the basic Linux commands aren’t available in their full versions but come in a trimmed-down version from the BusyBox package.
Alpine Linux therefore provides comparatively little comfort when working interactively. But Alpine Linux is sufficient to run a server service such as Apache or Nginx with minimum overhead—and that’s what matters in the Docker environment. You can find more information on this here:
Even though Alpine Linux isn’t intended for interactive use, you should create a container to try out its basic functions. The quickest way to do this is using the following command:
docker run -it --rm -h alpine --name alpine alpine
This will take you to an interactive root shell where you can determine the version number of Alpine Linux:
cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.16.2
PRETTY_NAME="Alpine Linux v3.16"
HOME_URL="https://alpinelinux.org"
BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues"
In Alpine Linux, the /bin/sh shell is executed by default, which is part of BusyBox (see the following section). This shell can’t keep up with the comfort of bash (i.e., use of cursor keys to reference/change commands, use of (Tab) key for command and file name completion), which is used with other Linux distributions. For this reason, it may be worth installing the much larger bash to explore Alpine Linux.
apk add --update bash bash-completion
/bin/bash
bash-5.1#
If you then run docker ps -s in a second terminal, you’ll see that the container size has grown from a few bytes to approximately 5 MB. In other words, bash alone takes up almost as much space as the entire Alpine image!
BusyBox is a relatively large program by Alpine standards (0.8 MB), but it contains implementations of about 140 standard commands such as cat, echo, grep, gzip, hostname, ip, ls, mount, ping, rm, route, and su. These commands are available as symbolic links on busybox:
ls /bin /sbin -l
/bin
... 12 ash -> /bin/busybox
12 base64 -> /bin/busybox
12 bbconfig -> /bin/busybox
824904 busybox
12 cat -> /bin/busybox
...
/sbin
12 acpid -> /bin/busybox
12 adjtimex -> /bin/busybox
69704 apk
12 arp -> /bin/busybox
...
The obvious advantage of BusyBox is that the space required for these standard commands is small. The disadvantage of BusyBox is that the commands are partly implemented in a simplified form with various options missing that are common on Linux. An overview of all commands and options that can be used with BusyBox can be found here:
https://busybox.net/downloads/BusyBox.html
On Linux, the init system is responsible for starting background and network services when the computer is booted. However, there’s no need for this when using it in Docker (also true for other Linux images for Docker).
The situation is similar for logging: by default, logging isn’t provided in the Alpine image. If needed, you can install the rsyslog package and take care of its startup.
The musl library used in Alpine Linux is a leaner libc implementation than the widely used glibc. However, this library sometimes leads to problems. One is that the evaluation of /etc/resolv.conf has been simplified. Thus, musl ignores the domain and search keywords. If you have trouble resolving domain names, you should take a look at the following web page:
https://github.com/gliderlabs/docker-alpine/blob/master/docs/caveats.md
Binary files that haven’t been compiled for Alpine Linux also cause difficulties. They sometimes use symbols that exist in glibc but not in musl. The ldd <binary> command helps you troubleshoot that.
Another problem is the lack of support for localization files (locales). One possible way around this is to install a variant of glibc optimized for Alpine Linux. You can find more details on this topic here:
In Alpine Linux, neither the man command nor the associated help texts are installed by default. The following commands help you solve this issue; they also activate less at the same time, so you can comfortably navigate through the help texts:
apk add --update mandoc mandoc-apropos man-pages less less-doc
export PAGER=less
Note that this will return the man pages for various standard commands but not those for specifically installed packages. On Alpine Linux, it’s common for documentation files to be in a separate package named <packagename>-doc. So, if you want to read the man pages for the bash shell, you must also install the bash-doc package:
apk add --update bash-doc
You can also find useful Alpine-specific documentation in the wiki of the project site. A good place to start is here:
https://wiki.alpinelinux.org/wiki/Tutorials_and_Howtos
In May 2019, it was revealed that Docker images of Alpine Linux were shipped without a root password. Fortunately, this sounds more dramatic than it actually is. In the Docker environment, it’s rather unusual for user management to be active within a container. By default, this isn’t the case in Alpine Linux nor in countless images built on it. Conversely, however, it can’t be ruled out that individual Docker users install additional packages for user management via apk. Then the option of a root login without a password really becomes a security risk.
The problem has, of course, long since been fixed. cat /etc/shadow shows that an exclamation mark in the sense of “invalid password” is stored in the hash code column for the root password:
cat /etc/shadow
root:!::0:::::
bin:!::0:::::
daemon:!::0:::::
...
Editor’s note: This post has been adapted from a section of the book Docker: Practical Guide for Developers and DevOps Teams by Bernd Öggl and Michael Kofler.