Wicked pdfというgemを使用して開発を進めていこうとしたのですが、Docker環境でM1の場合動作しないということがあったので、その対策方法を記載したいと思います。
動作しない原因は何なのか?
M1とその他マシーンでCPUアーキテクチャ(以下CPU)が異なる点が要因になっています。Docker環境はホストOSをベースとしてBuildしますが、BuildしたコンテナのCPUはそのベースとしたホストによって決まります。そしてwicked pdfで対応できるCPUにM1のCPU(arm64)は含まれていない為、エラーが起きるようです。
wicked pdfにおける対応可能なCPU一覧
参考ログ
困ったことになったということで、上記のGit上での会話を見ていると、jtelcontarさんが対応方法を記載してくれてました。
どうやら記載のパッケージでは64に対応できるということだったので、ダウンロードしてみたいと思います。ただし、M1以外の場合は既存のgemを参照するようにしたいので、M1の場合は新規にダウンロードしたパッケージ、それ以外は既存gemを参照するといった具合で分岐が必要になりそうです。実際にDockerfileに記載した内容がこちら
RUN if [ "$(uname -m)" = "aarch64" ]; then \
echo "M1からのアクセスです"; \
cd /usr/local/bin/ && wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.stretch_arm64.deb && \
apt-get update && \
apt-get install -y /usr/local/bin/wkhtmltox_0.12.6-1.stretch_arm64.deb && \
rm /usr/local/bin/wkhtmltox_0.12.6-1.stretch_arm64.deb; \
fi
if分の条件にある"$(uname -m)"はcpuアーキテクチャ情報を取得するコマンドで、ここでどの種類のマシーンからアクセスしたのかを判定します。あとはaptコマンドを使用してpackageをインストールしています。
最後にrmでインストールしたパッケージを削除しているのは、installコマンドでパッケージ解凍後に、このパッケージ自体はゴミになるので削除しています。
あとはwicked_pdf.rb内で、gemの参照先のパスをデフォルトで参照している記載があるのですが、こちらの内容を以下のように修正しました。
# M1でDockerを起動した場合、/usr/local/bin/のパスに64対応のファイルが作成されるのでそちらを参照する
# ファイルが存在しない(M1起動でない場合)はこれまで通りgemで格納したファイルを参照する)
# TODO 最新のgemが64に対応した段階で、デフォルト記載に戻す
if File.exist?('/usr/local/bin/wkhtmltopdf')
binary_path = '/usr/local/bin/wkhtmltopdf'
else
binary_path = "#{Gem.loaded_specs['wkhtmltopdf-binary'].full_gem_path}/bin/wkhtmltopdf"
end
WickedPdf.config = {
exe_path: binary_path,
}
先ほどDockerfile内にて、M1からのアクセスの場合、/usr/local/bin/のパスにパッケージをインストールするように記載していました。なのでこのパスに、wkhtmltopdfのファイルが存在していればそれはM1からのアクセスなので、パスの参照先をそちらを見るようにしているわけです。
注意点として、バージョン指定をしてインストールしているので、最新のバージョンがM1にも対応した場合これらの対応は元に戻すことをお忘れなく...
終わりに
調べて調べて調べまくった結果、今回のような実装に至りました。かなり苦戦を強いられましたが、ドキュメントを読み漁るという点では良い経験になったと思います。同じ現象に悩んでいる方がもしいらっしゃれば参考にしてみてください。