0
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?

Docker + Next.js + Goで開発するときにnext/imageでハマった話

Last updated at Posted at 2025-04-14

こんにちは。最近、Docker上でNext.js(フロントエンド)とGo(バックエンド)を使ってアプリを開発しているのですが、画像表示に使っていた next/image で結構ハマったので、原因と解決方法をまとめておこうと思います。

環境構成

Next.js(フロント): ポート3000

Go(バックエンド): ポート8080

画像: Goサーバー側で /uploads に静的ファイルとして保存

Docker Compose: Next.js と Go をそれぞれ別サービスとして定義

フロントからは、http://localhost:8080/uploads/xxx.jpg のように画像を参照したい状況です。

発生したエラー

Next.js 側の コンポーネントで以下のように画像を表示しようとすると…

<Image
  src="http://localhost:8080/uploads/sample.jpg"
  width={500}
  height={300}
  alt="サンプル画像"
/>

ビルド時、もしくは表示時にこんなエラーが出ました:

Error: Invalid src prop (http://localhost:8080/uploads/xxx.jpg) on `next/image`, hostname "localhost" is not configured under images in your `next.config.js`

原因は next.config.js の images.domains(または remotePatterns)
next/image はセキュリティとパフォーマンスの理由から、外部ホストの画像を使う場合に 事前にホワイトリスト登録が必要です。

これを解決するため、next.config.ts に以下を追加しました:

images: {
  remotePatterns: [
    {
      protocol: 'http',
      hostname: 'localhost',
      port: '8080',
      pathname: '/uploads/**',
    },
  ],
}

これで一旦はOK!…かと思いきや、Docker コンテナ内で Next.js を動かしたら画像が表示されない問題が発生しました。

Docker コンテナにおける localhost の罠

ここが最大のハマりポイントです。

Next.js を Docker コンテナで動かすと、localhost は「コンテナ自身」を指します。つまり:

http://localhost:8080 → frontend コンテナ内の8080ポートを見に行く

でも Go は別の backend コンテナで動いている

よって 接続できない(ECONNREFUSED エラー)

正しい解決方法:ホスト名は backend にする

Docker Compose では、サービス名が内部の DNS 名として解決されるので、
Next.js から Go にアクセスするには http://backend:8080 のように指定する必要があります。

例)next.config.ts

images: {
  remotePatterns: [
    {
      protocol: 'http',
      hostname: 'backend', // ←ここが重要
      port: '8080',
      pathname: '/uploads/**',
    },
  ],
}

そして の src も

<Image
  src="http://backend:8080/uploads/sample.jpg"
  width={500}
  height={300}
  alt="サンプル画像"
/>

ローカルでも動かしたい? → 環境変数で切り替えよう
開発中(Dockerを使わず手元で動かすとき)には localhost でアクセスしたくなることもあります。

その場合は、環境ごとに hostname を切り替えられるようにすると便利です:

.env.local(ローカル開発用)

IMAGE_HOST=localhost

.env.docker(Docker用)

IMAGE_HOST=backend

next.config.ts

const IMAGE_HOST = process.env.IMAGE_HOST || 'localhost';

images: {
  remotePatterns: [
    {
      protocol: 'http',
      hostname: IMAGE_HOST,
      port: '8080',
      pathname: '/uploads/**',
    },
  ],
}

まとめ

状況 使うホスト名
ローカルで開発中(PC) localhost
Docker Compose 環境 backend(サービス名)

おわりに

普段何気なく使っている localhost が、Docker の中では全く違う意味を持つことにあらためて気づかされました。
同じような構成でハマっている人の助けになれば幸いです

※当記事は一部、ChatGPTを参考に執筆しています。

0
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
0
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?