Some time ago, I started to set up the “Network UPS Tools” (NUT) for my uninterruptible power supply (UPS) “Eaton 3S”. It’s a UPS which can be connected to a computer via USB cable.
I found a NUT-package in the “testing”-repository of “Alpine Linux”.
Unfortunately, I was unable to create a working setup using this package. After some
research, I found the reason for my problems: A missing dependency to the
hidapi
-package. I wanted to submit a merge request to get around the problem
permanently.
Most of my servers run on “Alpine Linux” due to its “diskless mode”, but I prefer “Arch Linux” installed on my laptop. So, I needed an easy and reliable way to build and test the fixed package on my laptop to prepare the merge request.
I decided to give “containers” a try. In this tutorial, I show you, how I get
things up and running. I chose the bash
-package as an example. Please don’t
hesitate to choose another one to follow the tutorial.
Requisites for readers
This article is written for people with a basic understanding in “Linux” operating system and containers. Writing this article, I assume the reader does not have “Alpine Linux” running on her/his workstation. The instructions given here should work for most Linux distributions.
I added tags to clarify which commands have to be executed on which of your systems:
- Workstation: Your local desktop computer or laptop which you use to run the container.
- Container: Your build container.
To make this article easier to read, I do not prefix commands run as root
with sudo
. Instead, I use the following syntax for the commands in this
article. But for your daily business, I definitively recommend using the
sudo
-command.
$ command
: Running the command as a normal or admin user# command
: Running the command asroot
Build the container image
Workstation Build container image
First create a working directory and paste the content into a
Dockerfile
-file. It doesn’t matter how you name the working directory.
$ mkdir -p <working_directory_container_image>
$ vi Dockerfile
FROM alpine:latest
# install required packages to build "alpine linux" packages
RUN apk add --update --no-cache --no-progress alpine-sdk coreutils bash
RUN apk add --update --no-cache --no-progress sudo
# setup directory for built packages
RUN mkdir -p /var/cache/distfiles
RUN chmod a+w /var/cache/distfiles
RUN chgrp abuild /var/cache/distfiles
RUN chmod g+w /var/cache/distfiles
# setup the abuild configuration
RUN echo 'PACKAGER="Your Name <your@email.address>"' >> /etc/abuild.conf
RUN echo 'MAINTAINER="$PACKAGER"' >> /etc/abuild.conf
RUN echo "%abuild ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/abuild
# setup the build user in container
RUN adduser -D user1
RUN addgroup user1 abuild
# setup directory to pass in build instructions files for abuild
VOLUME /home/user1/aports
WORKDIR /home/user1/aports
RUN chown user1:user1 /home/user1/aports
# make user1 the current user in the image
USER user1
# create keys for signing packages after the build has been finished
RUN abuild-keygen -a -i -n
# setup git for the build user
RUN git config --global user.name "Build User"
RUN git config --global user.email "build-user@example.com"
Next, please download the current version of the “Alpine Linux” container base image. This
step is only required to update an already existing alpine:latest
-container image.
$ sudo docker pull alpine:latest
latest: Pulling from library/alpine
5843afab3874: Already exists
Digest: sha256:234cb88d3020898631af0ccbbcca9a66ae7306ecd30c9720690858c1b007d2a0
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest
When you have created the Dockerfile
-file, build the container image with the
following command. The given output should match yours.
$ sudo docker build -t feduxorg/alpine-dev .
Sending build context to Docker daemon 3.584kB
Step 1/19 : FROM alpine:latest
---> d4ff818577bc
Step 2/19 : RUN apk add --update --no-cache --no-progress alpine-sdk coreutils bash
---> Using cache
---> f7744c1c2842
Step 3/19 : RUN apk add --update --no-cache --no-progress sudo
---> Using cache
---> 3ea4a0e3bc06
Step 4/19 : RUN mkdir -p /var/cache/distfiles
---> Using cache
---> 1e97184b0aca
Step 5/19 : RUN chmod a+w /var/cache/distfiles
---> Using cache
---> f85a246cf9c4
Step 6/19 : RUN chgrp abuild /var/cache/distfiles
---> Using cache
---> 0167de99bca8
Step 7/19 : RUN chmod g+w /var/cache/distfiles
---> Using cache
---> bf41921c42ba
Step 8/19 : RUN echo 'PACKAGER="Your Name <your@email.address>"' >> /etc/abuild.conf
---> Using cache
---> a6b0746093eb
Step 9/19 : RUN echo 'MAINTAINER="$PACKAGER"' >> /etc/abuild.conf
---> Using cache
---> c8147e4ff956
Step 10/19 : RUN echo "%abuild ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/abuild
---> Using cache
---> 8e128a7d77d9
Step 11/19 : RUN adduser -D user1
---> Using cache
---> 072258140dc3
Step 12/19 : RUN addgroup user1 abuild
---> Using cache
---> 815f63fcb234
Step 13/19 : VOLUME /home/user1/aports
---> Using cache
---> 5337450d764a
Step 14/19 : WORKDIR /home/user1/aports
---> Using cache
---> 859c352752c3
Step 15/19 : RUN chown user1:user1 /home/user1/aports
---> Using cache
---> df99576f1802
Step 16/19 : USER user1
---> Using cache
---> 09edaf22bc0b
Step 17/19 : RUN abuild-keygen -a -i -n
---> Using cache
---> abe47dd97da3
Step 18/19 : RUN git config --global user.name "Build User"
---> Running in c50ce65f6cc7
Removing intermediate container c50ce65f6cc7
---> 147325c8eb08
Step 19/19 : RUN git config --global user.email "build-user@example.com"
---> Running in 5b9fcd3c6501
Removing intermediate container 5b9fcd3c6501
---> f859ac69a8d6
Successfully built f859ac69a8d6
Successfully tagged feduxorg/alpine-dev:latest
Setup “Alpine Linux” “aports”
Workstation Clone “aports” repository
Please clone the “Alpine Linux” aports
-repository. For this tutorial, we use a
so-called “shallow clone” to speed up the git clone
-command. Remove the
--depth 1
-parameter if you clone the repository for a “real” merge request.
$ git clone --depth 1 https://gitlab.alpinelinux.org/alpine/aports
Cloning into 'aports'...
warning: redirecting to https://gitlab.alpinelinux.org/alpine/aports.git/
remote: Enumerating objects: 22163, done.
remote: Counting objects: 100% (22163/22163), done.
remote: Compressing objects: 100% (15417/15417), done.
remote: Total 22163 (delta 1008), reused 16749 (delta 831), pack-reused 0
Receiving objects: 100% (22163/22163), 10.91 MiB | 6.48 MiB/s, done.
Resolving deltas: 100% (1008/1008), done.
Updating files: 100% (14383/14383), done.
When the git clone
-command has finished, make the aports
-directory to
your current working directory.
$ cd aports
Prepare the build container
-
Workstation Start the build container
Please start the container. You need to pass the directory with the
aports
-repository to the container.$ sudo docker run --rm --name alpine-dev-1 -v $PWD:/home/user1/aports -it feduxorg/alpine-dev
-
Container Check the content of the
/home/user1/aports
-directory.Given you cloned the
aports
-repository and passed it to the container, you should see a similar content in your directory.$ ls -1 CODINGSTYLE.md COMMITSTYLE.md README.md community main non-free scripts testing unmaintained
-
Container Update package repository
apk
requires the package database to be available to install packages. So, please, update the package database first.$ sudo apk update fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz v3.14.0-114-g8a8c96a0ea [https://dl-cdn.alpinelinux.org/alpine/v3.14/main] v3.14.0-112-gde20fa9d3b [https://dl-cdn.alpinelinux.org/alpine/v3.14/community] OK: 14932 distinct packages available
Build “Alpine Linux” package
-
Container Build package
As mentioned at the beginning, we build the
bash
-package in this tutorial. Please navigate to the/home/user1/aports/main/bash
-directory and run theabuild
-command.This directory contains all required files to build the package. The most important one is the
APKBUILD
-file. It contains all instructions about how to create theapk
-package.$ cd /home/user1/aports/main/bash
$ abuild -r >>> bash: Building main/bash 5.1.8-r0 (using abuild 3.8.0_rc4-r0) started Sun, 11 Jul 2021 13:06:38 +0000 >>> bash: Checking sanity of /home/user1/aports/main/bash/APKBUILD... >>> bash: Analyzing dependencies... >>> bash: Installing for build: build-base bison flex readline-dev>8 ncurses-dev WARNING: Ignoring /home/user1/packages//main: No such file or directory (1/7) Installing m4 (1.4.18-r2) (2/7) Installing bison (3.7.6-r0) (3/7) Installing flex (2.6.4-r2) (4/7) Installing libhistory (8.1.0-r0) (5/7) Installing ncurses-dev (6.2_p20210612-r0) (6/7) Installing readline-dev (8.1.0-r0) (7/7) Installing .makedepends-bash (20210711.130638) Executing busybox-1.33.1-r2.trigger OK: 238 MiB in 72 packages >>> bash: Cleaning up srcdir >>> bash: Cleaning up pkgdir >>> bash: Fetching https://ftp.gnu.org/gnu/bash/bash-5.1.tar.gz % Total % Received % Xferd Average Speed Time Time Tim [...] >>> bash: Build complete at Sun, 11 Jul 2021 13:09:29 +0000 elapsed time 0h 2m 51s >>> bash: Cleaning up srcdir >>> bash: Cleaning up pkgdir >>> bash: Uninstalling dependencies... (1/7) Purging .makedepends-bash (20210711.130638) (2/7) Purging bison (3.7.6-r0) (3/7) Purging flex (2.6.4-r2) (4/7) Purging m4 (1.4.18-r2) (5/7) Purging readline-dev (8.1.0-r0) (6/7) Purging libhistory (8.1.0-r0) (7/7) Purging ncurses-dev (6.2_p20210612-r0) Executing busybox-1.33.1-r2.trigger OK: 236 MiB in 65 packages >>> bash: Updating the main/x86_64 repository index... >>> bash: Signing the index...
-
Container Check for built packages
By default,
abuild
places built packages under/home/user1/packages/
. Let’s check, if we can find our packages in that directory as well.$ find /home/user1/packages/main/x86_64/ | sort /home/user1/packages/main/x86_64/ /home/user1/packages/main/x86_64/APKINDEX.tar.gz /home/user1/packages/main/x86_64/bash-5.1.8-r0.apk /home/user1/packages/main/x86_64/bash-dbg-5.1.8-r0.apk /home/user1/packages/main/x86_64/bash-dev-5.1.8-r0.apk /home/user1/packages/main/x86_64/bash-doc-5.1.8-r0.apk
-
Container Install package
Given your build was successful, you can find the package and install it. Any error about missing other packages requires a modification of the
APKBUILD
-file.$ sudo apk add --allow-untrusted /home/user1/packages/main/x86_64/bash*apk (1/4) Upgrading bash (5.1.4-r0 -> 5.1.8-r0) Executing bash-5.1.8-r0.post-upgrade (2/4) Installing bash-dbg (5.1.8-r0) (3/4) Installing bash-dev (5.1.8-r0) (4/4) Installing bash-doc (5.1.8-r0) Executing busybox-1.33.1-r2.trigger OK: 241 MiB in 68 packages
Conclusion
Now you have got a working build environment for an “Alpine Linux”-package. I hope you can make some use of it and support the “Alpine Linux”-project.