はじめに
Next.jsで開発したアプリケーションをAWS AppRunnerにデプロイする際、Docker環境特有の問題に遭遇しました。
ローカル環境では正常に動作していたPrismaのマイグレーションが、Dockerコンテナ内では以下のエラーで失敗する現象です。
Error: Cannot find module '@prisma/engines'
これはコンテナ起動時に実行されるprisma migrate deploy
コマンドで発生しており、
以下の点を確認してましたが、問題は見つかりませんでした。
- package.jsonの依存関係に
@prisma/engines
が正しく記載されているか - ローカルのnode_modules内に該当モジュールが存在するか
- Dockerfileの記述に明らかな誤りがないか
- ビルドプロセスでエラーが発生していないか
最終的に、この問題の原因はpnpmパッケージマネージャーのシンボリックリンク構造とDockerのファイルコピー処理の相性問題にあることがわかりました。
解決にかなり時間がかかってしまったので、同じ問題を抱えている方の参考になればと思い、原因と具体的な解決方法をまとめてみました。
プロジェクト構成
- Next.js v14.2.28
- Prisma v5.3.0
- pnpm v8.15.5
- Node.js v20.11.0
- Docker(AWS AppRunner向けにlinux/amd64でビルド)
問題:「Cannot find module '@prisma/engines'」エラー
エラーの発生状況
Docker環境でprisma migrate deploy
を実行すると:
Error: Cannot find module '@prisma/engines'
原因:node_modulesの部分的なコピー
当初のDockerfileでは、イメージサイズを削減しようと、必要最小限のnode_modulesだけをコピーしていた:
# ❌ 問題のあるコピー方法
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/prisma ./node_modules/prisma
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/@prisma ./node_modules/@prisma
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/.bin ./node_modules/.bin
なぜこの方法では動かないのか?
pnpmのシンボリックリンク構造
pnpmは効率的なnode_modules構造を作るためシンボリックリンクを多用しており、今回のような部分的なコピーではこれらのリンクが壊れてしまっていたようです。
node_modules/
├── .pnpm/
│ └── @prisma+engines@5.3.0/
│ └── node_modules/
│ └── @prisma/
│ └── engines/
└── @prisma/
└── engines -> ../.pnpm/@prisma+engines@5.3.0/node_modules/@prisma/engines
解決方法:node_modules全体をコピーする
# ✅ 解決方法:node_modules全体をコピー
COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nextjs:nodejs /app/prisma ./prisma