Intel Macで動作するDockerのNodeアプリを Apple Silicon Mac (M1) で動かすためにやったこと

Intel Mac で動作する Dockerfile を、Apple Silicon Mac (M1) で利用したら、イメージのビルドが失敗したり、docker 内の node のアプリ (react, gatsby, puppeteer) が動作しなくなったりしたので、その際に行った対処を書き残す。
サマリ
- node のイメージタグを
*-buster
に変更する。 xdg-utils
をインストールする。- (puppeteer を使う場合のみ)
- chromium をインストールする。
- node のイメージタグを
*-alpine
に変更する。
元ファイル
Intel Mac では動作する Dockerfile。
FROM node:14.17.0-slim
# Localize into Japanese
RUN apt-get update \
&& apt-get install -y locales \
&& locale-gen ja_JP.UTF-8 \
&& echo "export LANG=ja_JP.UTF-8" >> ~/.bashrc
# Install Chrome (only to use for puppeteer)
RUN apt-get install -y wget gnupg \
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
&& apt-get update \
&& apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \
--no-install-recommends
# Install wget and curl
RUN apt-get install -y \
wget \
curl \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
発生したエラー
spawn xdg-open ENOENT
npx create-react-app [project name] --template typescript
が完了後、npm start
コマンド実行時に以下が発生。
events.js:353
throw er; // Unhandled 'error' event
^
Error: spawn xdg-open ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:269:19)
at onErrorNT (internal/child_process.js:467:16)
at processTicksAndRejections (internal/process/task_queues.js:82:21)
Emitted 'error' event on ChildProcess instance at:
at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12)
at onErrorNT (internal/child_process.js:467:16)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
errno: -2,
code: 'ENOENT',
syscall: 'spawn xdg-open',
path: 'xdg-open',
spawnargs: [ 'http://localhost:3000' ]
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! front@0.1.0 start: `react-scripts start`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the front@0.1.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /home/node/.npm/_logs/2022-04-10T07_46_46_139Z-debug.log
一部の deb パッケージが 404 Not Found
上記エラーの xdg-open
は xdg-utils
パッケージに内包されているので、Dockerfile に RUN apt-get install -y xdg-utils
を追加してみたが、docker compose build
コマンド実行時に以下が発生。
E: Failed to fetch http://security.debian.org/debian-security/pool/updates/main/o/openssl/libssl1.1_1.1.0l-1~deb9u4_arm64.deb 404 Not Found [IP: 151.101.2.132 80]
E: Failed to fetch http://security.debian.org/debian-security/pool/updates/main/o/openssl/openssl_1.1.0l-1~deb9u4_arm64.deb 404 Not Found [IP: 151.101.2.132 80]
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
1 error occurred:
* Status: The command '/bin/sh -c apt-get install -y xdg-utils' returned a non-zero code: 100, Code: 100
調べてみると、元としているイメージ node:14.17.0-slim
は、debian の通称 "stretch" (Debian 9) から作られているが、debian の現在の安定版は "buster" (Debian 10) とのこと。
https://www.debian.org/releases/index.ja.html
ついでに node のバージョンもアップデートしたいので、イメージとして node:16.14.2-buster-slim
を選択してみた。
再度 docker compose build
を実行するとエラーは出ず、npm start
で問題なくアプリが起動した。
chrome がインストールできない
Puppeteer を実行するためにはコンテナに chrome をインストール必要があるが、docker compose build
コマンド実行時に以下が発生。
E: Package 'google-chrome-stable' has no installation candidate
現状、arm64 Linux 用の Chrome は存在しない模様。代わりに chromium を使う必要があるとのこと。
https://askubuntu.com/questions/1383789/install-chrome-on-ubuntu-debian-with-arm64
そこで、Dockerfile を以下のように書き換えて、
...
# Install Chrome (only to use for puppeteer)
RUN apt-get install -y chromium chromium-browser
...
再度 docker compose build
コマンド実行すると以下が発生。
E: Package 'chromium-browser' has no installation candidate
これに対して、snap コマンドを使ってインストールする方法がありそうだが、debian で Chromium を動かすことがあまり推奨されていないとのこと。
https://forum.pine64.org/showthread.php?tid=12497
特に Debian であることに拘りも無いため、alpine 版の node に chromium を追加して利用することにした。こちらは以下の追加のみで、pupeteer が問題なく動作した。
FROM node:16.14.2-alpine3.14
RUN apk add chromium
...
変更後のファイル
Docker on Apple Silicon Mac (M1) で動作確認済み。
React / gatsby 用
FROM node:16.14.2-buster-slim
RUN apt-get update \
&& apt-get install -y locales \
&& locale-gen ja_JP.UTF-8 \
&& echo "export LANG=ja_JP.UTF-8" >> ~/.bashrc
# 追加部分
RUN apt-get install -y xdg-utils
RUN apt-get install -y \
wget \
curl \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
Puppeteer 用
# apt系 (Debian) から apk系 (alpine) に全面書き換え
FROM node:16.14.2-alpine3.14
ENV TZ=Asia/Tokyo
ENV LANG=C.UTF-8
RUN apk update \
&& apk add chromium \
&& apk add bash tzdata wget curl