Build-Umgebung mit Docker erstellen

Wer kennt das nicht: Ein System soll gebaut werden. Der Hersteller des Boards stellt den Quellcode zur Verfügung, aber dieser lässt sich nicht auf dem Rechner des Entwicklers bauen. Sei es, dass der Compiler nicht in der benötigten Version bereit steht, dass Libraries nicht passen oder die verwendetet Distribution gleich gar nicht unterstützt wird.

Mitunter stellt der Hersteller die Entwicklungsumgebung im Form einer virtuellen Maschine zur Verfügung. Diese ermöglicht einen schnellen Einstieg, bringt aber auch Nachteile mit sich. Einerseits kann die Wartung und Archivierung  des Entwicklungssystems problematisch werden. Andererseits wird es schwierig sein, eine solche Umgebung in die CI-Umgebung zu integrieren. Aus diesen Gründen ist die virtuelle Maschine zwar eine Lösung für erste Versuche, wird aber auf Dauer den Erfordernissen nicht genügen.

Als idealer Weg erweist sich hier Docker.  Mit diesem, in der „Comunity Edition“ kostenlos nutzbaren, System können sehr einfach sogenannte Container erstellt werden, die zum Beispiel die geforderte Entwicklungsumgebung zur Verfügung stellen.

Beispiel: Yocto Linux für NXP i.MX6

NXP stellt für seine i.MX6-Prozessoren ein Board Support Package auf Basis von Yocto bereit. Nach Registrierung bei nxp.com kann die Dokumentation dort heruntergeladen werden.

Der „Freescale Yocto Project User’s Guide“ beschreibt im Detail, dass ein Entwicklungsrechner mit Ubuntu 12.04 oder 14.04 empfohlen wird und eine Reihe von zusätzlichen Paketen zu installieren ist, unter anderem das Python Script Repo.

Auf dieser Basis habe ich folgendes Dockerfile erstellt:

RROM ubuntu:14.04
RUN apt update && \
    apt -y upgrade && \
    apt -y install \
        gawk wget git-core diffstat unzip texinfo gcc-multilib \
        build-essential chrpath socat libsdl1.2-dev \
        libsdl1.2-dev xterm sed cvs subversion coreutils texi2html \
        docbook-utils python-pysqlite2 help2man make gcc g++ desktop-file-utils \
        libgl1-mesa-dev libglu1-mesa-dev mercurial autoconf automake groff curl lzop asciidoc \
        u-boot-tools \
        vim

RUN curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > /usr/local/bin/repo \
    && chmod a+x /usr/local/bin/repo

Das Image ist schnell gebaut und ausgeführt:

stephan@Kirk:~ docker build -tyocto-docker .
...
Successfully tagged yocto-docker:latest
stephan@Kirk:~ docker run -it --rm -v $(pwd):/work yocto-docker bash
root@72ca5645afe9:/# ls -ld /work
drwxr-xr-x 3 1000 users 4096 May 13 16:38 /work
root@72ca5645afe9:/# id
uid=0(root) gid=0(root) groups=0(root)
root@72ca5645afe9:/# exit
stephan@Kirk:~

Allerdings zeigt sich hier das Problem: die bash, die sich nun im aktuellen Arbeitsverzeichnis öffnet, wird als root ausgeführt! Die Möglichkeit, einen Benutzer im Dockerfile (USER xxx) anzugeben, schied aus, weil dann das Image nur für einen einzigen Benutzer brauchbar wäre. Die Benutzer-ID als Parameter bei „docker run -u xxx …“ anzugeben, erschien zu fehlerträchtig.

Dieses Problem zu lösen war gar nicht so trivial. Am Ende habe ich das Image um ein bash Script erweitert, welches

  1. den Besitzer des aktuellen Verzeichnisses ermittelt
  2. im Container einen entsprechenden Benutzer anlegt
  3. das Kommando mit diesem Benutzer ausführt

Das Script und das vollständige Dockerfile ist auf github zu sehen, das Image kann direkt von Docker Hub benutzt werden.

stephan@Kirk:~$ id
uid=1000(stephan) gid=100(users) Gruppen=100(users) 
stephan@Kirk:~$ docker run -it --rm -v $(pwd):$(pwd) -w $(pwd) steho/yocto bash
local_worker@36f0198f7a7b:/home/stephan$ pwd
/home/stephan
local_worker@36f0198f7a7b:/home/stephan$ id
uid=1000(local_worker) gid=100(users) groups=100(users)
local_worker@36f0198f7a7b:/home/stephan$ exit

Fazit

Auf diese Weise können schnell und einfach Entwicklungsumgebungen für fast beliebige Anforderungen erstellt werden. Werden diese wie in meinem Beispiel auf Github/Docker Hub oder in einem entsprechenden Repository im Intranet gepflegt steht jedem Entwickler im Team jederzeit eine aktuelle Entwicklungsumgebung zur Verfügung.

Disclamer

Das Recht, Docker zu benutzen, kommt dem Root-Recht für den betreffenden Benutzer gleich. Deshalb sollte es ausschließlich vertrauenswürdigen Entwicklern eingeräumt werden!