I'm encountering an issue while trying to run a Docker container. I build a image from Dockerfile:
docker build -t server -f ./backend/Dockerfile .
Run it:
docker run -it -p 8081:8081 server
Getting an error:
exec /app/backend/server: no such file or directory
When I go to check from Docker Desktop, then inside the container I see the file exists and is created to that location as it should be.
I also tried changing the second stage FROM golang:1.21-alpine but still getting same error.
With FROM gcr.io/distroless/base-debian11 I am getting:
/app/backend/server: /lib/aarch64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by /app/backend/server)
/app/backend/server: /lib/aarch64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /app/backend/server)
/app/backend/server: /lib/aarch64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /app/backend/server)
I looked here, here and tried many things. I'm relatively new to Docker, and I'm not sure how to troubleshoot this issue. Can someone please help me understand what might be causing this error and how to resolve it? Thanks in advance!
My Dockerfile below:
# Stage 1: Building the application
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . ./
RUN apt-get update && apt-get install -y sqlite3 libsqlite3-dev
RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -o /app/backend/server ./backend/backend.go
# Stage 2: Production stage using Alpine
FROM alpine:latest
RUN apk --no-cache add ca-certificates sqlite
COPY ./backend/configs/config /app/configs/config
COPY ./database/sqlite/schema.sql /app/database/sqlite/schema.sql
COPY ./tls/server.crt /tls/server.crt
COPY ./tls/server.key /tls/server.key
COPY --from=builder /app/backend/server /app/backend/server
EXPOSE 8081
ENTRYPOINT ["/app/backend/server"]
I replicated your issue with a simplified dockerfile and app (please try to provide minimal, reproducible, examples - I had to guess which sqlite lib you are using):
backend.go:
package main
import (
"database/sql"
"log"
"os"
_ "github.com/mattn/go-sqlite3"
)
func main() {
os.Remove("./foo.db")
db, err := sql.Open("sqlite3", "./foo.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
sqlStmt := `
create table foo (id integer not null primary key, name text);
delete from foo;
`
_, err = db.Exec(sqlStmt)
if err != nil {
log.Printf("%q: %s\n", err, sqlStmt)
return
}
}
dockerfile:
# Stage 1: Building the application
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . ./
RUN apt-get update && apt-get install -y sqlite3 libsqlite3-dev
RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -o /app/server
# Stage 2: Production stage using Alpine
FROM alpine:latest
RUN apk --no-cache add ca-certificates sqlite
COPY --from=builder /app/server /app/server
EXPOSE 8081
ENTRYPOINT ["/app/server"]
Starting a shell in the container (docker run -it --entrypoint /bin/sh server) we can see that the executable is there, the permissions are fine, but it does not run:
/ # ls -al /app/server
-rwxr-xr-x 1 root root 6816280 Sep 22 02:29 /app/server
/ # /app/server
/bin/sh: /app/server: not found
/ # ldd /app/server
/lib64/ld-linux-x86-64.so.2 (0x7ff8cb4ba000)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7ff8cb4ba000)
Error relocating /app/server: fcntl64: symbol not found
It's easy to read the error "not found" and think it must be due to the file not being where you expect, or having incorrect permissions. However, the same error is displayed when something the executable depends upon is missing. ldd shows the issue - the executable is relying upon fcntl64; this library is provided by glibc but not musl (as used in Alpine - incompatibilities between glibc and musl are not uncommon).
The simplest solution is to compile the app with the same OS as you will run it on:
# Stage 1: Building the application
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . ./
RUN apk --no-cache add gcc g++ sqlite
RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -o /app/server
# Stage 2: Production stage using Alpine
FROM alpine:latest
RUN apk --no-cache add ca-certificates sqlite
COPY --from=builder /app/server /app/server
EXPOSE 8081
ENTRYPOINT ["/app/server"]
And run this (my executable has no output but I confirm that the database has been created):
/ # ls -al /app/server
-rwxr-xr-x 1 root root 6838120 Sep 22 02:39 /app/server
/ # /app/server
/ # ldd /app/server
/lib/ld-musl-x86_64.so.1 (0x7fabcb701000)
libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7fabcb701000)
/ # ls -al ./foo.db
-rw-r--r-- 1 root root 8192 Sep 22 02:40 ./foo.db
An alternative option is to use a pure go library (removing the need for CGO).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With