如何制作基于alpine的jdk基础镜像

715 阅读2分钟

思考

制作出的镜像尽可能小

  • 基础镜像使用alpine,包含最基本的命令,满足日常维护需求.
  • 使用Server JRE代替JDK,官方精简版,据称可以减少40%程序文件.

应用以非root用户运行

  • 在基础镜像中创建应用运行时普通账号以及目录,本例中为 appuser用户和 /srv 目录.

需要解决应用时区问题

  • 本例中使用环境变量 TZ=Asia/Shanghai 设置java运行时使用时区.

需要支持中文字符集

  • 安装glibc-i18n,支持中文字符集.

其他考量

  • 安装tini以便支持在使用其作为entrypoint,以便处理僵尸进程和信号转发.
  • 同时制作最小运行环境和最小编译环境镜像,同时支持编译环境和运行环境.

步骤

  1. 从 www.oracle.com/java/techno… 下载Server JRE,这里使用的是 server-jre-8u202-linux-x64.tar.gz
  2. 编写dockerfile
FROM docker.io/library/alpine:3.16@sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e457f36f271ab1acc53015037c

RUN echo "https://mirrors.tuna.tsinghua.edu.cn/alpine/v3.16/main" > /etc/apk/repositories \
    && echo "https://mirrors.tuna.tsinghua.edu.cn/alpine/v3.16/community" >> /etc/apk/repositories \
    && adduser -D appuser && chown -R appuser.appuser /srv \
    && apk add tini \
    && apk add --virtual=.build-dependencies ca-certificates \
    && wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub \
    && wget -q -O /tmp/glibc-2.34-r0.apk https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.34-r0/glibc-2.34-r0.apk \
    && wget -q -O /tmp/glibc-bin-2.34-r0.apk https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.34-r0/glibc-bin-2.34-r0.apk \
    && wget -q -O /tmp/glibc-i18n-2.34-r0.apk https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.34-r0/glibc-i18n-2.34-r0.apk \
    && apk add /tmp/glibc-2.34-r0.apk /tmp/glibc-bin-2.34-r0.apk /tmp/glibc-i18n-2.34-r0.apk \
    && /usr/glibc-compat/bin/localedef -c -i POSIX -f UTF-8 C.UTF-8 || true \
    && rm -rf /etc/apk/keys/sgerrand.rsa.pub && apk del glibc-i18n && apk del .build-dependencies \
    && rm -rf /var/cache/* && rm -rf /var/lib/apk/* && rm -rf /tmp/*

ARG BIN_HOME

ADD ./$BIN_HOME /usr/local/share/$BIN_HOME

ENV LANG=C.UTF-8 TZ=Asia/Shanghai PATH=/usr/local/share/$BIN_HOME/bin:$PATH
  1. 编写编译脚本build.sh
#!/usr/bin/env bash
set -ex
cd $(dirname "$0")

JRE_TAR=server-jre-8u202-linux-x64.tar.gz    #调整为下载的Server JRE包名称
JRE_DIR=jdk1.8.0_202                         #调整为Server JRE解压后JDK所在目录名称

rm -rf ./${JRE_DIR} ./jre                    # 清理以前文件

tar -xvzf ./${JRE_TAR}
cp -r ./${JRE_DIR}/jre ./
                                             # 思考? 如何添加一些版本信息,这里暂时不处理
docker build --network=host --no-cache -t fakerepo/library/jre-alpine:$(date '+%Y%m%d') --build-arg BIN_HOME=jre ./

docker build --network=host --no-cache -t fakerepo/library/jdk-alpine:$(date '+%Y%m%d') --build-arg BIN_HOME=${JRE_DIR} ./

rm -rf ./${JRE_DIR} ./jre                    # 清理文件
  1. 执行 sh ./build.sh

其他

  • 本例中Server JRE代替JDK,部分java拓展,例如JavaFx无法使用.
  • 如果遇到无法加载类库问题,可以尝试安装alpine对应的package解决,例如ffmpeg无法使用,在安装libstdc++后解决.
  • 制作过程中alpine版本和glibc版本需要对应,否则镜像制作会失败.
  • 合理利用JAVA_TOOL_OPTIONS和_JAVA_OPTIONS指定运行时参数.

参考

www.alpinelinux.org

github.com/sgerrand/al…

github.com/krallin/tin…

blogs.oracle.com/java/post/u…