Euquid Blog.

WEBエンジニアの技術ブログ。主に個人開発で学んだことの備忘録です。

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

Cover Image for 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-openxdg-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 を選択してみた。

https://hub.docker.com/_/node

再度 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