Dockerビルド時にnpm installが失敗する問題の原因と解決策
DockerでNode.jsアプリのイメージビルド中にnpm installでEAI_AGAINエラーになる場合の問題点・原因・対応策です。
問題点:Dockerビルド中のnpm installがDNSエラーで失敗する
Dockerfile内でRUN npm installを実行すると、以下のようなエラーが発生してビルドが止まるケースがあります。
npm error code EAI_AGAIN
npm error syscall getaddrinfo
npm error errno EAI_AGAIN
npm error request to <https://registry.npmjs.org/mediasoup> failed, reason: getaddrinfo EAI_AGAIN registry.npmjs.org
一方で、ビルド時にnpm installをスキップし、できあがったイメージから起動したコンテナ内で手動実行すると問題なく成功します。
これは一見するとネットワークが通っているように見えますが、ビルド時の環境に特有の問題が潜んでいます。
原因:ビルド時のコンテナネットワーク設定とDNS解決の違い
Dockerイメージのビルド中は、一時的に生成される中間コンテナ上でRUNコマンドが実行されます。
この中間コンテナは、起動後のコンテナとは異なるネットワーク設定を持つため、DNS名前解決に失敗することがあります。
具体的には、ビルド時の中間コンテナはDockerデーモンのデフォルトDNS設定を使いますが、環境によってはDNSキャッシュの不整合や名前解決のタイムアウトが発生し、EAI_AGAINのような一時的エラーを引き起こします。
つまり、ビルド時のネットワーク環境と起動後のネットワーク環境でDNSの挙動が異なることが根本原因です。
対応策:docker-composeでbuild時にnetwork: hostを指定してDNS問題を回避する
この問題を解決する方法は、ビルド時のネットワーク設定をホストのネットワークに切り替えることです。
具体的には、docker-compose.ymlのbuildセクションに以下のようにnetwork: hostを追記します。
services:
app:
build:
context: .
network: host
これにより、ビルド時の中間コンテナがホストのネットワーク設定を共有し、DNS名前解決の失敗を回避します。
補足:その他のDNSトラブル対策
- DockerデーモンのDNS設定を見直す
/etc/docker/daemon.jsonにGoogle DNS(8.8.8.8など)を指定し、Dockerを再起動する方法を試す - ビルドと起動を分けて管理する
docker build --network=hostで事前にビルドしてからdocker-compose upで起動する - ビルド時の
npm installを起動後に移行する
ビルド時の環境依存を避けるため、コンテナ起動後にnpm installを実行する
まとめ
Dockerビルド時にnpm installがDNSエラーで失敗するのは、中間コンテナのネットワーク設定が起動後のコンテナと異なることが主な原因です。
docker-compose.ymlでbuild.network: hostを指定することで、ホストのネットワークを利用してDNS問題を回避できます。
