next.js: Another Memory Leak in `next/image`

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 22.2.0: Fri Nov 11 02:03:51 PST 2022; root:xnu-8792.61.2~4/RELEASE_ARM64_T6000 Binaries: Node: 19.0.1 npm: 9.2.0 Yarn: 1.22.19 pnpm: 7.21.0 Relevant packages: next: 13.1.1 eslint-config-next: 13.1.1 react: 18.2.0 react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

Image optimization (next/image, next/legacy/image)

Link to the code that reproduces this issue

https://github.com/jaunruh/next-image-test

To Reproduce

Set up docker image:

  • docker build --no-cache -t next-test .
  • docker run -p 3000:3000 --name next-test next-test

Surf the app:

  • open browser at localhost:3000
  • scroll the home page and the project pages randomly
  • use the Resource usage extension to monitor the memory usage
  • see the memory only increase and never decrease

Describe the Bug

The apps memory usage only ever increases and never really decreases anymore. On docker I have easily managed to pass 1gb in memory usage. The app was run on digitalocean as a bare nodejs app and as a docker container locally and in digitalocean. The memory usage in digitalocean (1 CPU, 512mb memory) looks as follows, but can also be reproduced with docker:

image

In the provided repo there are also commented-out image tags. As soon as these are used the problem disappears.

Expected Behavior

No continuous memory increase.

Which browser are you using? (if relevant)

All major browsers

How are you deploying your application? (if relevant)

docker run and build

NEXT-2023

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 17
  • Comments: 18 (2 by maintainers)

Commits related to this issue

Most upvoted comments

image

Persist in 13.4.7.

Three solutions worked:

  1. add to next.config.js
images: {
 unoptimized: true
},
  1. Change all next.js <Image> to <img>
  2. Add to all next.js <Image> param unoptimized

image

Generally using unoptimized images seems to fix the memory leak. But well, the images are unoptimized… so I still think this is a bug that needs to be fixed.

The memory leak seems to only be present when running in ubuntu:jammy base image (glibc).

I don’t see the memory leak when using the the recommended node:18-alpine base image (musl).

This is likely related to sharp and documented here:

I am seeing similar in 13.4.1.

Deployed a small website to Digital Ocean that uses RSC and Image. There’s maybe 50 mid-size images total in this entire web-site.

In the screenshot, after the black line is after image optimisation disabled in config. The other dips in the graph before that point are due to server restarts.

image

As per a warning in the NextJS documentation I am using jemalloc in my deployment.

I have the same issue with using nextjs Image. I am using nextjs 13.1.1 and docker container will be killed. my question is that if the solution is setting the images unoptimized, so is there still any benefit of using nextjs Image instead of usual Html img?

The memory leak persists on node 18 alpine, here’s the scenario for new nextjs app:

  1. Create nextjs-latest app
  2. Take a large image (~10MB for my case) and put it into public folder
  3. Render that image with next/image on home page
  4. deploy this to docker with node:18.20-alpine
  5. Open home page - this will cause a memory spike to ~2GB. After a bit it will fall to ~1GB and stay there
  6. Open the page in incognito tab and keep refreshing the main tab and the incognito - this will cause a second memory spike and memory usage will remain that way. A handy demo in case it’s needed: https://github.com/art-alexeyenko/next-image-oom

And some memory usage trends from my local tests with Docker Desktop: image

I have seen this option. I am going to try it in my repo. But even if it solves the memory leak problem, it creates the issue of unoptimized images. I can then just use a general <img/> tag instead. No need for next/image anymore.