exec ./ClinicApi: no such file or directory from a self-contained .NET app on
an Alpine image, when ls shows the file is there, means the app was published
for linux-x64 (glibc) and Alpine uses musl. Publish with
-r linux-musl-x64 instead.
Changing only the runtime identifier from linux-x64 to
linux-musl-x64 made the same Dockerfile produce an image that started.
The error
PS> docker run --rm --name fix10-dn-m1 fix10-dn-lab-musl
exec ./ClinicApi: no such file or directory
The container exited with code 255.
Why it happens
The Dockerfile published self-contained for linux-x64 and copied the output
onto mcr.microsoft.com/dotnet/runtime:10.0-alpine:
ARG RID=linux-x64
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
ARG RID
WORKDIR /src
COPY ClinicApi.csproj .
RUN dotnet restore -r $RID
COPY Program.cs .
COPY data ./data
RUN dotnet publish -c Release -r $RID --self-contained true -o /out --no-restore
FROM mcr.microsoft.com/dotnet/runtime:10.0-alpine
WORKDIR /app
COPY --from=build /out .
ENTRYPOINT ["./ClinicApi"]
The message is misleading because ./ClinicApi does exist. The
linux-x64 executable contains the path
/lib64/ld-linux-x86-64.so.2 once and no ld-musl string
(grep -c -a in the build stage printed 1 and 0), and on the Alpine image that
path does not exist; /lib holds the musl loader instead:
PS> docker run --rm --name fix10-dn-m3 --entrypoint ls fix10-dn-lab-musl -l /app/ClinicApi /lib64/ld-linux-x86-64.so.2
ls: /lib64/ld-linux-x86-64.so.2: No such file or directory
-rwxr-xr-x 1 root root 78256 Nov 13 05:33 /app/ClinicApi
PS> docker run --rm --name fix10-dn-m4 --entrypoint ls fix10-dn-lab-musl /lib
apk
firmware
ld-musl-x86_64.so.1
libc.musl-x86_64.so.1
modules-load.d
sysctl.d
The output of the failing run is one line, with no .NET text at all: the program never got as far as starting .NET.
The fix
docker build -q -f Dockerfile.musl --build-arg RID=linux-musl-x64 -t fix10-dn-lab-muslfix .
PS> docker run --rm --name fix10-dn-m2 fix10-dn-lab-muslfix
ClinicApi started on .NET 10.0.10
Both images built without an error; the mismatch between the runtime identifier and
the base image showed up only at docker run. The working image reported
.NET 10.0.10, the runtime that went into the self-contained publish, not the 10.0.15 that
the runtime:10.0-alpine base image lists with dotnet --list-runtimes. In your own Dockerfile, write -r linux-musl-x64 on both the restore and the
publish line. The other way out is to keep linux-x64 and change the final
FROM to the Ubuntu-based runtime-deps:10.0; a linux-x64 self-contained
image on that base (fix10-dn-deps-sc, a sibling console app) printed
ClinicApi started on .NET 10.0.10 and Ubuntu 24.04.5 LTS in its
/etc/os-release.
When you meet this message, list the file and the loaders first, as above: if the file
is there and /lib shows only ld-musl, the runtime identifier is
the thing to change, not the COPY line.
How it was reproduced
A console app built on mcr.microsoft.com/dotnet/sdk:10.0 (SDK 10.0.302) with
the Dockerfile above, run on mcr.microsoft.com/dotnet/runtime:10.0-alpine
(Alpine 3.24.4). The failing image was built with docker build -q -f
Dockerfile.musl -t fix10-dn-lab-musl . (the default RID=linux-x64).
Docker engine 29.9.3 on Windows 11.
Frequently asked
- Which runtime identifier do I use for a .NET app on Alpine?
- linux-musl-x64. In the test a linux-x64 self-contained publish failed on runtime:10.0-alpine with exec ./ClinicApi: no such file or directory, and linux-musl-x64 started.
- Why does Docker say no such file or directory when the file exists?
- In this case the linux-x64 executable contained the path /lib64/ld-linux-x86-64.so.2, the Alpine image had no file at that path and only the musl loader in /lib, and the start failed even though ./ClinicApi was in /app.
- Can I run a linux-x64 self-contained .NET app in Docker?
- Yes. A linux-x64 self-contained publish of the same kind of app started on mcr.microsoft.com/dotnet/runtime-deps:10.0, and that image reported Ubuntu 24.04.5 LTS in /etc/os-release.
The self-contained publish on runtime-deps is in exec: "dotnet": executable file not found in $PATH; the same "no such file or directory" wording from Windows line endings in a script is in exec /entrypoint.sh: no such file or directory. More decoded errors in the Fixes category.