Installer Docker sur un Orange Pi PC¶
toolchain¶
On travaille sur une architecture amd64 et l”Orange Pi PC a une architecture ARM v7 avec fpu hardware.
Sous Debian, une première solution consiste à installer les packages :
binutils-arm-none-eabi
gcc-arm-none-eabi
Une autre solution consiste à utilise les packages toolchain Linaro. On télécharge l’archive binaire sur le site, par exemple gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf.tar.xz
On l’extrait sous $HOME, ce qui crée le répertoire
gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/
, que l’on ajoute
au PATH
export PATH=~/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/bin:$PATH
Les exécutables sont préfixés par arm-linux-gnueabihf-
qu’il faudra
indiquer pour les cross-compilations.
u-boot¶
Dans un premier temps, cloner le dépôt git
git clone git://git.denx.de/u-boot.git
On se positionne sur la dernière release stable. Par exemple
git co v2016.11
Puis on lance la compilation. La variable CROSS_COMPILE contient le préfixe correspondant aux outils de la toolchain installés précédemment
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- orangepi_pc_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
A la fin de la compilation, on obtient, entre autres, un ficher u-boot-sunxi-with-spl.bin qui est celui qui nous intéresse.
Pour l’installer sur la carte SD et permettre de booter le noyau, on passe la commande
dd if=u-boot-sunxi-with-spl.bin of=/dev/sdX bs=1024 seek=8
Dans la commande ci-dessus, il faut remplacer /dev/sdX
par le device
correspondant à la carte SD (/dev/sdb
ou /dev/mmcblk0
par exemple).
Noyau Linux¶
Actuellement, Orange Pi PC (Opi PC) tourne avec un noyau 3.4 qui est le seul patché par sunxi pour supporter le matériel. Or ce noyau commence à dater sérieusement, a de nombreuses failles de sécurité , et n’est pas compatible avec Docker (il manque les cgroups en particulier) ou F2FS qui est un système de fichiers adapté aux mémoires flash comme les cartes SD.
Si le support matériel de l’Opi PC s’améliore dans le noyau Linux vanilla, il y a encore des manques importants, en particulier le port Ethernet et l’USB.
Docker étant plutôt orienté serveur, on peut se passer de l’USB mais pas de l’Ethernet. Heureusement, le support de l’Ethernet de l’Opi PC est en cours de développement et semble fonctionnel. Il existe un dépot Github qui fait un fork du noyau Linux pour ajouter le support emac de l’Opi PC.
Comme on va rebaser sur une version stable du noyau, on a besoin du dépot git de la branche stable de Linux. On récupère également la branche de Linus (version en développement qui sert de base au patch).
Allons-y
git clone -o stable git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
cd linux-stable
git remote add emac https://github.com/montjoie/linux.git
git remote add linus git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
git fetch linus
git fetch emac
# on se place sur la v4 du patch emac
git co emac/sun8i-emac-wip-v4
# on le rebase sur la version 4.8.6 du noyau
git rebase v4.8.9
# on crée un tag pour garder la trace
git br emac_wip4_4.8.9
A ce stade, on a donc les sources d’un noyau Linux stable 4.8.9 avec le patch permettant le support Ethernet.
J’ai toujours eu l’habitude de séparer les sources du répertoire de
construction (dans l’exemple ~/build/stable
) avec la commande suivante
make O=~/build/stable ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- sunxi_defconfig
On repart de la config sunxi par défaut mais celle-ci est loin de convenir. Pour l’adapter
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
Voici la config que j’utilise.
Pour le support Ethernet, ne pas oublier les options
CONFIG_ETHERNET=y
CONFIG_NET_VENDOR_ALLWINNER=y
CONFIG_SUN4I_EMAC=y
CONFIG_SUN8I_EMAC=y
CONFIG_PHYLIB=y
CONFIG_SWPHY=y
Reste à (cross-)compiler le noyau. Le script qui suit compile le noyau, les modules et les device trees dans le répertoire ~/build/install
#!/bin/sh
INSTALL=~/build/install
rm -r $INSTALL
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- oldconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8 zImage modules
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs
make INSTALL_MOD_PATH=$INSTALL ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules_install
cp -r arch/arm/boot/zImage arch/arm/boot/dts $INSTALL
Les différents composants utiles sont donc tous présents dans le répertoire
install
. Pour ceux qui veulent éviter toutes les étapes précédentes,
on peut récupérer l”archive résultante.
Partitionnement de la carte SD¶
On considère que la carte SD est le device /dev/sdX. On va créer une partition de boot en format FAT, un swap et la partition root.
La parition boot va contenir le noyau, les device trees et le script de configuration.
La partition root va être constitué d’un fichier en F2FS, a priori plus adapté à une carte SD que le format EXT4. C’est une des raisons de l’existence de la partition FAT : u-boot saurait se contenter d’une partition unique EXT4 mais, à ma connaissance, pas en F2FS. De plus, ce n’est pas très génant de séparer boot et root.
Device Start End Sectors Size Id Type
/dev/sdX1 2048 264191 262144 128M c W95 FAT32 (LBA)
/dev/sdX2 264192 2361343 2097152 1G 82 Linux swap / Solaris
/dev/sdX3 2361344 31116287 28754944 13,7G 83 Linux
Création des systèmes de fichiers¶
- ::
sudo mkfs.vfat /dev/sdX1 sudo mkswap /dev/sdX2 sudo mkfs.f2fs /dev/sdb3
sudo mount /dev/sdX1 /mnt/tmp1 sudo mount /dev/sdX3 /mnt/tmp3
cd /mnt/tmp1 cp -r install .
sudo vi boot.cmd
Partition boot¶
Depuis le répertoire install, on copie le fichier zImage
et le répertoire
dts
. Les modules devront être copiés plus tard dans le rootfs mais la
config retenue fait qu’ils ne sont pas indispensables pour booter car les
éléments importants sont compilés dans le noyau et non pas en modules.
Reste le fichier de configuration de boot. On édite le fichier boot.cmd
avec le contenu suivant
setenv bootargs console=ttyS0,115200 noinitrd root=/dev/mmcblk0p3 rootwait panic=10
fatload mmc 0 ${kernel_addr_r} zImage
fatload mmc 0 ${fdt_addr_r} dts/sun8i-h3-orangepi-pc.dtb
bootz ${kernel_addr_r} - ${fdt_addr_r}
Un peu de détail ligne par ligne :
la première ligne active la console sur le port UART : celà permet d’avoir le log dès le boot du noyau. Comme on a pas l’USB actif, il est quasiment indispensable d’avoir un cable série-USB pour suivre ce qui se passe au boot (et après). On précise également la partition (pour l’Opi PC) qui contient la partition root (ici
/dev/mmcblk0p3
).la deuxième ligne charge le noyau (depuis une partition FAT)
la troisième ligne charge le device tree de l’Opi PC (depuis une partition FAT)
et on boot (le - en second paramètre signifie qu’on a pas d’initrd)
Il faut ensuite compiler ce fichier par la commande suivante
mkimage -C none -A arm -T script -d boot.cmd boot.scr
Si la commande mkimage n’existe pas, il faut installer le package
u-boot-tools
.
A ce stade, on doit pouvoir vérifier que l’Opi PC boote sur la carte SD et lance le noyau. Par contre, on va échouer à monter la racine qui n’existe pas.
Partition rootfs¶
On a de quoi booter un noyau mais il faut maintenant créer un système complet
dans la partition root. Le choix fait ici est de créer un système Debian
en utilisant la commande multistrap
. On aura également besoin de
qemu-user-static
pour émuler un processeur ARM et chrooter dans le
rootfs.
On commence donc par installer les packages
apt install multistrap qemu-user-static
Il faut ensuite un fichier de configuration. Voici celui que j’utilise et qui
peut être adapté. Fichier armhf1.conf
[General]
arch=armhf
directory=jessie-armhf1
cleanup=true
noauth=true
unpack=true
debootstrap=Debian Net Utils
aptsources=Debian
[Debian]
packages=apt kmod lsof
source=http://cdn.debian.net/debian/
keyring=debian-archive-keyring
suite=jessie
components=main contrib non-free
[Net]
packages=netbase net-tools ethtool udev iproute iputils-ping ifupdown
isc-dhcp-client ssh
source=http://cdn.debian.net/debian/
[Utils]
packages=locales adduser vim zsh less wget dialog usbutils rsync tmux git
source=http://cdn.debian.net/debian/
Pour utiliser ce fichier, il suffit ensuite de passer la commande
multistrap -f armhf1.conf
Il faut ensuite copier /usr/bin/qemu-arm-static
dans le répertoire
/usr/bin
du rootfs et chrooter pour exécuter dpkg --configure -a
.
L’image obtenue n’est toutefois pas parfaite car plusieurs fichiers de
configuartion ne sont pas renseignés, par exemple /etc/fstab
ou
/etc/network/interfaces
.
Pour simplifier l’installation, on peut regrouper les différentes opérations dans un script
ROOTFS_DIR="jessie-armhf1"
HOSTNAME="opi"
ROOTDEV="/dev/mmcblk0p3"
BOOTDEV="/dev/mmcblk0p1"
ID_RSA_PUB="ssh-rsa AAAAB3...JglcE61D36Xs1aWF37Q9DKP54L philippe@example"
multistrap -f armhf1.conf
cp /usr/bin/qemu-arm-static $ROOTFS_DIR/usr/bin
mount -o bind /dev/ $ROOTFS_DIR/dev/
export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true
export LC_ALL=C LANGUAGE=C LANG=C
chroot $ROOTFS_DIR dpkg --configure -a
#hostname
filename=$ROOTFS_DIR/etc/hostname
echo $HOSTNAME > $filename
#name servers
filename=$ROOTFS_DIR/etc/resolv.conf
echo nameserver 8.8.8.8 > $filename
echo nameserver 8.8.4.4 >> $filename
#network interfaces
filename=$ROOTFS_DIR/etc/network/interfaces
echo auto eth0 >> $filename
echo iface eth0 inet dhcp >> $filename
#fstab
filename=$ROOTFS_DIR/etc/fstab
echo $BOOTDEV /boot vfat noatime 0 1 > $filename
echo $ROOTDEV / ext4 noatime 0 1 >> $filename
#apt sources
filename=$ROOTFS_DIR/etc/apt/sources.list
echo deb http://ftp.fr.debian.org/debian jessie main > $filename
echo deb http://security.debian.org/ jessie/updates main >> $filename
echo deb http://ftp.fr.debian.org/debian jessie-backports main >> $filename
# ssh
mkdir -p $ROOTFS_DIR/root/.ssh
chmod 700 $ROOTFS_DIR/root/.ssh
echo $ID_RSA_PUB >> $ROOTFS_DIR/root/.ssh/authorized_keys
Il suffit ensuite de recopier ce rootfs sur la partition root, par exemple
en utilisant la commande rsync
et en créant un fichier tar.
On peut également recopier les modules du noyau dans le répertoire
/lib/modules
du rootfs.
# crée système de fichier F2FS
mkfs.f2fs /dev/sdX3
# monte sous /mnt
mount /dev/sdX3 /mnt
cd /mnt
# copie le rootfs crée ci-dessus
rsync -av ~/rootfs/jessie-armhf1/ .
# copie les modules du noyau
rsync -av ~/build/install/lib .
# démonte la carte SD
umount /mnt
Premier boot¶
Théoriquement, il y a tout ce qu’il faut pour booter et obtenir un debian pur avec un noyau vanilla (à part le patch emac).
Ne reste plus qu’à installer docker
apt install docker.io thin-provisioning-tools