我在try 运行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进行判断时,在容器内我看到该文件存在,并按其应有的位置创建到该位置.

我也try 更改第二阶段FROM golang:1.21-alpine,但仍然出现相同的错误.

加上FROM 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岁,try 了很多东西.我对Docker比较陌生,我不确定如何解决这个问题.谁能帮我了解一下这个错误可能是什么原因以及如何解决它?提前谢谢!

我的文档文件如下:

# 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和应用程序复制了您的问题(请try 提供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"]

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

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

很容易读到错误"Not Found",并认为这一定是由于文件不在您预期的位置,或者具有错误的权限.但是,当可执行文件所依赖的内容丢失时,也会显示相同的错误.ldd显示了这个问题--可执行文件依赖于fcntl64;这个库是由glibc提供的,而不是musl(正如在阿尔卑斯山中使用的那样--glibcmusl之间的不兼容性是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

另一种 Select 是使用pure go library(不需要CGO).

Linux相关问答推荐

抛出主,即未捕获到SIGSEGV中的异常结果

获取Perl文件::Tail开始在最后流传输文件

BASH-SCRIPT-在特定行合并两个文件

Linux和Windows x86程序集调用约定

Git在某些文件中添加回车符,尽管autocrlf已关闭

加载ELF64头文件为什么会导致分段错误?

如何使用netcat为DPDK实例提供输入?

如何更改文件的上次访问/修改/更改日期?

使用 awk 将多行文本转换为 CSV

在 bash 中查找匹配多个模式的文件

在不调试的情况下查找哪个汇编指令导致了非法指令错误

argv的编码是什么?

为什么在编译 K&R2 第 1 章中最长的行示例时出现getline 的类型冲突错误?

如何在 Linux 中使用命令行将 PDF 转换为 JPG?

仅在不存在时添加换行符

将 $_GET 参数传递给 cron 作业(job)

bash shell 脚本函数定义(如f () {})中使用的括号是什么?它与使用function关键字不同吗?

在 Linux 中的特定行向文件添加文本

CentOS:在 PHP 安装中启用 GD 支持

构建窗口管理器