在 docker 容器之间传输时缺少 stdlib 符号

Missing stdlib symbols when transfering between docker containers

本文关键字:stdlib 符号 传输 docker 之间      更新时间:2023-10-16

我正在使用 docker 使用 g++ 编译C++项目,并且在使用多阶段 dockerfile 时遇到了一个奇怪的情况。我已将其缩减为一个小测试用例

FROM alpine:3 AS build
RUN apk add g++
COPY main.cpp main.cpp
RUN g++ main.cpp
FROM alpine:3 AS run
# RUN apk add g++ # Uncommenting this line will make it work for me
COPY --from=build /a.out /a.out
ENTRYPOINT ["/a.out"]

和我的C++程序:

#include<iostream>
int main(void) {
std::cout << "Hello world!" << std::endl;
return 0;
}

我注意到当我只用这个 main.cpp 和 Dockerfile 在容器将正确构建的文件夹中运行docker build .时,但它将无法运行(通过docker run CONTAINER_HASH(报告有关缺少符号的错误,ala:

Error relocating /a.out: _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc: symbol not found
...
Error relocating /a.out: _ZSt4cout: symbol not found

我截断了输出,保留了我认为在我的示例程序中可能会有所帮助的行。

重新生成第二个容器并安装g++可以解决此问题。

这对我来说暗示了一个事实:

  • iostream(可能还有其他C++标准库组件(是动态链接的。事实果真如此吗?是否有一个信誉良好的位置(也许是C++标准网站(来查找该列表?这些动态库是否位于文件系统中合理可预测的位置?

  • 有没有办法强制g++静态链接我需要的标准库?我的目标是使我的最终映像尽可能小,并且不安装所有g++会很好......

这将解决您的问题:

g++ -static -static-libstdc++ main.cpp

默认情况下,g++ 链接针对共享版本:

当 g++ 程序用于链接C++程序时,它通常 自动链接到 libstdc++。如果 libstdc++ 可用作 共享库,并且不使用 -static 选项,则此链接 针对 libstdc++ 的共享版本。这通常没问题。 但是,有时冻结版本很有用 程序使用的libstdc++,而没有一直到完全 静态链接。-static-libstdc++ 选项将 g++ 驱动程序定向到 静态链接libstdc++,而不必链接其他库 静态。