Skip to content

❗️Deno FFI Error on Docker (Apple Silicon M1/M2/M3/M4) – Resolution Guide #29596

@im-habib

Description

@im-habib

Version: denoland/deno:2.3.5

🐞 Deno FFI Plugin Load Error in Docker on MacBook M4 Pro

📌 Issue Summary

When running a Deno app using deno-bcrypt in Docker on a MacBook M4 Pro (or any Apple Silicon chip), you may encounter this error:

error: Uncaught (in promise) Error: Could not open library: Could not open library: /deno-dir/plug/https/github.com/f1dff8b6d21e6f91fc972acd4a3ce646b546535da3cabec18138cf42dc67ccc9.so: cannot open shared object file: No such file or directory
⚙️ Background
deno-bcrypt uses FFI with Deno.dlopen() to load .so binaries.

These binaries are not universal; they are compiled for specific architectures.

Your machine uses the ARM64 (aarch64) architecture, but Docker pulls the x86_64 or Linux-only builds by default.

The plugin’s native .so file either:

Doesn't exist for aarch64 in the plugin’s releases

Or, fails to download or install in a compatible format

🧪 How to Reproduce
bash
Always show details

Copy
docker run -it -p 1993:1993 -v $PWD:/app denoland/deno:2.3.5 run --allow-net --allow-ffi --allow-env --allow-read /app/main.ts
Results in:

bash
Always show details

Copy
error: Could not open library: .../github.com/...so: cannot open shared object file: No such file or directory
🔍 Root Cause
deno-bcrypt lacks .so binaries for aarch64 Linux in its GitHub releases.

Deno tries to download one, fails, and doesn’t fall back to build-from-source.

Docker does not persist plugin cache across runs unless mounted explicitly.

Docker image is Linux-based (alpine or debian), which adds complexity when running on macOS ARM chips.

✅ Workarounds
✅ 1. Use Pure JS/TS Hashing Library
Switch to a fallback implementation like:

bcryptjs

argon2-browser

They are slower, but don't depend on FFI and work across all environments.

✅ 2. Custom Docker Image with Cached Plugin Directory
Create a Dockerfile:

Dockerfile
Always show details

Copy
FROM denoland/deno:2.3.5

WORKDIR /app
COPY . .

ENV DENO_DIR=/app/deno-dir

CMD ["run", "--allow-net", "--allow-read", "--allow-env", "--allow-ffi", "main.ts"]
Then run:

bash
Always show details

Copy
docker build -t my-deno-app .
docker run -it -v $PWD:/app my-deno-app
✅ 3. Persist Deno Plugin Cache Using a Volume
Mount the .cache/deno path explicitly:

bash
Always show details

Copy
docker run -it \\
  -v $PWD:/app \\
  -v $HOME/.cache/deno:/deno-dir \\
  -e DENO_DIR=/deno-dir \\
  denoland/deno:2.3.5 run --allow-net --allow-read --allow-env --allow-ffi /app/main.ts
❌ Not Recommended
❌ Expecting Deno to always download a matching .so binary

❌ Using native FFI in a cross-architecture environment without fallback

🧠 Conclusion
This issue is not due to a bug in Docker or Deno itself. It’s a consequence of:

Using native FFI (deno-bcrypt) on an unsupported architecture

Not persisting Deno’s plugin download/cache directory across runs

💡 The best long-term solution is to avoid FFI-dependent libraries unless they offer universal or ARM-compatible builds.

🛠️ Recommendations
Request aarch64-unknown-linux-gnu builds from the plugin maintainer.

Use pure TypeScript libraries unless performance mandates FFI.

Avoid native plugins for apps that need portability across Docker, macOS, or ARM-based servers.
"""

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions