Alpine Linux for your Docker containers
Alpine linux was slowly becoming the de-facto for most of the Docker registry images, and today is one of the most used base images for official Docker images (called Docker Library), Some examples: nginx and redis.
Distribution #
Alpine Linux is a super small linux distribution that claims to focuses on being lighteight, secure and resource efficient. The idea comes the Busybox implementation, and also uses musl and libc which results in an
image no bigger than 8MB!
$ time docker run --rm alpine echo true
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
e110a4a17941: Already exists
Digest: sha256:3dcdb92d7432d56604d4545cbd324b14e647b313626d99b889d0626de158f73a
Status: Downloaded newer image for alpine:latest
true
docker run --rm alpine echo true 0.01s user 0.01s system 0% cpu 3.892 total
It downloads the image, starts the container, runs the command and removes the container in less than 4s!
Package manager #
Being such a different beast from other Linux distribution it could not exist without It’s own tailored package manager is called apk. Installing and removing stuff is just a breeze and does not require much hassle:
$ docker run --rm -ti alpine sh
/ # apk add --update bash
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/community/x86_64/APKINDEX.tar.gz
(1/5) Installing ncurses-terminfo-base (6.0-r7)
(2/5) Installing ncurses-terminfo (6.0-r7)
(3/5) Installing ncurses-libs (6.0-r7)
(4/5) Installing readline (6.3.008-r4)
(5/5) Installing bash (4.3.42-r3)
Executing bash-4.3.42-r3.post-install
Executing busybox-1.24.2-r9.trigger
OK: 13 MiB in 16 packages
/ # bash
bash-4.3#
Easy enough, right? Let’s move ahead
Running everyday’s commands inside containers #
So, at this point now we’ve downloaded the image and then run a container interactively and installed bash, pretty useless altogether. Let’s do something a bit more meaningful, like running the mysql command to connect to one of our databases from inside a docker container to avoid installing all the required files and directories.
To start, we need to create a Dockerfile declaration inside a folder called mysql-client
, easy:
FROM alpine:3.4
MAINTAINER Marc Lopez <github.com/marclop>
RUN apk add --update \
mysql-client \
&& rm -rf /var/cache/apk/*
ENTRYPOINT ["mysql"]
Then, we build it with the command docker build
:
$ docker build -t marclop/mysql-client mysql-client
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM alpine:3.4
3.4: Pulling from library/alpine
Digest: sha256:3dcdb92d7432d56604d4545cbd324b14e647b313626d99b889d0626de158f73a
Status: Downloaded newer image for alpine:3.4
---> 4e38e38c8ce0
Step 2 : RUN apk add --update mysql-client && rm -rf /var/cache/apk/*
---> Running in 78fc0645976f
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/community/x86_64/APKINDEX.tar.gz
(1/6) Installing mariadb-common (10.1.14-r3)
(2/6) Installing ncurses-terminfo-base (6.0-r7)
(3/6) Installing ncurses-terminfo (6.0-r7)
(4/6) Installing ncurses-libs (6.0-r7)
(5/6) Installing mariadb-client (10.1.14-r3)
(6/6) Installing mysql-client (10.1.14-r3)
Executing busybox-1.24.2-r9.trigger
OK: 39 MiB in 17 packages
---> 0328578e96e5
Removing intermediate container 78fc0645976f
Step 3 : ENTRYPOINT mysql
---> Running in 1ee892f3dcc8
---> 5d883815424f
Removing intermediate container 1ee892f3dcc8
Successfully built 5d883815424f
Once we have all that, we can run the command mysql with:
$ docker run --rm -ti marclop/mysql-client --version
mysql Ver 15.1 Distrib 10.1.14-MariaDB, for Linux (x86_64) using readline 5.1
But it’s a bit inconvenient doing so for every time we want to run the mysql command, so let’s just create an alias of that command pointing to mysql
$ alias mysql='docker run --rm -ti marclop/mysql-client'
$ mysql --version
mysql Ver 15.1 Distrib 10.1.14-MariaDB, for Linux (x86_64) using readline 5.1
Now we have our awesome command ready to be run at our demand, and all that happens inside a container, isn’t that awesome?
I’ve created a repository with a Makefile to automate the container creation, it can be found here
If you liked this article, don’t forget to Kudos it!