vercel / next.js

The React Framework
https://nextjs.org
MIT License
125.95k stars 26.87k forks source link

Can not remove /out directory when building a docker image for the project. #59988

Open samialitop3 opened 9 months ago

samialitop3 commented 9 months ago

Link to the code that reproduces this issue

https://github.com/samialitop3/next.js

To Reproduce

Create a new next.js project using npx create-next-app@latest Add output: "export" to next.config.js. Make sure to have docker installed. Run the following command docker run --rm --mount type=bind,source='/Users/administrator/my-test-app/src',destination='/src',readonly --mount type=bind,source='/Users/administrator/my-test-app/public',destination='/public',readonly --mount type=bind,source='/Users/administrator/my-test-app/package.json',destination='/package.json',readonly --mount type=bind,source='/Users/administrator/my-test-app/package-lock.json',destination='/package-lock.json' --mount type=bind,source='/Users/administrator/my-test-app/next.config.js',destination='/next.config.js',readonly --mount type=bind,source='/Users/administrator/my-test-app/tsconfig.json',destination='/tsconfig.json',readonly --mount type=bind,source='/Users/administrator/my-test-app/.next',destination='/.next' --mount type=bind,source='/Users/administrator/my-test-app/out',destination='/out' node:20-alpine3.18 /bin/sh -c 'npm install && npm run build'

Current vs. Expected behavior

Following the steps from the previous section: Expected behavior: Successful static export as the images below. image image

Current Behavior: Getting an error for not being able to remove /out directory. [Error: EBUSY: resource busy or locked, rmdir '/out'] { errno: -16, code: 'EBUSY', syscall: 'rmdir', path: '/out' }```

image

Verify canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.2.0: Wed Nov 15 21:59:33 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T8112
Binaries:
  Node: 20.9.0
  npm: 10.1.0
  Yarn: 1.22.21
  pnpm: 8.13.1
Relevant Packages:
  next: 14.0.5-canary.29
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.1.3
Next.js Config:
  output: export

Which area(s) are affected? (Select all that apply)

Static HTML Export (output: "export")

Additional context

While trying to build a docker image for my next.js v14 project, I am using docker mounts to be able to generate the static files of the project using output: 'export' inside docker container, the only issue is that when binding the mount /out in docker and running yarn build in the docker run command, it is not possible to have next build command removing /out folder and its contents because it is mounted into docker.

desnor commented 8 months ago

I am also having this issue when the build is run in buildkite using docker.

Dockerfile contents

FROM node:18-bullseye-slim

COPY package.json package-lock.json .npmrc ./
RUN npm ci
COPY . ./

CMD ["npm", "run", "build"]

Scripts in buildkite that run build in docker:

 - "docker build -t my-app ."
 - "docker run -v $$PWD/out:/out my-app"

Build output:

▲ Next.js 14.1.0
--
  | - Environments: .env
  | - Experiments (use at your own risk):
  | · typedRoutes
  |  
  | Creating an optimized production build ...
  | ✓ Compiled successfully
  | Linting and checking validity of types ...
  | Collecting page data ...
  | Generating static pages (0/8) ...
  | Generating static pages (2/8)
  | Generating static pages (4/8)
  | Generating static pages (6/8)
  | ✓ Generating static pages (8/8)
  | Finalizing page optimization ...
  | Collecting build traces ...
  |  
  | > Build error occurred
  | [Error: EBUSY: resource busy or locked, rmdir '/out'] {
  | errno: -16,
  | code: 'EBUSY',
  | syscall: 'rmdir',
  | path: '/out'
  | }
  | 🚨 Error: The command exited with status 1
desnor commented 8 months ago

@samialitop3 what affect does your change to comment out the call to remove the directory do? does it work ok once deployed without removing it?

// await fs.rm(outDir, { recursive: true, force: true })

zorrobiwan commented 5 months ago

also have the same issue

a workaround is to execute a script which execute the export in a specific directory which is not the volume and then copy the files in the volume once files generated

mrclay commented 4 months ago

Easier workaround: Configure distDir to a subdirectory of the volume so it doesn't try to delete the volume's root in the container.

BTW, since my team only ran into this recently, my guess is this is not a Next bug but a new (and sensible) limitation of docker volumes. But Next could work around it by deleting all the contents instead of recreating it.

samialitop3 commented 4 months ago

Since I am using a series of commands to automate the build of my Next.js project, my solution was to run the container without --rm and give the container a name, this will keep the container in docker without removing it, then I use docker cp to copy the contents of the out folder to the directory I need then delete the docker container.