When you manage one or two packages, it’s a good idea to spin up a virtual machine as build environment just for that. Using some tricks it can be made possible to build them automatically.
Here I want to show fully automated approach using headless build host inside a Docker container.
A word on Docker
Docker consists of several parts like docker-engine, docker-compose, docker-machine and docker-swarm.
Docker-engine is the basic tool which purpose is to create and run images in containers, managing virtual networks.
Further in this post I assume the reader already knows docker basics.
Creating of a package, when done manually, is fairly error prone. Such processes as version and release management, manual dependencies declarations or updating a repository require a lot of attention.
Also, to create an RPM package, put it into repository and update an index of that repo, one must do all that inside and rpm-based environment. The distro I used is Alt Linux, which is a bit odd. The thing is, it uses apt package manager, but the system itself is rpm-based. They used apt-rpm with it’s own repository structure, but putting that aside it looks a lot like ordinary apt. But it’s not my work environment, so at first Alt Linux lived inside a VirtualBox machine. It’s worth to give it a credit: virtual machine snapshots are awesome. But overall, spinning a virtual machine and building a dozen of packages by hand felt not right.
There are tools like Vargrant exist to make life a little easier for anyone who does a lot of boilerplate work with virtual machines. I think it’s awesome when one needs a development environment closely mimicking production environment or to have some environment at all, like using your linux setup under windows.
Docker to the rescue
Containers that serve a single purpose, seems like it. Actually, building a package is just a properly
rpmbuild call. Indexing a repository is a bit more complicated, but all in all it’s just 20 lines
Luckily, there is an image of altlinux-p7 on the docker hub,
which was just what I need. Here is a
FROM fotengauer/altlinux-p7 RUN apt-get update && apt-get -y install git rpm-build apt-repo-tools ADD ./i386-alt-linux /usr/lib/rpm/i386-alt-linux ADD ./i486-alt-linux /usr/lib/rpm/i486-alt-linux ADD ./i586-alt-linux /usr/lib/rpm/i586-alt-linux ADD ./i686-alt-linux /usr/lib/rpm/i686-alt-linux RUN ln -s /usr/lib/rpm/i386-alt-linux /usr/lib/rpm/i386-linux RUN ln -s /usr/lib/rpm/i486-alt-linux /usr/lib/rpm/i486-linux RUN ln -s /usr/lib/rpm/i586-alt-linux /usr/lib/rpm/i586-linux RUN ln -s /usr/lib/rpm/i686-alt-linux /usr/lib/rpm/i686-linux RUN useradd -m builder RUN useradd -M user WORKDIR /home/builder USER builder ADD ./script /opt/ CMD /opt/script
These four files are macro definitions for build targets of the same name. This image is x86_64 and macro’s are necessary to build x86 binary rpms. A script looks like this:
#!/bin/bash mkdir -p /tmp/pkgbuild cd /tmp/pkgbuild tar xvp </dev/stdin ls -alh &>/dev/stderr make
I’ll explain myself a little further.
To build an image, use
docker build -t rpmbuild . from the directory with script and Dockerfile.
Here comes the interesting part: the resulting image is meant to be dispossably used with a tar archive of project directory. Directory itself:
Makefile PKGNAME RELEASE TARGET package/ project.spec project-file-1 ... project-file-n
All projects share the same Makefile which is as follows:
name=$(shell cat PKGNAME) target=$(shell target) version=$(shell git tag | tail -1) src=$(shell git ls-files) rpm: rpm-tarball rpmbuild \ --target $(target) \ --define "_topdir /tmp/" rm -f $(name)-$(version).tar.gz rpm-tarball: tar czvpf $(name)-$(version).tar.gz $(src) --transform '/^./$(name)-$(version)/' --show-transformed docker-rpm: tar cvp . -O | docker run -i -v ./package:/tmp/RPMS rpmbuild docker-repo: docker run -i -v './package:/tmp/RPMS' -v '/myrepo:/tmp/repo' rpmrepo && echo $$$$((`cat RELEASE` + 1)) > RELEASE
rpmrepo image looks a lot like
rpmbuild, except the script. It contains some setup and call to
docker-rpm target relies on piping
tared current directory to stdout and piping it to
rpmbuild container, which
then decompresses it to
This post has shown how docker images can be used as a lightweight and highly automated alternative to virtual machines.
stdin and stdout. Volumes might be used here as well.