← 전체 글로 돌아가기

Docker

Docker로 띄운 Next.js에서 이미지 최적화가 안 될 때

Next.js Image 컴포넌트는 요청 시점에 서버에서 이미지를 처리하는데, Docker 환경에서는 sharp 패키지와 환경변수 설정이 맞지 않으면 제대로 동작하지 않는다.

Next.js <Image>는 빌드 시점이 아니라 요청 시점에 이미지를 리사이즈하고 WebP로 변환한다. 이 처리가 서버에서 일어나기 때문에 Docker 환경 설정에 따라 동작이 달라진다.

sharp 패키지 아키텍처 문제

Next.js 이미지 최적화는 내부적으로 sharp 패키지를 쓴다. 로컬 macOS에서 npm installsharp는 Alpine Linux 기반 Docker 이미지에서 동작하지 않는다. CPU 아키텍처와 libc 차이 때문이다.

docker logs --tail=100 서비스이름 2>&1 | grep -i sharp

에러가 있으면 Dockerfile에서 플랫폼을 명시해서 설치해야 한다.

RUN npm install --platform=linux --arch=x64 sharp

또는 멀티스테이지 빌드에서 npm ci --omit=dev 후 sharp만 따로 추가한다.

컨테이너 상태와 이미지 태그 확인

docker ps
docker inspect 서비스이름

이미지 태그가 :latest면 이전 캐시된 이미지가 실행 중일 수 있다. 명시적인 버전 태그나 다이제스트를 써야 새 빌드가 반영됐는지 확신할 수 있다. docker logs --tail=100 서비스이름으로 시작 시점 에러도 확인한다.

외부 이미지 도메인 허용

외부 URL 이미지를 <Image src="https://..." />로 쓰려면 next.config.js에 허용 도메인을 명시해야 한다.

// next.config.js
module.exports = {
  images: {
    remotePatterns: [
      { protocol: 'https', hostname: 'cdn.example.com' },
    ],
  },
};

이 설정은 빌드 시점에 번들에 포함되므로 환경변수가 아니라 설정 파일에 직접 써야 한다.

standalone 출력 모드

module.exports = {
  output: 'standalone',
};

Docker 환경에서는 standalone 출력 모드를 쓰면 불필요한 파일 없이 이미지 크기를 줄일 수 있다. 이 모드에서는 public/ 폴더와 .next/static/을 Dockerfile에서 따로 복사해야 한다. 빠뜨리면 정적 파일이 안 나온다.

이미지 최적화가 계속 안 되고 원본 크기 그대로 서빙된다면 next.config.jsunoptimized: true가 설정돼 있지 않은지도 확인한다.