linux - Docker运行错误: exec/app/backend/server: no such file or directory

标签 linux docker go

我在尝试运行 Docker 容器时遇到问题。我从 Dockerfile 构建了一个镜像:

docker build -t server -f ./backend/Dockerfile .   

运行它:

docker run -it -p 8081:8081 server

出现错误:

exec /app/backend/server: no such file or directory

当我从 Docker Desktop 进行检查时,我会在容器内看到该文件存在,并且已按照应有的位置创建到该位置。

我还尝试更改第二阶段FROM golang:1.21-alpine,但仍然遇到相同的错误。

随着来自 gcr.io/distroless/base-debian11 我得到:

/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)

我看了here , here并尝试了很多事情。我对 Docker 比较陌生,不知道如何解决这个问题。有人可以帮助我了解可能导致此错误的原因以及如何解决它吗?提前致谢!

下面是我的 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/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"]

最佳答案

我使用简化的 dockerfile 和应用程序复制了您的问题(请尝试提供 minimal, reproducible, examples - 我不得不猜测您正在使用哪个 sqlite 库):

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"]

在容器中启动一个shell(docker run -it --entrypoint/bin/sh server)我们可以看到可执行文件在那里,权限很好,但它不运行:

/ # 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

很容易看到错误“未找到”,并认为这一定是由于文件不在您期望的位置,或者权限不正确。但是,当可执行文件所依赖的内容丢失时,会显示相同的错误。 ldd 显示问题 - 可执行文件依赖于 fcntl64 ;该库由 glibc 提供,但不是 musl 提供(如 Alpine 中使用的 - glibc 和 musl 之间的不兼容性为 not uncommon )。

最简单的解决方案是使用与运行应用程序相同的操作系统来编译应用程序:

# 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"]

然后运行这个(我的可执行文件没有输出,但我确认数据库已创建):

/ # 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

另一种选择是使用 pure go library(无需 CGO)。

关于linux - Docker运行错误: exec/app/backend/server: no such file or directory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77151610/

相关文章:

linux - 无法从源代码安装git

c - 进程阻塞了哪些调用?

azure - Docker 托管的 Azure Function 无法与事件网格链接

linux - 使用 sed 替换具有匹配模式的行

linux - Linux下文件格式的改变

docker - 具有多个 LoadBalancer 服务的 Kubernetes (docker-desktop)

docker - 如何知道公证服务器的Docker客户端位置?

go - 如何创建包装容器/list.List 的 golang 结构?

go - 如何在 go/goa 框架中正确弃用 API 端点?

go - golang中如何获取当前主机的唯一标识?