RaspberryPi OSのDockerイメージを使ってCI環境構築

5月 12, 2023

本記事では, GitHub Actionsを使用してRaspberryPiの環境を構築し, Pythonパッケージのビルド管理を行う方法を説明します. この方法により, RaspberryPi実機を定期的に立ち上げてビルドチェックする必要がなくなります. x86_64のPCしかデフォルトではGitHub Actions上で選択できませんが, QEMUを使用することでRaspberryPi環境が構築できるようになります. さらに, 無料でクラウド上にRaspberryPi環境にCIを導入できるという利点があります.

本記事で示した手順に従うことで, Raspberry Pi OSのDockerイメージを作成し, それをGitHub Actionsと組み合わせて使用することができます. これにより, Raspberry Piの実ハードウェアを使わずに, その環境でのPythonパッケージのビルドとテストが可能となります.

セットアップ

Docker

ローカルPC上に下記記事を参照してDockerをインストールします.

Dockerhub

Dockerhubにアカウントを作成し, New Access TokenからAccessTokenを作成します.

Github

Githubにアカウントを作成し, CIを導入するリポジトリを用意します.
そのリポジトリのSettings->Security->Secrets and variables->Actions->New repository secretからDockerhubで生成したAccessTokenとアカウントIDを登録します.

  • Name : DOCKERHUB_TOKEN, Secret : AccessToken
  • Name : DOCKERHUB_USERNAME, Secret : DockerhubのアカウントID

RaspberryPi OS の Docker Image の作成, 起動方法

下記の記事を参考にRaspberryPi OS の Docker Image を作成します.

まずはRaspberryPi OSのルートシステムをダウンロードし, Dockerにimportし, RaspberryPi OSのDocker imageを作成します.

wget https://downloads.raspberrypi.org/raspios_lite_armhf/root.tar.xz
docker image import root.tar.xz techlife/raspios_lite_armhf:2022-09-06_bullseye

QEMUを使用して, ローカルPC上でRaspberryPiを立ち上げることができます.
QEMUを使用せずにRasberryPi OSのdockerを立ち上げようとしてもローカルPCとRaspberryPiのCPUのアーキテクチャが異なるため, 下記エラーが発生し, 立ち上げることができません.
exec /usr/bin/bash: exec format error

QEMU立ち上げコマンド

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

上記コマンド実行後, RaspberryPi OSを立ち上げます.

docker run -it --rm \
    -v `pwd`:/workspace \
    techlife/raspios_lite_armhf:2022-09-06_bullseye bash

後にdocker imageとして使用するため, dockerhubにpushしておきます.

docker login

# docker push REPOSITORY:TAG
docker push techlife/raspios_lite_armhf:2022-09-06_bullseye

Dockerfileの作成

CIでチェックしたいライブラリやソースを最終的にインストールやビルドをし, テストできる環境を作成するDockerfileを作成します.
今回は顔認識ライブラリのface_recognitionをインストールし, そのテストを実施します.
ベースのコンテナイメージには作成したRaspberryPi OSのDocker imageを指定します.
face_recognitionをインストールするために, その前段階で, その依存パッケージをインストールしています.

Github Actionsには6時間の制約があるので, Raspberry Pi向けのopencv-pythonをソースからビルドしているとタイムオーバーになってしまいます. そのため, 自前でビルド済みのwheelファイルを用意しています.

# Dockerfile

# Base : Raspberry Pi OS
FROM techlife/raspios_lite_armhf:2022-09-06_bullseye

# install dependecies
RUN apt update && \
    apt upgrade -y
RUN apt install -y build-essential \
    cmake \
    gfortran \
    git \
    wget \
    curl \
    graphicsmagick \
    libgraphicsmagick1-dev \
    libatlas-base-dev \
    libavcodec-dev \
    libavformat-dev \
    libboost-all-dev \
    libgtk2.0-dev \
    libjpeg-dev \
    liblapack-dev \
    libswscale-dev \
    pkg-config \
    python3-dev \
    python3-numpy \
    python3-pip \
    zip
RUN apt clean
RUN cd ~ && \
    mkdir -p dlib && \
    git clone -b 'v19.9' --single-branch https://github.com/davisking/dlib.git dlib/ && \
    cd  dlib/ && \
    python3 setup.py install --compiler-flags "-mfpu=neon"

RUN cd ~ && \
    git clone https://github.com/tech-life-hacking/opencv_python_wheels.git && \
    cd opencv_python_wheels && \
    pip3 install opencv_python-4.7.0.72-cp39-cp39-linux_armv7l.whl

# install face_recognition
RUN pip3 install face_recognition

# test
RUN cd ~ && \
    git clone https://github.com/ageitgey/face_recognition.git && \
    cd face_recognition/examples && \
    python3 face_distance.py

GitHub Actions

作成したDockerfileをGithub Actionsにビルドしてもらいます. そのビルドのワークフローをYAMLファイルで定義します. リポジトリに.github/workflows/main.ymlを置き, そのファイル内にon: [push]を記載しておくと, リポジトリに何らかのファイルがpushされたのをトリガーにDockerfileをビルドしてくれます.

リポジトリを下記構成にします.

.github/workflows/main.yml

Dockerfile

etc…

main.ymlの流れ

  1. リポジトリのソースをチェックアウト
  2. QEMUのセットアップ
  3. Docker Buildxのセットアップ
  4. Dockerfileのビルド, テストとそのイメージのDockerhubへのpush
# .github/workflows/main.yml

name: CI
on: [push]

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v2
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v1
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1
      -
        name: Login to DockerHub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      -
        name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: .
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/face_recognition:latest

Github Actionsの基本的な使い方

GitHub Actionsを利用したDockerイメージの自動ビルド

おわりに

本記事で説明した内容が, Raspberry Piの環境を模擬するためのDockerイメージの作成や, GitHub Actionsを用いたCIの導入に役立つことを願っています.これらの技術を活用することで, ソフトウェア開発の品質向上や効率化に寄与することでしょう.