1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS App Runner + Next.js standaloneでヘルスチェックが通らない問題の原因と解決策

Last updated at Posted at 2025-12-11

はじめに

AWS App RunnerでNext.js(standaloneモード)をデプロイしようとしたところ、ヘルスチェックが通らずサービス作成に失敗する問題に遭遇しました。

ローカルのDockerでは正常に動作するのに、App Runnerでは失敗する。この謎を「なぜなぜ分析」で解明し、解決した記録です。

環境

  • Next.js 16.0.7(standalone出力モード)
  • Node.js 20 Alpine
  • AWS App Runner(東京リージョン)

症状

App Runnerコンソールでの表示

作成に失敗 three-sisters-portal
Health check failed on protocol TCP [Port: '8080']

CloudWatch Logsでのアプリケーションログ

▲ Next.js 16.0.7
- Local:   http://ip-10-0-104-219.ap-northeast-1.compute.internal:8080
- Network: http://ip-10-0-104-219.ap-northeast-1.compute.internal:8080
✓ Starting...
✓ Ready in 151ms

一見、正常に起動しているように見えます。

ローカルDockerでのログ

▲ Next.js 16.0.7
- Local:   http://localhost:8080
- Network: http://0.0.0.0:8080
✓ Starting...
✓ Ready in 63ms

違いに気づきましたか?

問題の原因:なぜなぜ分析

5つのなぜ

  1. なぜヘルスチェックが失敗?
    → ポート8080へのTCP接続ができない

  2. なぜ接続できない?
    → Next.jsが0.0.0.0ではなく、内部ホスト名(ip-10-0-104-219...)にバインドしている

  3. なぜ内部ホスト名にバインド?
    → Next.js standaloneのserver.jsHOSTNAME環境変数を参照してバインドアドレスを決定する

  4. なぜHOSTNAMEが内部ホスト名になっている?
    → App Runnerがコンテナ起動時にHOSTNAME環境変数を自動設定している

  5. 根本原因
    App Runnerの仕様。コンテナオーケストレーターは一般的にHOSTNAMEを内部ネットワークのホスト名で設定する

Dockerfileの罠

最初のDockerfile:

ENV HOSTNAME="0.0.0.0"
ENV PORT=8080

CMD ["node", "server.js"]

ENVHOSTNAMEを設定しても、App Runnerが実行時に上書きするため意味がありません。

解決策の比較

方法 確実性 理由
Dockerfile内でENV HOSTNAME="0.0.0.0" x App Runnerが実行時に上書き
App Runner環境変数でHOSTNAME=0.0.0.0設定 App Runnerが後から上書きする可能性
起動スクリプトで強制設定 CMD実行時に再設定するため確実

解決策:CMDでHOSTNAMEを強制設定

# NG: App Runnerに上書きされる
CMD ["node", "server.js"]

# OK: シェル経由でHOSTNAMEを強制設定
CMD ["sh", "-c", "HOSTNAME=0.0.0.0 node server.js"]

なぜこれで動くのか?

  1. コンテナ起動時、App RunnerがHOSTNAMEを内部ホスト名に設定
  2. CMDが実行される
  3. sh -cにより、その場でHOSTNAME=0.0.0.0が環境変数として設定
  4. node server.jsは新しいHOSTNAME=0.0.0.0を参照
  5. Next.jsが0.0.0.0:8080にバインド
  6. ヘルスチェック成功!

完全なDockerfile

FROM node:20-alpine AS base

# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json pnpm-lock.yaml* ./
RUN corepack enable pnpm && pnpm i --frozen-lockfile || pnpm i

# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN corepack enable pnpm && pnpm run build

# Production image
FROM base AS runner
WORKDIR /app

ENV NODE_ENV=production
ENV PORT=8080

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public
RUN mkdir .next
RUN chown nextjs:nodejs .next

COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 8080

# ポイント: HOSTNAMEを強制設定してからnode起動
CMD ["sh", "-c", "HOSTNAME=0.0.0.0 node server.js"]

next.config.mjsの設定

standalone出力を有効にするために必要:

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',
}

export default nextConfig

App Runner設定

{
  "instanceConfiguration": {
    "cpu": "1024",
    "memory": "2048"
  },
  "healthCheckConfiguration": {
    "protocol": "TCP",
    "port": "8080",
    "interval": 10,
    "timeout": 5,
    "healthyThreshold": 1,
    "unhealthyThreshold": 5
  }
}

教訓

  1. Next.js standaloneモードはHOSTNAME環境変数に依存する
  2. コンテナオーケストレーター(App Runner, ECS, K8s等)はHOSTNAMEを自動設定することがある
  3. DockerfileのENVは実行時に上書きされる可能性がある
  4. 確実な方法は、CMDでシェル経由で環境変数を設定すること

他のプラットフォームでも要注意

この問題はApp Runner固有ではありません。以下のプラットフォームでも同様の注意が必要です:

  • AWS ECS / Fargate
  • Google Cloud Run
  • Azure Container Apps
  • Kubernetes

コンテナオーケストレーターを使う場合は、HOSTNAME環境変数の挙動を確認しましょう。

まとめ

「ローカルでは動くのに本番で動かない」という典型的なハマりパターンでしたが、なぜなぜ分析で根本原因を特定できました。

ログのNetwork: http://0.0.0.0:8080Network: http://ip-10-0-xxx...:8080の違いに気づけたのが解決の鍵でした。

同じ問題でハマっている方の参考になれば幸いです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?