I had a docker file that was working fine. However to remote debug it , I read that I needed to install dlv
on it and then I need to run dlv and pass the parameter of the app I am trying to debug. So after installing dlv on it and attempting to run it. I get the error
exec /dlv: no such file or directory
This is the docker file
FROM golang:1.18-alpine AS builder
# Build Delve for debugging
RUN go install github.com/go-delve/delve/cmd/dlv@latest
# Create and change to the app directory.
WORKDIR /app
ENV CGO_ENABLED=0
# Retrieve application dependencies.
COPY go.* ./
RUN go mod download
# Copy local code to the container image.
COPY . ./
# Build the binary.
RUN go build -gcflags="all=-N -l" -o fooapp
# Use the official Debian slim image for a lean production container.
FROM debian:buster-slim
EXPOSE 8000 40000
RUN set -x && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y
ca-certificates &&
rm -rf /var/lib/apt/lists/*
# Copy the binary to the production image from the builder stage.
#COPY --from=builder /app/fooapp /app/fooapp #commented this out
COPY --from=builder /go/bin/dlv /dlv
# Run dlv as pass fooapp as parameter
CMD ["/dlv", "--listen=:40000", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", "/app/fooapp"]
The above results in exec /dlv: no such file or directory
I am not sure why this is happening. Being new to docker , I have tried different ways to debug it. I tried using dive
to check and see if the image has dlv
on it in the path /dlv
and it does. I have also attached an image of it
3
Answers
TL;DR
Run
apt-get install musl
, then/dlv
should work as expected.Explanation
Follow these steps:
docker run -it <image-name> sh
apt-get install file
file /dlv
Then you can see the following output:
The confusing
no such file or directory
(see this question for related discussions) is caused by the missing/lib/ld-musl-x86_64.so.1
.As a result, the solution is to install the
musl
library by following its documentation.My answer is inspired by this answer.
You built
dlv
inalpine
-based distro.dlv
executable is linked againstlibc.musl
:But then you switched to
glibc
-based imagedebian:buster-slim
. That image doesn’t have the required libraries.That’s why you can’t execute
dlv
– the dynamic linker fails to find the proper lib.You need to build in
glibc
-based docker. For example, replace the first lineBTW. After you build you need to run the container in the priviledged mode
In non-priviledged container
dlv
is not allowed to spawn a child process.Really Minimal Image
You use
debian:buster-slim
to minimize the image, it’s size is 80 MB. But if you need a really small image, usebusybox
, it is only 4.86 MB overhead.The image size is 25 MB, of which 18 MB are from
dlv
and 2 MB are fromHello World
application.While choosing the images care should be taken to have the same flavors of
libc
.golang:bullseye
links againstglibc
. Hence, the minimal image must beglibc
-based.But if you want a bit more comfort, use
alpine
withgcompat
package installed. It is a reasonably rich linux with lots of external packages for just extra 6 MB compared tobusybox
.The
no such file or directory
error indicates either your binary file does not exist, or your binary is dynamically linked to a library that does not exist.As said in this answer, delve is linked against libc.musl. So for your delve build, you can disable
CGO
since that can result in dynamic links to libc/libmusl:This even allows you later to use a scratch build for your final target image and does not require you to install any additional packages like
musl
or use anyglibc
based image and require you to run in privileged mode.