容器化部署应用变得越来越便捷,遵循一个docker容器运行一个应用或者进程的原则,追求便捷的同时,容器镜像的大小也是我们应该关注的地方,一个镜像动辄近1G
的大小 例如一些ubuntu
和centos
的基础镜像 不是我们想要看到的 所以就引出了alpine的基础镜像 可以最大程度上精简我们的镜像大小,当然具体还有好多方法精简 这个建议看下google
的一个dockerfile最佳实践
的文档,这边就不岔开话题
这里只针对在使用alpine基础镜像过程中碰到的注意事项,记录下
alpine 默认使用的软件仓库地址服务器在国外,导致在docker build阶段安装软件会比较慢
这里就需要我们根据国内的网络环境替换成国内的软件仓库地址
解决方法:使用国内的软件包镜像,比如 https://mirrors.ustc.edu.cn 的镜像:
RUN sed -i 's!http://dl-cdn.alpinelinux.org/!https://mirrors.ustc.edu.cn/!g' /etc/apk/repositories
/usr/local/go/lib/time/zoneinfo
文件解决方法:安装 tzdata
这个包
RUN apk update && apk --no-cache add tzdata && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
ENV TZ Asia/Shanghai
There’s no glibc package ported by alpine linux officially, and for such java libraries depending on some c/c++ JNI libraries (.so) we should install the glibc package on alpine linux beacuse of the dependencies of such JNI libs.
使用动态链接方式编译了一个使用了 GLIBC
库的程序生成的,但是 alpine
镜像中没有 GLIBC
库而是用的 MUSL LIBC
库,这样就会导致该二进制文件无法被执行。
解决方法:
GLIBC
(比如编译 Go 程序的时候指定 CGO_ENABLED=0
) 或者在 alpine 中编译一个依赖 MUSL LIBC
的版本gnu libc
的镜像ENV LANG=C.UTF-8
RUN ALPINE_GLIBC_BASE_URL="https://github.com/sgerrand/alpine-pkg-glibc/releases/download" && \
ALPINE_GLIBC_PACKAGE_VERSION="2.31-r0" && \
ALPINE_GLIBC_BASE_PACKAGE_FILENAME="glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
ALPINE_GLIBC_BIN_PACKAGE_FILENAME="glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
ALPINE_GLIBC_I18N_PACKAGE_FILENAME="glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
apk add --no-cache --virtual=.build-dependencies wget ca-certificates && \
wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \
wget \
"$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
apk add --no-cache \
"$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
\
rm "/etc/apk/keys/sgerrand.rsa.pub" && \
/usr/glibc-compat/bin/localedef --force --inputfile POSIX --charmap UTF-8 "$LANG" || true && \
echo "export LANG=$LANG" > /etc/profile.d/locale.sh && \
\
apk del glibc-i18n && \
\
rm "/root/.wget-hsts" && \
apk del .build-dependencies && \
rm \
"$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
https
服务时提示证书问题:x509: certificate signed by unknown authority
Go 程序使用 alpine 作为基础镜像时有时可能会遇到程序中访问 https
服务时会提示证书问题 x509: certificate signed by unknown authority
解决方法:安装 CA 证书
RUN apk add --no-cache ca-certificates && \
update-ca-certificates
alpine并发解析A
和AAAA
记录,造成netfilter race
alpine 使用的底层 c 库是 musl libc
,其它镜像基本都是 glibc
alpine 优先通过DNS解析而不走本地hosts文件,/etc/nsswitch.conf
可以控制,但看有问题的 pod 里没有这个文件。然后观察到有问题的 pod 用的 alpine 镜像,试试其它镜像后发现只有基于 alpine 的镜像才会有这个问题。
解决方法:
gnu libc
的镜像 cgo (CGO_ENABLED=0)
,并告诉链接器要静态链接 (go build
后面加 -ldflags '-d'
),但这需要语言和编译工具支持才可以nsswitch.conf
文件 (可以用 hostPath)参考文档:
https://blog.quentin-machu.fr/2018/06/24/5-15s-dns-lookups-on-kubernetes/
https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
https://segmentfault.com/a/1190000021572045
https://imroc.io/posts/troubleshooting-with-kubernetes-network/