en / de
Expertisen
Methoden
Dienstleistungen
Referenzen
Jobs & Karriere
Firma
Technologie-Trends TechCast WebCast TechBlog News Events Academy

Raspberry Pi Image erstellen

Ein Raspberry Pi eignet sich ideal für Server oder Desktop Anwendungen. Das Betriebssystem ist schnell und einfach installiert und diverse Dienste oder Anwendungen lassen sich einfach nach installieren. Ist die Anwendung jedoch komplexer oder müssen mehrere Instanzen erstellt werden, kann es schnell vorbei sein mit der Benutzerfreundlichkeit. Um dieses Problem zu lösen, gibt es mehrere Ansätze. Einer davon ist selber ein Raspberry Pi Image erstellen mithilfe von Yocto

Dieser Ansatz verspricht ein kleinstes mögliches Image sowie eine einfache Wartbarkeit der Konfiguration. Als Bonuspunkt kann das Projekt einfach auf eine benutzerspezifische Hardware portiert werden.

Buildumgebung Docker

Das Yocto Projekt, welches benötigt wird, um ein eigenes Raspberry Pi Image erstellen zu können benötigt eine Linux Umgebung, in unserem Fall Docker mit WSL. Hier ein Dockerfile welches ein entsprechendes Dockerimage erstellen kann das alle nötigen Anwendungen enthält:

FROM ubuntu:22.04

# Relax retries and timeout to prevent errors
RUN echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries; \
    echo 'Acquire::http::Timeout "20";' > /etc/apt/apt.conf.d/99-timeout-http; \
    echo 'Acquire::ftp::Timeout "20";' > /etc/apt/apt.conf.d/99-timeout-ftp;

# Update and upgrade existing
RUN apt-get update; \
    apt-get upgrade -y;

# Setup locales
RUN apt-get update; \
    apt-get -y install locales apt-utils sudo && dpkg-reconfigure locales && locale-gen en_US.UTF-8 && update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 
ENV LANG=en_US.UTF-8 

# Setup timezone 
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Zurich
RUN apt-get update; \
    apt-get install -y tzdata; \
    ln -fs /usr/share/zoneinfo/Europe/Zurich /etc/localtime; \
    dpkg-reconfigure --frontend noninteractive tzdata;

# Setup user
ENV USERNAME=yoctouser
ENV USERGROUP=users
RUN groupadd users;\
    useradd -ms /bin/bash -G sudo -d /home/${USERNAME} -g ${USERGROUP} -r ${USERNAME}; \
    passwd -d ${USERNAME}
RUN passwd -d root
USER ${USERNAME}

# Install packages needed to build yocto (from https://docs.yoctoproject.org/ref-manual/system-requirements.html), dos2unix to simplify maintaining packages.txt
COPY packages.txt /
RUN sudo apt-get update; \
    sudo apt-get install -y dos2unix; \ 
    sudo dos2unix /packages.txt; \
    sudo apt-get install -y $(grep -vE "^\s*#" /packages.txt  | tr "\n" " ");

# Setup manifest repo
ENV MANIFEST_DIR=/manifest
RUN sudo install -o ${USERNAME} -g ${USERGROUP} -d ${MANIFEST_DIR};
WORKDIR ${MANIFEST_DIR}
RUN git init; \
    git config --global user.email "[email protected]"; \
    git config --global user.name "you";
COPY default.xml ${MANIFEST_DIR}/
RUN git add *; \
    git commit -m "Added reopsitory";
WORKDIR /

# Setup project dir
ENV PROJECTDIR=/home/${USERNAME}/yoctodir
RUN sudo install -o ${USERNAME} -g ${USERGROUP} -d ${PROJECTDIR};
WORKDIR ${PROJECTDIR}
RUN repo init -u file://${MANIFEST_DIR}/ -b master < /dev/null; \
    repo sync -j8;

# Setup build dir
ENV BUILDDIR=/home/${USERNAME}/builddir
RUN sudo install -o ${USERNAME} -g ${USERGROUP} -d ${BUILDDIR};

WORKDIR ${BUILDDIR}
COPY layers.conf /layers.conf
COPY localconf_append.conf /localconf_append.conf
RUN sudo dos2unix /layers.conf; \
    sudo dos2unix /localconf_append.conf; \
    sudo sed -i -e "s,##PROJECTDIR##,${PROJECTDIR},g" /layers.conf;
COPY setup_env_script.sh setup_env_script.sh
RUN sudo chmod +x setup_env_script.sh; \
    sed -i -e "s,##PROJECTDIR##,${PROJECTDIR},g" setup_env_script.sh; \
    sed -i -e "s,##LOCALCONFFILE##,/localconf_append.conf,g" setup_env_script.sh; \
    sed -i -e "s,##BBLAYERFILE##,/layers.conf,g" setup_env_script.sh;

WORKDIR ${BUILDDIR}
ENTRYPOINT ["/bin/bash"]

Damit die nötigen Anwendungen einfach gepflegt und erweitert werden können sind diese in einem separaten File aufgelistet:

# Additional tools (may conatains dublicates)
git
nano
curl
repo
# Official yocto packages for yocto (https://docs.yoctoproject.org/ref-manual/system-requirements.html)
gawk
wget
git
diffstat
unzip
texinfo
gcc
build-essential
chrpath
socat
cpio
python3
python3-pip
python3-pexpect
xz-utils
debianutils
iputils-ping
python3-git
python3-jinja2
libegl1-mesa
libsdl1.2-dev
python3-subunit
mesa-common-dev
zstd
liblz4-tool
file
locales
libacl1
curl
python-is-python3
nano

Projekt Setup

Um ein Raspberry Pi Image zu erstellen, muss der entsprechende Raspberrypi-Yocto-Layer inklusive seiner Abhängigkeiten in das Projekt eingebunden werden. Um diese Schritte zu vereinfachen, werden alle benötigten Repositories mithilfe des repo-tools beim Erstellen des Images geholt. Folgende Konfigurationsdatei kann hierzu verwendet werden:

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <default sync-j="8" revision="kirkstone"/>
  <remote name="oe"    fetch="https://git.openembedded.org"/>
  <remote name="yocto" fetch="https://git.yoctoproject.org"/>

  <project name="meta-security.git" path="meta-security" remote="yocto" revision="kirkstone"/>
  <project name="meta-raspberrypi" path="meta-raspberrypi" remote="yocto" revision="kirkstone"/>
  <project name="meta-openembedded" path="meta-openembedded" remote="oe" revision="kirkstone"/>
  <project name="poky.git" path="poky" remote="yocto" revision="kirkstone"/>
</manifest>

Weiter wird direkt mit dem Image ein Build Verzeichnis erstellt, welches ein Setupskript enthält.

#!/bin/bash

if [ "${BASH_SOURCE}" = "${0}" ]; then
    printf "\\n[ERROR]: Use this script with source\\n\\n"
else
    PROJECTDIR="##PROJECTDIR##"
    BBLAYERFILE="##BBLAYERFILE##"
    LOCALCONFFILE="##LOCALCONFFILE##"

    BBLAYERSEXIST="1"
    CONFEXIST="1"

    if [ ! -f "conf/bblayers.conf" ]; then
        LAYERSEXIST="0"
    fi
    if [ ! -f "conf/local.conf" ]; then
        CONFEXIST="0"
    fi

    cd $(dirname ${BASH_SOURCE})
    . ${PROJECTDIR}/poky/oe-init-build-env .

    if [ "$LAYERSEXIST" == "0" ]; then
        bitbake-layers add-layer $(grep -vE "^\s*#" ${BBLAYERFILE}  | tr "\n" " ");
    fi

    if [ "$CONFEXIST" == "0" ]; then
        cat $LOCALCONFFILE >> conf/local.conf
    fi

    unset LAYERSEXIST
    unset CONFEXIST
    unset LAYERFILE
    unset LOCALCONFFILE
    unset PROJECTDIR
fi

Dieses kann verwendet werden, um den Yocto Build zu initialisieren sowie nach jedem Neustart des Containers die Umgebung zu laden. Mithilfe des layers.conf sind die zu verwendenden Layer einfach zu definieren.

##PROJECTDIR##/meta-openembedded/meta-oe/
##PROJECTDIR##/meta-openembedded/meta-python/
##PROJECTDIR##/meta-openembedded/meta-multimedia/
##PROJECTDIR##/meta-openembedded/meta-networking/
##PROJECTDIR##/meta-raspberrypi/

Weiter kann mithilfe des localconf_append.conf das local.conf einfach erweitert werden.

# Extension of locale.conf file to configure project
MACHINE = "raspberrypi4"

Container erstellen

Mithilfe des oben beschriebenen Aufbaus kann aus der Kommandozeile mit

docker build --tag ‚yoctoimage‘ .

ein entsprechendes Image erstellt werden. Ein interaktiver Container daraus wird mit

docker run -it yoctoimage

erzeugt.

Image erstellen und auf die SD-Karte laden

Läuft der erstellte Container kann das Build Projekt erstellt werden, indem das bereitgestellte setup Skript gesourced wird:

cd ${BUILDDIR}

source setup_env_script.sh

Nun steht das Build Projekt bereit und es kann zum Beispiel mit

bitbake core-image-minimal

ein minimal Image erstellt werden. Dies kann je nach Leistung des Rechners einige Zeit in Anspruch nehmen. Ebenfalls benötig der Build mindestens 50GB an Festplattenspeicher. Das erstellte Image muss nun extrahiert werden.

bzip2 -d -f ${BUILDDIR}/tmp/deploy/images/raspberrypi4/core-image-minimal-raspberrypi4.wic.bz2

Die Windows PowerShell eignet sich um das extrahierte Image aus dem Container auf das Hostsystem zu kopieren um es danach mithilfe von rufus auf eine SD-Karte zu flashen.

docker cp <Docker Container Id>:/home/yoctouser/builddir/tmp/deploy/images/raspberrypi4/core-image-minimal-raspberrypi4.wic .

Image flashen

Nun kann der Raspberry Pi mit dem selbst erstellten Image gestartet werden.

Abschliessender Kommentar

Die beschriebenen Konfigurationen und Schritte ermöglichen es ein minimales Image für den Raspberry Pi zu erstellen. Nun liegt es am Benutzer das Image zu erweitern und eventuell zusätzliche oder eigene Layer im Yoctoprojekt einzufügen. Diese können auch direkt im default.xml sowie layers.conf erweitert werden damit diese automatisch mit erstellt werden beim Generieren des Images. Weiter kann es sich lohnen das download Verzeichnis als Volume in den Container zu mounten damit man die Daten bei mehreren Projekten nur einmal herunterladen muss. Zum Schluss wurde festgestellt, dass der Download des Rezeptes linux-raspberrypi fehlschlagen kann. Dies kann umgangen werden indem das Rezept einzeln mit

bitbake -c fetch linux-raspberrypi

heruntergeladen wird und anschliessend nochmals das Image erstellt wird mit

bitbake core-image-minimal

Dass ganze Projekt kann als ZIP-File hier herunter geladen werden.

Kommentare

Schreiben Sie einen Kommentar

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Newsletter - aktuelle Angebote, exklusive Tipps und spannende Neuigkeiten

 Jetzt anmelden
NACH OBEN
Zur Webcast Übersicht