在docker里如果用 Centos 获取Ubuntu 做基础镜像执行go二进制文件起码200m往上.可以看看大佬这篇文章来学习如果让镜像文件更小:减少go镜像的大小
我们用 alpine 作为基础镜像构建
FROM alpine:3.14
...
alpline 本身5m大小,大大缩减了镜像的体积.
后续 执行 ./ 二进制文件时 出现 ./project no found .这就奇怪了!
这里报的 not found 并不是说找不到这个程序,而是说,程序在运行的时候无法找到需要动态链接的目标文件.
我们都知道,程序编写完毕后需要编译、链接才能运行。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织,最终形成可执行代码的过程。按理来讲,我们的代码变成可执行的程序的时候,需要调用的代码都已经被链接好了,但是这并不完全准确,因为在此时完成的只是静态链接。
所谓静态链接是指把要调用的函数或者过程链接到可执行文件中,成为可执行文件的一部分。静态链接的问题很明显,它会造成空间的浪费和软件更新的困难。举例来说,当有好几个程序调用了相同的系统函数时,每个程序都把这个函数加载到内存里,重复占用了很多空间,造成了资源的浪费。
动态链接解决了这一问题,其基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。
那么问题就出现了,这个动态链接是和系统内置的库相关的。
glibc 和 musl libc
The GNU C Library(glibc) 是当代绝大多数 Linux 发行版内置的 C 标准库实现,而 musl libc 则是一个速度快、轻量化的,严格遵循 POSIX 定义的 C 标准库实现。虽然后者试图保持与 glibc 的兼容性,但两者间的差距始终不小,在使用时难免会遇到兼容性问题。
Alpine 为了简单轻量,没有使用大多数 Linux 发行版使用的 glibc 而选择了 musl libc。 Docker 容器选择了 Alpine 镜像,使用的是 musl libc,所以无法正常动态链接,也就无法运行。
搜到网上这方式可以解决:
RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
mkdir alpine
mkdir echo "" > Dockerfile
Dockerfile:FROM alpine:3.14RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
执行docker build -t myalpine:3.14 .
以该镜像作为基础镜像执行二进制时.依然出现问题!!! 但这次换了其它not found.看来问题还没解决.
看来上面还有其它动态库引用了,并没有完全解决.
Dockerfile:
FROM alpine:3.14
ENV GLIBC_REPO=https://github.com/sgerrand/alpine-pkg-glibc
ENV GLIBC_VERSION=2.30-r0RUN set -ex && \apk --update add libstdc++ curl ca-certificates && \for pkg in glibc-${GLIBC_VERSION} glibc-bin-${GLIBC_VERSION}; \do curl -sSL ${GLIBC_REPO}/releases/download/${GLIBC_VERSION}/${pkg}.apk -o /tmp/${pkg}.apk; done && \apk add --allow-untrusted /tmp/*.apk && \rm -v /tmp/*.apk && \/usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib
重新执行docker build -t myalpine:3.14 . (记得把刚刚构建的删除了)
然后用该镜像去构建你的应用
FROM myalpine:3.14
...
docker run -d -p …
成了!
相比较以前用centos 做基础镜像的 270m往上.现在65m 相对少了一半多.但可能alpine还有以前坑.我还无法得知,不考虑服务器容量的话,直接上centos 或者 Ubuntu吧