[ラズパイ x puppeteer] Alpine:edgeのdockerイメージをラズパイにプルしてpuppeteerが動くか試すまでのお話


2021/01/18

常時稼働するスクレイピングサーバーをラズパイで立てて、Dockerコンテナ内部から
pupetteerで定期的に情報採集することをやってみた時のネタです。

基本的には以前の内容をラズパイでも同じことを行えるのかを検証した内容になっています。

今回の内容は、ラズパイでpuppeteerが動くまでの手順を以降で説明しています。


Puppeteerには64bitベースのOSを使おう

まず結論をズバッというと、ラズパイでpupeteerを使うには、もっと正確に言うと、最新のヘッドレスChromeの機能をフルに使うためには、この記事執筆現在もベータ版扱いであるRaspberrypi OS 64bitを使うことが推奨です。

なおご存知かとは思いますが、現在の
公式のRaspberry Pi OS(旧Raspbian OS)といえば暗黙で32bitになります。


ラズパイでpuppeteerをインストール

それでは以降でラズパイにpuppeteerを入れるまでの試行錯誤的な実験をしてみます。

上手くいかない例: 通常のRaspberry Pi OS (32bit)を使ってみる

とりあえず何も考えないで動作環境は、手持ちのラズパイ3B+にRaspberry Pi OS 32bit版を使ってみます。

まずはヘッドレスChromeを正常に動かすために
alpine:edgeをDockerHubからプルしてみます。

            
            $ docker pull alpine:edge
$ docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
alpine                       edge                904d557dd3a3        3 weeks ago         3.82MB
...
        
これで一応はコンテナがローカルにセットできました。

インタラクティブモードで中身に入れるかルートのまま入って適当なコマンドをやってみます。

            
            $ docker run --rm -it alpine:edge sh
/# uname -a
Linux 1acab526291a 5.4.51-v7+ #1333 SMP Mon Aug 10 16:45:19 BST 2020 armv7l Linux
        
このDockerイメージはCPUアーキテクチャarmv71(RaspberryPi OS 32bit版相当)向けにビルドされていることが確認できます。

以前の記事でalpineへのpuppeteerの導入方法を解説していましたので、この手順でラズパイでもやってみます。

なお手元のラズパイでdockerとdocker-composeが使える前提にしていますので、2つが使えるようにしておきましょう。

この時の動作確認時でのプログラムバージョンは以下の通りです。

            
            $ docker --version
Docker version 19.03.12, build 48a6621
$ docker-compose --version
docker-compose version 1.25.5, build 8a1c60f6
        
そのままビルドが通ればよかったのですが、なんだかシステムの環境によるエラーが発生してます。

            
            $ docker-compose build
Building app
Step 1/7 : FROM alpine:edge
 ---> 904d557dd3a3
Step 2/7 : RUN apk update && apk upgrade && apk add --no-cache bash openssh expect
 ---> Running in 76dc8b73963d
fetch https://dl-cdn.alpinelinux.org/alpine/edge/main/armv7/APKINDEX.tar.gz
ERROR: https://dl-cdn.alpinelinux.org/alpine/edge/main: temporary error (try again later)
WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/edge/main: No such file or directory
fetch https://dl-cdn.alpinelinux.org/alpine/edge/community/armv7/APKINDEX.tar.gz
ERROR: https://dl-cdn.alpinelinux.org/alpine/edge/community: temporary error (try again later)
WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/edge/community: No such file or directory
2 errors; 14 distinct packages available
ERROR: Service 'app' failed to build: The command '/bin/sh -c apk update && apk upgrade && ...' returned a non-zero code: 2
        
なるほど、Alpineのapkのアップデートが出来ないというエラー...?

パッケージにエラーがないか確かめてみます。

            
            $ docker run --rm -it alpine:edge apk info
WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/edge/main: No such file or directory
WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/edge/community: No such file or directory
musl
busybox
alpine-baselayout
alpine-keys
libcrypto1.1
libssl1.1
ca-certificates-bundle
libtls-standalone
ssl_client
zlib
apk-tools
scanelf
musl-utils
libc-utils
        
レポジトリの2つが欠けているようなので、これがエラーになっている....?。

同じようなエラーで悩んでいる方がいないかネットで検索していると、
同じような不具合の報告をされている方のサイトを見つけて、dockerをアップデートせよと書いてありました。

...え、そんだけ...?と祈るような思いで
dockerを久々にアップデートしてみます。

            
            $ sudo apt-get update && sudo apt-get install docker-ce
$ docker --version
Docker version 20.10.2, build 2291f61
        
dockerを最新バージョンにロールアップしてみても全く効果が無く、無常にも同じエラーが繰り返されているようです。

ただこの時点で、docker本体のプログラムは正常であることが分かりました。

再度、良く問題の
alpine:edgeのコンテナの挙動を観察してみると、そもそもコンテナ内部からネットワーク外部にアクセス出来ていないことが分かります。

            
            $ docker run --rm -it alpine:edge
/ # ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
ping: clock_gettime(MONOTONIC) failed
        
pingさえlocalhostに通らないので、今回はイメージそのものにネットワークエラーの原因があるようです。

とはいえ、
alpine:edge以外のイメージからであれば、コンテナ内部からは正常に外部へアクセス出来ているようです。

            
            $ docker run --rm -it arm32v7/alpine:3.11
/ # ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.290 ms
64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.278 ms
64 bytes from 127.0.0.1: seq=2 ttl=64 time=0.271 ms
64 bytes from 127.0.0.1: seq=3 ttl=64 time=0.269 ms
64 bytes from 127.0.0.1: seq=4 ttl=64 time=0.275 ms
64 bytes from 127.0.0.1: seq=5 ttl=64 time=0.276 ms
--- 127.0.0.1 ping statistics ---
8 packets transmitted, 8 packets received, 0% packet loss
round-trip min/avg/max = 0.269/0.275/0.290 ms
        
つまり、arm32用にビルドされていないイメージを使ってしまったことでエラーが起こっているようです。

ここで議論されていますが、

            
            This problem only happens on the raspberry pi with 32bit os with alpine:edge armhf
        
と言うことで、alpine:edgeをRasbianOS32bit環境で使うときに固有のネットワークエラーが発生してしまうのでCPUアーキテクチャを良く考慮する必要があるとのこと。


上手く例: ベータ版のRaspberry Pi OS (64bit)を使ってみる

現状ではDockerfileなどのリソースコードまで弄るとなると、簡単に解決することでもなさそうですので、心機一転、別のラズパイ機でRaspberryPiOSの64bit版から試すことにしました。

まず
RaspberryPiOSの64bit版を入れ直し、dockerが使えるようにしておきます。

            
            $ uname -a
Linux raspberrypi 5.10.5-v8+ #1392 SMP PREEMPT Sat Jan 9 18:56:30 GMT 2021 aarch64 GNU/Linux
$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
        
この64bit環境で早速alpine:edgeを試してみます。

            
            $ docker pull alpine:edge
$ docker run --rm -it alpine:edge
/# uname -a
Linux c3f81c1d71cb 5.10.5-v8+ #1392 SMP PREEMPT Sat Jan 9 18:56:30 GMT 2021 aarch64 Linux
#👇pingを叩くと反応あり
/# ping localhost
PING localhost (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.214 ms
64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.238 ms
64 bytes from 127.0.0.1: seq=2 ttl=64 time=0.224 ms
64 bytes from 127.0.0.1: seq=3 ttl=64 time=0.254 ms
64 bytes from 127.0.0.1: seq=4 ttl=64 time=0.229 ms
--- localhost ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.214/0.231/0.254 ms
        
では今度こそDockerイメージをビルド出来るか再トライしてみましょう...

            
            $ docker-compose build
Building app
Step 1/7 : FROM alpine:edge
 ---> 9079f290228e
Step 2/7 : RUN apk update && apk upgrade && apk add --no-cache bash openssh expect
 ---> Running in 02b3d58d9141
fetch https://dl-cdn.alpinelinux.org/alpine/edge/main/aarch64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/edge/community/aarch64/APKINDEX.tar.gz
v3.13.0-156-gb9f6e9e586 [https://dl-cdn.alpinelinux.org/alpine/edge/main]
v3.13.0-168-gc177701a68 [https://dl-cdn.alpinelinux.org/alpine/edge/community]
OK: 13805 distinct packages available
Upgrading critical system libraries and apk-tools:
(1/1) Upgrading apk-tools (2.12.0-r3 -> 2.12.0-r4)
#...省略
Removing intermediate container 671b64657589
 ---> adcd7e21988d
Successfully built adcd7e21988d
Successfully tagged puppeteer-alpine:edge
        
...ようやく無事ビルド出来ました!🎉

やはり先程までのdockerコンテナ内部からネットワークに繋がらなくなる不具合はRaspberryPiOSの32bit版内部で引っかかっていたようです。

これで晴れて、ラズパイでもpuppeteerが使えるようになりました。

合同会社タコスキングダム|蛸壺の技術ブログ


まとめ

今回はラズパイのalpine:edgeベースのDockerコンテナからpuppeteerを起動させるための注意点を順を追って説明してみました。

結論としては、Raspberrypi OS 64bit版を使うことで正常に動作させることができると言うことを確認しました。

もちろんベースとしてalpine:edgeのイメージを使う前提であれば、
Dockerの使える環境が構築できるArch Linuxなどの64bitOSは割とたくさんの候補が存在しているようです。

とはいえ、ラズパイ公式のサポートするRaspberryPi OSは他のOSと比べて技術情報が圧倒的に多いので、余程の理由がなければ他のOSを使う理由も無いように思います。
記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。