Joe Blog

前言

容器化部署应用变得越来越便捷,遵循一个docker容器运行一个应用或者进程的原则,追求便捷的同时,容器镜像的大小也是我们应该关注的地方,一个镜像动辄近1G的大小 例如一些ubuntucentos的基础镜像 不是我们想要看到的 所以就引出了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

执行二进制文件执行时却提示 not found 或 no such file

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 库,这样就会导致该二进制文件无法被执行。

解决方法:

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

DNS解析异常

alpine并发解析AAAAA记录,造成netfilter race

alpine 使用的底层 c 库是 musl libc,其它镜像基本都是 glibc

alpine 优先通过DNS解析而不走本地hosts文件,/etc/nsswitch.conf 可以控制,但看有问题的 pod 里没有这个文件。然后观察到有问题的 pod 用的 alpine 镜像,试试其它镜像后发现只有基于 alpine 的镜像才会有这个问题。

解决方法:

参考文档:

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/