Raspberry Pi 4 に Docker と Docker Compose をインストールする

ラズベリーパイで Docker がどっかーん。
2021.10.09

シングルボードコンピュータである Raspberry Pi に Docker の実行環境を構築する機会があったので手順をご紹介したいと思います。

検証に使った Raspberry Pi の環境

利用した Raspberry Pi の環境は以下のとおりです。

  • デバイス:Raspberry Pi 4 (4GB)
  • OS 環境は下記の通り「Raspbian 32 bit の buster」を使っています。
    • Raspberry Pi Imager でインストールしました
$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 10 (buster)
Release:    10
Codename:   buster
$ cat /etc/debian_version
10.9
$ cat /etc/issue
Raspbian GNU/Linux 10 \n \l
$ uname -a
Linux hostname 5.10.17-v7l+ #1414 SMP Fri Apr 30 13:20:47 BST 2021 armv7l GNU/Linux

Raspberry Pi Imager については下記もご参照ください。

前提条件

今回は下記のドキュメントに沿って作業を行います。

このドキュメントにある前提条件は下記の通りです。

  • Debian または Raspbian バージョンのいずれかの64ビットバージョン
  • Debian Bullseye 11(安定版)
  • Debian Buster 10(oldstable)
  • Raspbian Bullseye 11(安定版)
  • Raspbian Buster 10(oldstable)
  • x86_64 (or amd64), armhf, and arm64 のアーキテクチャをサポート

今回使うデバイスには「Raspbian Buster 10」の 32 bit がインストールされています。上記の通り Docker Engine はarmhfがサポートされているので、特に問題は無いと判断して進めることにしました。

Docker Engine のサポート対象は下記にまとまっているので、こちらも合わせてご覧いただければと思います。

前提条件の補足

前提条件にある 「Bullseye」 について少し気になったので調べみました。 「Raspbian Bullseye」 は公式にはまだリリースアナウンスが無い(見つけられなかっただけ?)ようで、2021年10月6日現在で Raspberry Pi Imager でインストールしたものは Buster となっていました。

下記に Raspbian として Bullseye のイメージが置かれていたので準備はできているように見えます。

一方で下記には Bullseye は見当たらず最も新しいものは Buster となっていました。

下記フォーラムでも議論されているようですが、「Debian Bullseye は公式にリリースしたが、Raspbian は Debian と全く同じではない」という記載が何度か繰り返されていて、はっきりと言及されていませんでした。

今回は、時間の都合でこれまで使っていた環境を作り直したくなかったこともあり、Buster のまま進めることにしました。

また、Raspbian 64 bit は 公開されてはいるものの未だにベータ提供という位置づけのようです。
Buster 64bit のイメージを見つけたので別デバイスで少し試したところ、正常に動かないアプリケーションがあったので断念しました。

なお、Raspbian 用の Bullseye 64 bit イメージは見つけられませんでした。いずれにしても、Raspbian では一部の実装に対応できていない部分があり全面的に 64 bit に移行できないようです。Raspberry Pi 4 では4GB 版、8GB 版とメモリ容量の大きなものがあるので、性能を活かし切るには 64bit 用の Debian などをインストールして使うのがよいようです。

実際、下記の記事では Raspberry Pi 4 に対して「64bit の Debian」をインストールして性能比較されていますが、概ね 64 bit 版の方が高い性能を示しています。

個人的に調べた限りはこのような状況でしたが、詳しい方いらっしゃればコメントいただけると嬉しく思います。

Docker Engine のインストール方法

多くの Linux ディストリビューションにおいては、Dockerのリポジトリを利用してインストールすることができます。下記は Debian にインストールする手順が書かれたドキュメントです。こちらに、Raspbian へのインストール方法も記載されています。

しかし上記ドキュメントでは、Raspbian の場合「convenience script」なるスクリプトでインストールすることが唯一の方法として紹介されていました。

Most users set up Docker’s repositories and install from them, for ease of installation and upgrade tasks. This is the recommended approach, except for Raspbian.

In testing and development environments, some users choose to use automated convenience scripts to install Docker. This is currently the only approach for Raspbian.

( DeepL翻訳 による日本語訳)

ほとんどのユーザーは、インストールやアップグレード作業を容易にするために、Dockerのリポジトリを設定し、そこからインストールします。これは、Raspbianを除いて推奨される方法です。

テストや開発環境では、自動化された便利なスクリプトを使ってDockerをインストールすることを選択するユーザーもいます。これは現在、Raspbianでの唯一の方法です。

上記の通りなので、ドキュメントに従って「convenience script」を使ってインストール作業を行いたいと思います。

convenience script による Docker Engine のインストール

前置きが長くなってしまいましたが、「convenience script」を使ってインストールしていきましょう!
インストール作業自体は下記のコマンドを実行するだけです。

$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh

Docker Engine の動作確認

Docker Engine のバージョン確認

インストールが完了したらバージョンを確認します。

$ docker -v
Docker version 20.10.8, build 3967b7d

追加リポジトリ等無しでaptコマンドでインストールした場合はDocker version 18.09.1, build 4c52b90だったので、新しいバージョンがインストールされていることが分かります。

Docker コンテナの起動権限を付与

この状態では まだpiユーザーでは Dockerコンテナ を起動できませんが、dockerグループに piユーザを追加すればsudoを付けずに実行できるようになります。
必要に応じて実行してください。

$ sudo usermod -aG docker pi

Nginx コンテナで動作確認してみる

せっかくなので適当なイメージ(Nginx)からコンテナの動作確認をしてみます。

$ docker run --name some-nginx -d -p 8080:80 nginx

Nginx が 8080 ポートで起動していますね。

$ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                   NAMES
7360adff42ad   nginx     "/docker-entrypoint.…"   25 seconds ago   Up 19 seconds   0.0.0.0:8080->80/tcp, :::8080->80/tcp   some-nginx

イメージも確認できました。

$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    bd1e09f31869   2 weeks ago   103MB

手元の Mac から Raspbian Pi へブラウザでアクセスしてみます。Nginx のページが見れました。

01-docker-nginx-ip

Docker Compose のインストール

次に Docker Compose をインストールします。2021年10月6日現在で「Docker Compose V2」がリリースされていますが、今回は「V1」をインストールしています。
V2 については別途検証しているので、別記事にてご紹介できればと思います。

インストール手順は下記ドキュメントを参考にしています。

この中で実行する手順は、下記にある「Alternative install options」 タブに記載のものになります。

06-install-compose-linux-alternative

いくつか依存パッケージがあるようですが、足りなかったら都度インストールすればいいので、手順にある通り、一旦pipで Docker Compose をインストールしていきましょう。

$ sudo pip3 install docker-compose

私の環境では、特にエラーにならずにインストールできました。

なお、インストール手順の隣タブにある 「Linux」の手順では、今回使っている Raspbian のアーキテクチャに適合するバイナリが無いのでインストールできないので注意してください。

05-install-compose-linux

ちなみに「バージョン 1.29.2」で用意されているパッケージは下記になります。

03-docker-compose-1-29-2

今回使っている Raspbian は armv7lなので相当するものがなく「Linux」タブの手順ではインストールできない、ということになります。

Docker Compose の動作確認

Docker Engine のバージョン確認

インストールが完了したのでバージョンを確認します。

$ docker-compose -v
docker-compose version 1.29.2, build unknown

追加リポジトリ等無しでaptコマンドでインストールされたものはdocker-compose version 1.21.0, build unknownだったので、新しいバージョンがインストールされていることが分かります。

Nginx と PostgreSQL のコンテナで動作確認してみる

せっかくなので複数コンテナを使って動作確認してみたいと思います。適当なディレクトリで下記のようなdocker-compose.yamlを作成します。

今回は、Docker Hub のパブリックリポジトリから Nginx と PostgreSQL の公式イメージを使いました。

version: '3'

services:
  db:
    image: postgres:latest
    environment:
        POSTGRES_USER: postgres
        POSTGRES_PASSWORD: password
    ports:
      - 5432:5432
  web:
    image: nginx:latest
    ports:
      - 8080:80

コンテナを起動します。(docker-compose.yamlがある同じディレクトリで下記コマンドを実行します。)

$ docker-compose up -d

Starting mydocker_db_1  ... done
Creating mydocker_web_1 ... done

Nginx と PostgreSQL のコンテナが起動しました。

$ sudo docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED              STATUS              PORTS                                       NAMES
568067f977cf   nginx:latest      "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:8080->80/tcp, :::8080->80/tcp       mydocker_web_1
98b3fe050192   postgres:latest   "docker-entrypoint.s…"   About an hour ago    Up About a minute   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   mydocker_db_1

今回は PostgreSQL に接続して確認してみます。(デバイス上で)接続できました!

$ psql -h localhost -U postgres
Password for user postgres: 
psql (11.12 (Raspbian 11.12-0+deb10u1), server 13.4 (Debian 13.4-1.pgdg100+1))
WARNING: psql major version 11, server major version 13.
         Some psql features might not work.
Type "help" for help.

postgres=#

psqlは下記でクライアントだけインストールできます。

$ sudo apt install postgresql-client

これで Raspberry Pi で Docker を動かす環境ができました。次は Greengrass のコンポーネントで動かしたいと思うので、コンテナは止めておきましょう。

$ docker-compose down

Greengrass のコンポーネントで Docker コンテナを動かすのは次回ご紹介したいと思います。

時刻同期できない問題

冒頭に書いたとおり、今回の検証環境は下記のとおりです。

  • デバイス
    • Raspberry Pi 4 (Memory : 4GB)
  • OS
    • Raspbian Buster 32 bit

実は、 この環境では Docker コンテナがホスト側と時刻同期できない問題があります。(2021年10月13日現在)
実際、対象のコンテナ上で date コマンドを実行すると下記の通り「1970年01月01日 00時00分00秒」 と表示されます。また何度 date コマンドを実行しても時刻が更新されることはありませんでした。

$ docker exec -it [CONTAINER_NAME] date
Thu Jan  1 00:00:00 UTC 1970

回避策

下記の issue でも議論されていますが、原因は Raspberry Pi (Raspbian OS)側にありました。最後のコメントにあるように libseccomp のパッケージに問題があるようで、最新バージョンを ホスト側(Raspberry Pi) にインストールすることで解消しました。

$ wget http://ftp.debian.org/debian/pool/main/libs/libseccomp/libseccomp2_2.5.1-1_armhf.deb
$ sudo dpkg -i libseccomp2_2.5.1-1_armhf.deb

libseccomp 自体は 2021年10月13日 現在の最新バージョンは「2.5.2」です。

先程の deb パッケージも下記で最新版が利用できるようになっていました。こちらをインストールしても同様に時刻同期できました。

インストールできたら改めてコンテナを起動して、時刻を確認してみましょう。
先程と異なり、正しい時刻が取得できるようになりました!

$ docker exec -it [CONTAINER_NAME] date
Wed Oct 13 06:34:19 UTC 2021

他の Raspberry Pi の状況

他の組み合わせでも確認してみたところ、時刻同期できない問題は「Raspberry Pi 4」+「Raspbian Buster 32 bit」の組み合わせでのみ発生しました。

Raspberry Pi バージョン OS 時刻同期
Raspberry Pi 3B Raspbian Buster 32 bit OK
Raspberry Pi 3B+ Raspbian Buster 32 bit OK
Raspberry Pi 4 Raspbian Buster 32 bit NG
Raspberry Pi 4 Raspbian Buster 64 bit OK

同じ状況でお困りの方がいらっしゃれば、libseccompのパッケージ更新を試してみてください!

なお、上記のうち「Raspbian Buster 64 bit」以外は Raspberry Pi Imager から OS ダウンロード・インストールしました。「Raspbian Buster 64 bit」については、下記よりイメージをダウンロードして、Raspberry Pi Imager からローカルのイメージファイルを指定してインストールしています。

最後に

最初は単に「aptコマンドでインストールするだけでいいだろう」と思っていたのですが調べると「前提条件」など追加で調べることが増えて、思いの外時間がかかってしまいました。

どなたかのお役に立てれば幸いです。