未定义的引用 - Golang CGO 构建失败使用 Docker,但不是在主机上
Undefined References - Golang CGO build fails using Docker, but not on host machine
我正在尝试使用 Go 的 lilliput 库。它仅在 Linux 和 OS X.运行 上制作。
在我的 Linux (Debian 10.3) 主机以及我的 WSL2 设置 (Ubuntu 20.04.1) 上,我 运行 构建我的代码没有问题 (摘录如下)。
// main.go
package main
import (
"github.com/discordapp/lilliput"
)
func main() {
...
decoder, err := lilliput.NewDecoder(data)
...
}
但是,当我尝试将其放入 Docker 容器中时,使用以下配置,它无法构建。
# Dockerfile v1
FROM golang:1.14.4-alpine AS build
RUN apk add build-base
WORKDIR /src
ENV CGO_ENABLED=1
COPY go.mod .
COPY go.sum .
RUN go mod download
COPY . .
RUN go build -o /out/api .
ENTRYPOINT ["/out/api"]
EXPOSE 8080
我已经尝试用不同的方法调整 Docker 文件,例如:
FROM alpine:edge AS build
RUN apk update
RUN apk upgrade
RUN apk add --update go=1.15.3-r0 gcc=10.2.0-r5 g++=10.2.0-r5
WORKDIR /app
RUN go env
ENV GOPATH /app
ADD . /app/src
WORKDIR /app/src
RUN go get -d -v
RUN CGO_ENABLED=1 GOOS=linux go build -o /app/bin/server
FROM alpine:edge
WORKDIR /app
RUN cd /app
COPY --from=build /app/bin/server /app/bin/server
CMD ["bin/server"]
两者都会产生以下构建日志:
为了完整起见,主机的 go env
。
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/kingofdog/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/kingofdog/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/lib/go-1.11"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.11/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/kingofdog/{PROJECT FOLDER}/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build589460337=/tmp/go-build -gno-record-gcc-switches"
我已经在网上搜索过这个错误,但我能找到的都是处理其他人在他们的 Go 项目中导入 C 库的方式的错误。然而,就我而言,我很确定这不是关于源代码的错误,而是 docker 容器的配置错误,因为代码本身在 Docker 之外工作得很好而且我不能'在 lilliput 存储库中找到类似的问题。
你建立依赖了吗?
您必须 运行 脚本才能在 Linux 上构建依赖项。
脚本:https://github.com/discord/lilliput/blob/master/deps/build-deps-linux.sh
他们的文档提到:
Building Dependencies
Go does not provide any mechanism for arbitrary building of dependencies, e.g. invoking make or cmake. In order to make lilliput usable as a standard Go package, prebuilt static libraries have been provided for all of lilliput's dependencies on Linux and OSX. In order to automate this process, lilliput ships with build scripts alongside compressed archives of the sources of its dependencies. These build scripts are provided for OSX and Linux.
如果它仍然失败,那么问题可能与 glibc-musl
有关,因为 alpine 图像具有 musl libc
而不是 glibc
(GNU 的 libc)。所以,你可以试试 Ubuntu/ CentOS/etc。最少的图像或找到一种方法 glibc
在 alpine 上。
alpine
docker 图像是简约的 Linux 版本 - 使用 musl-libc 而不是 glibc
- 通常用于构建小图像。
要获得更多功能 glibc
- 并解决您缺少的 CGO
依赖项 - 使用 golang
Docker 映像的 non-alpine 版本来构建您的资产:
#FROM golang:1.14.4-alpine AS build
#RUN apk add build-base
FROM golang:1.14.4 AS build
我正在尝试使用 Go 的 lilliput 库。它仅在 Linux 和 OS X.运行 上制作。
在我的 Linux (Debian 10.3) 主机以及我的 WSL2 设置 (Ubuntu 20.04.1) 上,我 运行 构建我的代码没有问题 (摘录如下)。
// main.go
package main
import (
"github.com/discordapp/lilliput"
)
func main() {
...
decoder, err := lilliput.NewDecoder(data)
...
}
但是,当我尝试将其放入 Docker 容器中时,使用以下配置,它无法构建。
# Dockerfile v1
FROM golang:1.14.4-alpine AS build
RUN apk add build-base
WORKDIR /src
ENV CGO_ENABLED=1
COPY go.mod .
COPY go.sum .
RUN go mod download
COPY . .
RUN go build -o /out/api .
ENTRYPOINT ["/out/api"]
EXPOSE 8080
我已经尝试用不同的方法调整 Docker 文件,例如:
FROM alpine:edge AS build
RUN apk update
RUN apk upgrade
RUN apk add --update go=1.15.3-r0 gcc=10.2.0-r5 g++=10.2.0-r5
WORKDIR /app
RUN go env
ENV GOPATH /app
ADD . /app/src
WORKDIR /app/src
RUN go get -d -v
RUN CGO_ENABLED=1 GOOS=linux go build -o /app/bin/server
FROM alpine:edge
WORKDIR /app
RUN cd /app
COPY --from=build /app/bin/server /app/bin/server
CMD ["bin/server"]
两者都会产生以下构建日志:
为了完整起见,主机的 go env
。
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/kingofdog/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/kingofdog/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/lib/go-1.11"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.11/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/kingofdog/{PROJECT FOLDER}/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build589460337=/tmp/go-build -gno-record-gcc-switches"
我已经在网上搜索过这个错误,但我能找到的都是处理其他人在他们的 Go 项目中导入 C 库的方式的错误。然而,就我而言,我很确定这不是关于源代码的错误,而是 docker 容器的配置错误,因为代码本身在 Docker 之外工作得很好而且我不能'在 lilliput 存储库中找到类似的问题。
你建立依赖了吗?
您必须 运行 脚本才能在 Linux 上构建依赖项。 脚本:https://github.com/discord/lilliput/blob/master/deps/build-deps-linux.sh
他们的文档提到:
Building Dependencies
Go does not provide any mechanism for arbitrary building of dependencies, e.g. invoking make or cmake. In order to make lilliput usable as a standard Go package, prebuilt static libraries have been provided for all of lilliput's dependencies on Linux and OSX. In order to automate this process, lilliput ships with build scripts alongside compressed archives of the sources of its dependencies. These build scripts are provided for OSX and Linux.
如果它仍然失败,那么问题可能与 glibc-musl
有关,因为 alpine 图像具有 musl libc
而不是 glibc
(GNU 的 libc)。所以,你可以试试 Ubuntu/ CentOS/etc。最少的图像或找到一种方法 glibc
在 alpine 上。
alpine
docker 图像是简约的 Linux 版本 - 使用 musl-libc 而不是 glibc
- 通常用于构建小图像。
要获得更多功能 glibc
- 并解决您缺少的 CGO
依赖项 - 使用 golang
Docker 映像的 non-alpine 版本来构建您的资产:
#FROM golang:1.14.4-alpine AS build
#RUN apk add build-base
FROM golang:1.14.4 AS build