oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
73.47k stars 2.71k forks source link

error: EACCES reading #10331

Closed haovei closed 1 day ago

haovei commented 5 months ago

What version of Bun is running?

1.1.4+fbe2fe0c3

What platform is your computer?

Darwin 23.4.0 arm64 arm

What steps can reproduce the bug?

  1. Install axios

    bun install axios
  2. External axios

    await Bun.build({
    entrypoints: ['./src/index.ts'],
    outdir: './dist',
    target: 'bun',
    external: ['hono', 'axios'],
    });
  3. Docker build

    
    FROM oven/bun:1 AS base

WORKDIR /app

FROM base AS builder COPY . . RUN bun install RUN bun run build

FROM base AS runner COPY --from=builder /app/dist /app/dist COPY --from=builder /app/package.json /app/package.json COPY --from=builder /app/bun.lockb /app/bun.lockb RUN bun install --production

run the app

USER bun EXPOSE 3000/tcp ENTRYPOINT [ "bun", "run", "start" ]


4. Run app error
```shell
> docker run -it 05f120b8296e70
bun ./dist/index.js
error: EACCES reading "/app/node_modules/proxy-from-env/index.js"
error: script "start" exited with code 1

What is the expected behavior?

No response

What do you see instead?

No response

Additional information

The error message is that the proxy-from-env module cannot be read, but this module exists and there is no problem when running locally. View permissions

> ls -lh
total 58
-rw-r-----  2 root  wheel   1.1K  4 17 00:52 LICENSE
-rw-r-----  2 root  wheel   5.1K  4 17 00:52 README.md
-rw-r-----  2 root  wheel   3.3K  4 17 00:52 index.js
-rw-r-----  2 root  wheel   956B  4 17 00:52 package.json
-rw-r-----  2 root  wheel    17K  4 17 00:52 test.js

Bun cannot handle files with read-only permissions

FozzieHi commented 5 months ago

There's definitely a difference of permissions here between npm and bun, with npm being more permissive. I've spun up a Docker container with each, as below.

It's worth noting that this error also happens if you install the package with bun and then run it with node. So I think the issue lies with how bun installs the package and not with how bun runs the project.

bun

FROM docker.io/oven/bun:1-alpine
WORKDIR /app

RUN bun install proxy-from-env
$ ls -l node_modules/proxy-from-env/index.js
-rw-r-----    2 root     root          3348 <snip> node_modules/proxy-from-env/index.js

npm

FROM docker.io/node:21-alpine
WORKDIR /app

RUN npm install proxy-from-env
$ ls -l node_modules/proxy-from-env/index.js
-rw-r--r--    1 root     root          3348 <snip> node_modules/proxy-from-env/index.js
FozzieHi commented 5 months ago

The package tarball actually has the file permissions of -rw-r-----, the same as what bun is saving it as. I'm guessing npm install is changing the file permissions at some point?

Download the tarball with: npm pack proxy-from-env

$ tar -tzvf proxy-from-env-1.1.0.tgz
<snip>
-rw-r----- 0/0            3348 1985-10-26 09:15 package/index.js
<snip>
FozzieHi commented 5 months ago

From my digging, npm install seems to set a fmode of 0o666 and a dmode of 0o777 to extracted files and directories from the tarball. This is done in npm/pacote instead of npm/cli: https://github.com/npm/pacote/blob/066ead20986074a6e6120aeb146bbddc7aec8b2c/lib/fetcher.js#L79

This combined with a umask of 0o022 will result in 0o644 for files, as seen here. I haven't written a single line of Zig before so please correct me if I am wrong, but from an initial search of the codebase and the behaviour outlined here, I don't think bun is applying any sort of default fmode or dmode to extracted files?

haovei commented 5 months ago

The way bun handles file permissions is more direct, directly applying the permissions in the tarball. npm is compatible with this permission issue. My temporary solution to this problem is:

# ...
RUN bun install --production
RUN chmod 644 /app/node_modules/proxy-from-env/

Maybe there is a better way

LolipopJ commented 4 months ago

I follow the official guide and meet the same problem.

...
# copy production dependencies and source code into final image
FROM base AS release
COPY --from=install /temp/prod/node_modules node_modules
...
# run the app
USER bun

For me, I use chown while executing COPY, and it works:

# copy production dependencies and source code into final image
FROM base AS release
COPY --chown=bun:bun --from=install /temp/prod/node_modules node_modules
...
# run the app
USER bun
sunderee commented 3 months ago

I follow the official guide and meet the same problem.

...
# copy production dependencies and source code into final image
FROM base AS release
COPY --from=install /temp/prod/node_modules node_modules
...
# run the app
USER bun

For me, I use chown while executing COPY, and it works:

# copy production dependencies and source code into final image
FROM base AS release
COPY --chown=bun:bun --from=install /temp/prod/node_modules node_modules
...
# run the app
USER bun

Had the same issue. This worked for me. Thank you!

deltamualpha commented 2 months ago

This does appear to be a minor incompatibility with how bun handles node_modules' contents vs npm and yarn. The other toolchains apply uniform file permissions, while bun trusts that the package's creator has given their files a reasonable permission.

Since having to worry about this isn't a norm in the javascript community, there will likely be a decent number of packages that have subtle packaging errors that this surfaces -- I ran into it in a CI context where imbios/bun-node was used to create a node_modules folder (owned by root:root) that subsequent stages in the pipeline, running as different non-root users, couldn't access a specific package that has -rw----r-- file permissions for some reason.

deltamualpha commented 1 day ago

This was closed as completed, but reading through recent commits and changelogs, I don't see a change that would be relevant?